OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 23210|回复: 56

写点 u8 KEY_Scan(u8 mode) 按键扫描函数的分析。老鸟就别笑我了

  [复制链接]

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2014-11-11
在线时间
5 小时
发表于 2016-9-2 20:10:23 | 显示全部楼层 |阅读模式
本帖最后由 若不俗和inide 于 2016-9-2 20:10 编辑

最近身边的很多同学都在学习原子哥的STM32视频,我发现他们都看不懂原子哥里面按键扫描程序。由于问的人多,所以我也写了个心得,分享一下,老鸟别喷我哈。先贴上代码吧:

//返回值:
//0,没有任何按键按下
//KEY0_PRES,KEY0按下
//KEY1_PRES,KEY1按下
//WKUP_PRES,WK_UP按下
//注意此函数有响应优先级,KEY0>KEY1>WK_UP!!


u8 KEY_Scan(u8 mode)      //mode:0,不支持连续按;   1,支持连续按;
{         
        static u8 key_up=1;//按键按松开标志  //flga
        if(mode==1)   {key_up=1;}     
        if(key_up==1 &&(KEY0==0||KEY1==0||WK_UP==1)) //如果有一个按键按下
        {
                delay_ms(10);//去抖动
                key_up=0;
                if(KEY0==0)     return KEY0_PRES;
                else if(KEY1==0)return KEY1_PRES;
                else if(WK_UP==1)return WKUP_PRES;
        }
        else if(KEY0==1&&KEY1==1&&WK_UP==0)
        {key_up=1;}
        return 0;// 无按键按下
}
首先必须搞懂static这个关键字,用这个关键字定义的变量,其值会保存,下次再执行这个函数的时候。不会被初始化。也就是说有点类似与全局变量,值是会保存上一次赋值过后的值。
下面我们一句一句来分析代码。
首先我们假设将mode =1,设置成支持连续按下。同时假设KEY0按下。
1. static u8 key_up=1;
2. if(mode==1)   {key_up=1;}    来一个判断语句,如果mode==1 ,那么全程key_up=1。
3.if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1)) ,由于key_up=1,假设按键key0又按下了。所以if语句成立。执行括号里面的内容。并且返回按键按下的值
4. 先消抖, key_up=0;  注意注意 重点来  key_up=0;    由于我们前面有一个判断语句 if(mode==1)   {key_up=1;}     所以key_up=0; 之后,瞬间  key_up又等于1了。
5. 假设此时key0按键按着没有松开,所以KEY0==0,由于第4步所说的,key_up=0之后的瞬间  key_up又等于1了。
6.所以此时此刻,if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1)) 又成立了,又执行括号里面的内容。并且返回按键按下的值。如此循环下去,达到长按效果。
7. 假设你此时将按键松开。自己想后面的吧。。。讲得够详细了。。。。。


假设mode=0,设置成不支持长按。同时假设KEY0按下。
1. static u8 key_up=1;
2. if(mode==1)   {key_up=1;}    这句话直接变成没有的语句了。  if(0==1)   {key_up=1;}   0怎么可能等于1???
3.3.if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1)) ,由于key_up=1,假设按键key0又按下了。所以if语句成立。执行括号里面的内容。并且返回按键按下的值
4. 先消抖, key_up=0;  接着判断哪个按键按下,返回按键按下的值。
5.此时如果你还按着按键,也不会有作用了。 if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1))   因为此时key_up=0;  if语句不成立了。
6.当你一松开手,马上进入        else if(KEY0==1&&KEY1==1&&WK_UP==0)   {key_up=1;}    当 按键都没有按下,{key_up=1;}   key_up又被重新刷新了,又等于1了。
7.当你再次按下按键key0的时候,if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1)) 又成立了。又再次进入循环体。  实现了单次按键的效果






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2017-1-24
在线时间
8 小时
发表于 2017-1-30 21:23:27 | 显示全部楼层
本帖最后由 xiaochu312 于 2017-1-30 22:49 编辑

LZ,支持连续按键的分析不对。

1. static u8 key_up=1;(mode=1,这句不会运行了
2. if(mode==1)   {key_up=1;}    来一个判断语句,如果mode==1 ,那么全程key_up=1。(key_up不会全程等于1)
3.if(key_flag==1 &&(KEY0==0||KEY1==0||WK_UP==1)) ,由于key_up=1,假设按键key0又按下了。所以if语句成立。执行括号里面的内容。并且返回按键按下的值
4. 先消抖, key_up=0;  注意注意 重点来  key_up=0;    由于我们前面有一个判断语句 if(mode==1)   {key_up=1;}     所以key_up=0; 之后,瞬间  key_up又等于1了。(这里严重解释错误,应该是:延时消抖后,key_up=0,key_up重新赋值后的确是等于0了,不会发生瞬间  key_up又等于1这样的事情
5. 假设此时key0按键按着没有松开,所以KEY0==0,由于第4步所说的,key_up=0之后的瞬间  key_up又等于1了。(5.按键按着没有松开,main()程序继续调用KEY_Scan(1)按键扫描程序,由于mode=1,所以if(mode)key_up=1;
6.所以此时此刻,if(key_up==1 &&(KEY0==0||KEY1==0||WK_UP==1)) 又成立了,又执行括号里面的内容。并且返回按键按下的值。如此循环下去,达到长按效果。


回复 支持 10 反对 0

使用道具 举报

8

主题

21

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2017-5-25
在线时间
20 小时
发表于 2017-5-26 07:53:34 | 显示全部楼层
void KEY_Init(void);//IO初始化
u8 KEY_Scan(u8);  //按键扫描函数
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下
//4,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1;  //支持连按  
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY0==0)return 1;
else if(KEY1==0)return 2;
else if(KEY2==0)return 3;
else if(KEY3==1)return 4;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1;     
return 0;// 无按键按下
}
函数解读:
一、mode=0时,按键不支持连按,程序运行过程,主函数中,按键扫描,首先默认为key_up=1,因为从开机,到函数运行速度是极快的,因此会扫描到无按键按下。当然,有一种特殊的情况是,在起机时,就按下按键,此时key_up=0,估计少有人去做这么蛋疼的事吧!
一切准备就绪,程序开始运行,如有按键按下,执行到if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))
此时,key_up=0,函数返回一个u8型数(0||1||2||3||4),如按键不松开,key_up=0,if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))语句永远不会执行,只有按键松开,执行else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1,因此实现了按键不连按的效果!当然,此时,或许会有人想,如果,我按一下键,赶紧再按一下,不就永远不会执行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))里的语句了么,我想说的是,你多虑了,我现在所用的是芯片是72MHZ的,代码执行的间距仅仅几毫秒,人的反应速度还没那么快呢,(注:一般条件下,反应时间约为0.1~0.5 s。对于复杂的选择性反应时间达1~3 s,要进行复杂判断和认识的反应时间平均达3~5 s,具体的带有判别的反应时间t可用下式求得: t = k log2 (n+1)   式中,k为常数;n为等概率出现的选择对象数;(n+1)是考虑判明是否出现刺激。)即是低一点的芯片也是没问题的。
二、mode=1时,初始化和mode=0是一样,上面提到,在这里就不再说了,直接看代码,函数在主函数中循环,若有按键按下,运行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1)),此时key_up=0;不丢开按键,主函数循环到按键扫面函数,执行if(mode)key_up=1;之后,若有按键按下,当然可以运行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))里的语句了。至此,实现了连续按键。
三、这个函数的封装性极强,换句话说,即是不懂这个函数里的意思,也可以直接拿来运用,当然函数应当这样描述:
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下
//4,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
u8 t;
t=KEY_Scan(0);
switch(t)
{
   case 1:
   case 2:
   case 3:
   case 4:
}
函数的整体设计确实很吸引人,如果将函数的扫描放在中断里,将大大节省内存,从而可以提高程序运行速率!
    在这儿不得不再次提到一些高级语言,比如C#,VB,Java等等,个人觉得这些高级语言也许正和上面的这个函数有点相像,封装性太强,尤其C#,感觉一种很飘渺的感觉,说实在的起初还可以,时间久了便腻了!我觉得编程人员不是为编程而编程,而是从编程中去寻找乐趣,寻求一种自由!
    所以,正如这个函数,如果只是调用,太简单了,但是如果你了解了这个的设计过程,那么你就是成功地!当然,若想获得更好,懂得底层驱动,甚至,芯片的驱动原理,呵呵,便最好不过了!
    《易经》:“易有太极,是生两仪,两仪生四象,四象生八卦。”孔颖达疏:“太极谓天地未分之前,元气混而为一,即是太初、太一也。”
     由于时间仓促及水平有限,难免有些差错和不足,希望读者多多指教!
     高手勿喷,在此谢过代码的设计者!
回复 支持 9 反对 0

使用道具 举报

0

主题

21

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2016-8-16
在线时间
32 小时
发表于 2016-9-3 11:29:39 | 显示全部楼层
有时候分享并不是为了给别人看,而是给自己一个总结,看看自己学到哪个地步
回复 支持 2 反对 0

使用道具 举报

24

主题

107

帖子

0

精华

初级会员

Rank: 2

积分
141
金钱
141
注册时间
2014-3-29
在线时间
63 小时
发表于 2016-10-15 20:35:23 | 显示全部楼层
本来自己都有点想明白了,经过楼主一分析,又有点乱了,我想静静
回复 支持 1 反对 0

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2017-8-13
在线时间
5 小时
发表于 2017-8-17 20:19:06 | 显示全部楼层
我觉得那个key_up=0是不是应该放在return KEY_VALUE的前面???
回复 支持 1 反对 0

使用道具 举报

26

主题

280

帖子

1

精华

高级会员

Rank: 4

积分
908
金钱
908
注册时间
2013-8-2
在线时间
279 小时
发表于 2016-12-20 22:08:45 | 显示全部楼层
赞LZ,做了两个模式可选这个不错。
给楼主一个建议:多花些时间在代码可读性上,尽量让使用代码的人操作傻瓜化。
我也有写过按键的,跟LZ交流。
《STM8L之自定义长短按键》:http://blog.csdn.net/feilusia/article/details/53154346
博客:http://blog.csdn.net/feilusia
CC2541群(127442605);CC2640群(557278427);
Android群(541462902);STM8/STM32群(164311667);
Linux群(512598061);职场交流群(450154342);
回复 支持 1 反对 0

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
发表于 2017-2-24 13:34:28 | 显示全部楼层
xiaochu312 发表于 2017-2-24 12:58
不是的,你去看看static关键字的说明,static u8 key_up=1,初始化后 key_up会一直=1,而且只初始化一次 ...

是这么回事~~
亦余心之所善,
虽九死其犹未悔。
回复 支持 0 反对 1

使用道具 举报

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2014-11-11
在线时间
5 小时
 楼主| 发表于 2016-9-2 20:10:24 | 显示全部楼层
本帖最后由 若不俗和inide 于 2016-9-2 20:15 编辑

  写了这么多 希望 刚玩32的朋友们能看懂。。。我终于明白为什么很多大神都不太愿意码字分享了。  因为这真的有点耗费个人的时间,但我还是花了点时间来写。希望刚开始玩的朋友们别被STM32的第二个按键程序(第一个程序LED灯成)就吓到看不懂了。特别是刚开始玩的朋友,很多东西,看不懂不要怕,程序嘛,赋值上去,一步一步来分析。 我相信只要用心都能有收获
回复 支持 反对

使用道具 举报

3

主题

177

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1604
金钱
1604
注册时间
2016-1-28
在线时间
265 小时
发表于 2016-9-2 20:37:11 | 显示全部楼层
回复 支持 反对

使用道具 举报

4

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2014-11-11
在线时间
5 小时
 楼主| 发表于 2016-9-3 23:20:08 | 显示全部楼层
PPlucky 发表于 2016-9-3 11:29
有时候分享并不是为了给别人看,而是给自己一个总结,看看自己学到哪个地步

回复 支持 反对

使用道具 举报

12

主题

336

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1576
金钱
1576
注册时间
2015-8-9
在线时间
625 小时
发表于 2016-9-4 10:32:59 | 显示全部楼层
同意4楼观点
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-13
在线时间
18 小时
发表于 2016-9-22 16:31:31 | 显示全部楼层
很好啊,谢谢你,我现在看懂了点,非常感谢哦,加油啊大神
回复 支持 反对

使用道具 举报

1

主题

5

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2015-9-10
在线时间
51 小时
发表于 2016-10-12 09:45:32 | 显示全部楼层
分析的很仔细,可以让看不懂的朋友学习一下,支持楼主
回复 支持 反对

使用道具 举报

2

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
105
金钱
105
注册时间
2015-3-5
在线时间
8 小时
发表于 2016-10-16 15:20:33 | 显示全部楼层
哈哈哈,看了楼上的回复我想笑了。

还是要为楼主的精神点赞。
回复 支持 反对

使用道具 举报

10

主题

172

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1479
金钱
1479
注册时间
2016-1-25
在线时间
260 小时
发表于 2016-10-16 15:21:26 | 显示全部楼层
make 学习了哈 ,原本也是一直有点懵逼的说
回复 支持 反对

使用道具 举报

20

主题

143

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2015-8-28
在线时间
108 小时
发表于 2016-12-14 17:36:51 | 显示全部楼层
厉害了
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2016-12-14
在线时间
0 小时
发表于 2016-12-14 21:03:01 | 显示全部楼层
4. 先消抖, key_up=0;  注意注意 重点来  key_up=0;    由于我们前面有一个判断语句 if(mode==1)   {key_up=1;}     所以key_up=0; 之后,瞬间  key_up又等于1了。这一步为什么因为判断句 if(mode==1)  所以key_up=0呀???为什么key_up永远是???
回复 支持 反对

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
28
金钱
28
注册时间
2020-5-2
在线时间
7 小时
发表于 2016-12-20 14:32:23 | 显示全部楼层
现在懂了,谢谢
回复 支持 反对

使用道具 举报

8

主题

39

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
225
金钱
225
注册时间
2016-12-14
在线时间
33 小时
发表于 2016-12-20 19:23:40 | 显示全部楼层
感谢大神
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2016-12-20
在线时间
0 小时
发表于 2016-12-20 19:36:50 | 显示全部楼层
本帖最后由 燕永辉 于 2016-12-20 19:38 编辑

函数名里u8起什么作用?  u8不是红外接收头吗
回复 支持 反对

使用道具 举报

26

主题

280

帖子

1

精华

高级会员

Rank: 4

积分
908
金钱
908
注册时间
2013-8-2
在线时间
279 小时
发表于 2016-12-20 21:58:46 | 显示全部楼层
燕永辉 发表于 2016-12-20 19:36
函数名里u8起什么作用?  u8不是红外接收头吗

#define u8    unsigned char
博客:http://blog.csdn.net/feilusia
CC2541群(127442605);CC2640群(557278427);
Android群(541462902);STM8/STM32群(164311667);
Linux群(512598061);职场交流群(450154342);
回复 支持 反对

使用道具 举报

4

主题

15

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2016-10-8
在线时间
6 小时
发表于 2017-1-31 16:13:42 | 显示全部楼层
为什么我使用原子的模式1出现的是错的现象
回复 支持 反对

使用道具 举报

7

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-2-23
在线时间
24 小时
发表于 2017-2-23 17:45:33 | 显示全部楼层
wgyashin 发表于 2016-12-14 21:03
4. 先消抖, key_up=0;  注意注意 重点来  key_up=0;    由于我们前面有一个判断语句 if(mode==1)   {key_u ...

因为mode是1,就算在if函数里面key_up被赋成0,在if(mode)这个函数里也会被赋成1,所以它永远都是1
回复 支持 反对

使用道具 举报

7

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
158
金钱
158
注册时间
2017-2-23
在线时间
24 小时
发表于 2017-2-23 22:53:54 | 显示全部楼层
LINKMessi 发表于 2017-1-31 16:13
为什么我使用原子的模式1出现的是错的现象

什么模式一
回复 支持 反对

使用道具 举报

8

主题

145

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
462
金钱
462
注册时间
2016-12-14
在线时间
75 小时
发表于 2017-2-24 08:27:27 | 显示全部楼层
楼主精神可嘉,学习了。。。。
书山有路勤为径,学海无涯苦作舟!
回复 支持 反对

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
发表于 2017-2-24 08:46:54 | 显示全部楼层
xiaochu312 发表于 2017-1-30 21:23
LZ,支持连续按键的分析不对。

1. static u8 key_up=1;(mode=1,这句不会运行 ...

是不是static关键字主要是作用于mode=0,让key_up=0用于下一次按键检测
亦余心之所善,
虽九死其犹未悔。
回复 支持 反对

使用道具 举报

16

主题

78

帖子

0

精华

初级会员

Rank: 2

积分
81
金钱
81
注册时间
2016-12-19
在线时间
50 小时
发表于 2017-2-24 12:42:55 | 显示全部楼层
非常感谢楼主,这个程序看了半天都是似懂非懂,现在明白了。~~~~
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2017-1-24
在线时间
8 小时
发表于 2017-2-24 12:58:30 | 显示全部楼层
南有乔木 发表于 2017-2-24 08:46
是不是static关键字主要是作用于mode=0,让key_up=0用于下一次按键检测

不是的,你去看看static关键字的说明,static u8 key_up=1,初始化后 key_up会一直=1,而且只初始化一次,mode=1的话就是一直让key_up==1,有按键按下之后,软件key_up=0;当再次调用扫描函数时,不会再运行static u8 key_up=1,这条语句,你软件仿真一下就明白了
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-13
在线时间
18 小时
发表于 2017-3-8 11:23:57 | 显示全部楼层
xiaochu312 发表于 2017-1-30 21:23
LZ,支持连续按键的分析不对。

1. static u8 key_up=1;(mode=1,这句不会运行 ...

我同意你的观点
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
63
金钱
63
注册时间
2016-7-13
在线时间
18 小时
发表于 2017-3-8 11:25:28 | 显示全部楼层
楼主,19楼分析的队,你看下,如果你觉得对就该下你的贴咯,怕有些人没看下面的回复就误导了。谢谢咯,好人一生平安
回复 支持 反对

使用道具 举报

4

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2017-3-12
在线时间
13 小时
发表于 2017-3-12 10:43:01 | 显示全部楼层
本帖最后由 dczjn 于 2017-3-12 11:18 编辑

u8 KEY_Scan(u8 mode)的参数mode,有哪条语句可判断mode是0或1
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-3-17
在线时间
3 小时
发表于 2017-3-17 15:23:27 | 显示全部楼层
dczjn 发表于 2017-3-12 10:43
u8 KEY_Scan(u8 mode)的参数mode,有哪条语句可判断mode是0或1

和你有相同的疑问,mode初始好像一直就是0,而且不能赋值。不知道你现在有没有解决这个问题?
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-3-17
在线时间
3 小时
发表于 2017-3-17 15:44:23 | 显示全部楼层
dczjn 发表于 2017-3-12 10:43
u8 KEY_Scan(u8 mode)的参数mode,有哪条语句可判断mode是0或1

我刚问了下师傅,解决了,主函数里调用的这个函数有赋值一个0过来,你可以看看。
回复 支持 反对

使用道具 举报

4

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
83
金钱
83
注册时间
2017-3-12
在线时间
13 小时
发表于 2017-3-23 21:40:15 | 显示全部楼层
是的,对的我仔细分析主函数,有赋值
回复 支持 反对

使用道具 举报

2

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2018-4-14
在线时间
10 小时
发表于 2017-5-3 00:30:07 来自手机 | 显示全部楼层
厉害。受教了,不过我还是不太明白主函数的switch(t)
回复 支持 反对

使用道具 举报

2

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
133
金钱
133
注册时间
2017-4-10
在线时间
28 小时
发表于 2017-5-3 09:32:13 | 显示全部楼层
谢谢楼主分享,小白学习了。
回复 支持 反对

使用道具 举报

4

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2017-4-24
在线时间
44 小时
发表于 2017-5-9 11:00:09 | 显示全部楼层
其实有算法流程框图就好了,更容易看懂,走流程
回复 支持 反对

使用道具 举报

4

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2017-4-24
在线时间
44 小时
发表于 2017-5-9 11:02:47 | 显示全部楼层
Yejia 发表于 2017-5-3 00:30
厉害。受教了,不过我还是不太明白主函数的switch(t)

switch是为了保持主函数的简洁性,为了你以后添加输入可以直接在主函数的switch下主函数添加,在key.c中在详细写
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2017-7-5
在线时间
4 小时
发表于 2017-7-14 15:28:25 | 显示全部楼层
38楼说的很对,static这个关键字定义的变量仅仅是再次进入函数时不会被执行初始化,然而它被赋值为零的时候还是会被赋值为零。并不是全程一直就是初始化的值,这点楼主需要注意一下。
回复 支持 反对

使用道具 举报

1

主题

21

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2017-6-29
在线时间
11 小时
发表于 2017-7-14 21:44:17 | 显示全部楼层
还是很感谢楼主的辛苦付出
回复 支持 反对

使用道具 举报

10

主题

232

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2288
金钱
2288
注册时间
2012-8-24
在线时间
247 小时
发表于 2017-8-17 22:52:40 | 显示全部楼层
每个人分析的不错,受教了
单片机技术交流请加127034610
回复 支持 反对

使用道具 举报

14

主题

76

帖子

0

精华

初级会员

Rank: 2

积分
77
金钱
77
注册时间
2017-8-16
在线时间
37 小时
发表于 2017-8-21 13:46:57 | 显示全部楼层
这个程序要怎么移植啊 比如用在别的按键上
回复 支持 反对

使用道具 举报

14

主题

76

帖子

0

精华

初级会员

Rank: 2

积分
77
金钱
77
注册时间
2017-8-16
在线时间
37 小时
发表于 2017-8-21 13:54:48 | 显示全部楼层
u8  key_scan(u8 mode)
{
      static u8 key_up= 1;//按键松开标志
      if (mode) key_up=1;//支持连按
       if(key_up&&key_1==0||key_2==0)
       {
         Delay(0xff);//去抖动
         key_up=0;
         if(key_1==0)  return  key_double;
         else if(key_2==0)  return key_thirple;
       }
       else if (key_1==1&&key_2==1)  key_up=1;
       return 0;//无按键按下
  }
       unsigned char key_driver(void)
       {
         static unsigned char key_state = key_state_0, key_time = 0;
         unsigned char key_press,key_press1, key_return = N_key;//N_key等于0
         key_press=key_1;
         key_press1=key_2;
         switch(key_state)
                {
                case  key_state_0:
                  if(!key_press) key_state = key_state_1;
                 break;
                case key_state_1:
                   if(!key_press)
                   {  
                     key_time = 0;
                     key_state = key_state_2;
                   }
                  else
                     key_state = key_state_0;
                   break;   
                 case key_state_2:
                 if(key_press)
                 {
                      key_return=S_key;//按键释放,单击操作,返回s_key
                      key_state = key_state_0;
                 }
                   else if(++key_time >= 100)
                        {
                                key_return = L_key;//按下时间为1000ms,长按操作
                                key_state = key_state_3;
                        }
                    break;
                case key_state_3://等待按键释放状态,此状态只返回无按键时间
                     if(key_press)   key_state = key_state_0;//按键已释放,转换到初始按键状态     
                     break;
        }
        return key_return;
}
/*对于长键,按下1s后马上响应,反应最快
  对于单键,第2次按键释放后马上得到反应
  对于单键,释放后延时拖后500ms后才能响应,反应最慢*/
unsigned char key_read(void)
{
        static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return=N_key,key_temp;
       key_temp=key_driver();
   
        switch(key_m)
        {
        case key_state_0:
               
                        if(key_temp == S_key)
                        {
                                key_time_1 = 0;//第一次单击 不返回,到下个状态判断后面是否有出现双击
                               key_m= key_state_1;
                        }
                        else
                        
                                key_return = key_temp;
                         break;
                case   key_state_1:
               
                        if(key_temp == S_key)//又一次单击(间隔小于500ms)
                        {
                                key_return = D_key;//返回双击事件,回初始状态
                                key_m= key_state_0;
                        }
                        else
                        {      
                          if(++key_time_1>=30)//这里返回的都是无键事件
                        {
                           key_return = S_key;
                           key_m = key_state_0;
                        }
                }
                break;
        }
        return key_return;
                }  

这个程序要怎么移植啊  里面那个KEY_PRESS=KEY_1,一次只能判断一个按键,如果我想加多一个按键呢  求大佬赐教
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2018-9-8
在线时间
8 小时
发表于 2018-11-1 19:14:41 | 显示全部楼层
那设置的KEY_UP有什么用呢
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2018-9-8
在线时间
8 小时
发表于 2018-11-1 19:36:42 | 显示全部楼层
        static u8 key_up=1;//°′¼ü°′Ëé¿a±êÖ¾         if(mode)key_up=1;  //Ö§3Öᬰ′                           if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))         {                 delay_ms(10);//襶¶¶ˉ                  key_up=0;                 if(KEY0==0)return KEY0_PRES;                 else if(KEY1==0)return KEY1_PRES;                 else if(KEY2==0)return KEY2_PRES;                 else if(WK_UP==1)return WKUP_PRES;         }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;                       return 0;// ÎT°′¼ü°′Ï }
回复 支持 反对

使用道具 举报

1

主题

13

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2018-9-8
在线时间
8 小时
发表于 2018-11-1 19:37:35 | 显示全部楼层

谁给我讲讲按键扫描函数咋写

本帖最后由 日木电子 于 2018-11-1 20:30 编辑

先定义引脚的输出标志位,通过函数来捕获引脚输出的数据,输出标志就是对应的哪个引脚;然后通过函数来捕获引脚输出的0或1 在输出一组状态标志位;
在主函数中通过判断这些标志位来确定其他外设的输出状态;


回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2019-7-17
在线时间
1 小时
发表于 2019-7-17 11:13:37 | 显示全部楼层
请问这mode受什么控制,什么时候为1什么时候为0
回复 支持 反对

使用道具 举报

6

主题

51

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
251
金钱
251
注册时间
2019-7-25
在线时间
57 小时
发表于 2019-8-14 16:30:52 | 显示全部楼层
孤风丶 发表于 2019-7-17 11:13
请问这mode受什么控制,什么时候为1什么时候为0

函数定义的是u8 KEY_Scan(u8 mode),主函数里调用可以是KEY_Scan(0)或者KEY_Scan(1)
回复 支持 反对

使用道具 举报

2

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
160
金钱
160
注册时间
2019-9-2
在线时间
21 小时
发表于 2019-9-2 23:17:26 | 显示全部楼层
我有个问题想问下,最后一句 return 0  是不是无论执行if  还是else if  都要执行? 这样不就函数返回值一直是0  这明显不对啊  按理说应该是执行 else if return0,else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;                       return 0;
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-5 09:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表