戒指320
发表于 2009-7-26 14:09
打破教科书上的按键检测方法
传统的教科书,无一例外都是采用delay的方法检测按键,但是这种方法有很多缺陷,今天发一贴说说,各位大侠不要见笑,初级菜鸟可以借鉴。<br />传统的处理方法:在第一次检测到有键按下时,执行一段延时 10ms 的子程序以后再确认该按键电平是否能保持闭合状态的电平,如果保持闭合状态电平,则确认为真正有键按下,从而消除抖动的影响. <br />缺点: <br />1. 传统的处理方法执行 10ms 的延时子程序,会降低程序的实时性。 <br />2. 传统的处理方法一次按键动作的确认,只检测两次,在高抗干扰环境下的会有按键的误动作。<br />建议: <br />1. 建议弹跳时间为 100ms 才可有效通过 EFT 杂讯认证。 <br />2. 建议主程序中连续检查 100ms 的稳定低电平才可认定按键按下成立。 <br />3. 相同道理连续检查 100ms 高电平才可认定按键弹起。 <br />4. 为了保证 MCU 的执行效率,按键的检测尽量不要使用 Delay 的方式,可以考虑采用轮询检测和计时器配合的方式进行。<br /><br />方法如下:<br />在发现低电平后,我们每一个循环(时基)去读取一次电平,并与上次进行比较,若是相同则计数器加 1,直至达到足够的次数就进行处理,否则计数器清零,重新开始。<br />https://bbs.21ic.com/upfiles/img/20097/200972614416718.jpg
戒指320
发表于 2009-7-26 14:11
哦
同时这也包含了 分时处理 的思想https://bbs.21ic.com/upfiles/img/20097/200972614753945.jpg
古道热肠
发表于 2009-7-26 14:26
哈哈,按键处理的确很有学问.
直接调用有阻塞的延时函数的确不可取.浪费CPU资源不说,更重要的是不好扩充功能.
程序匠人
发表于 2009-7-26 14:35
需要100ms吗?
会不会有点显得迟钝?
戒指320
发表于 2009-7-26 14:42
哦
呵呵,我也从来没检测超过100ms 30-50ms我觉得可以,100ms的确有点迟钝。这个嘛可以调节。
myfaith
发表于 2009-7-26 15:32
低电平检测100ms
高电平也检测100ms,一次按键200ms,手脚不灵的人按键才会这么慢吧
oldli
发表于 2009-7-26 16:06
延时是必须的
可以设键标志,用一个或数个工作程序段的运行本身作延时。这样就不会有停止等待。<br />如果定时器空着,也可以用来数数。<br />100mS是太长了,15mS左右是合适的。<br />
戒指320
发表于 2009-7-26 16:23
O
请大家不要再对这个100ms发起讨论,前面说过这个可以调整。还有,有的情况下是不需要检测按键放开的。<br /><br />七楼大哥 说用其他程序段代替延时程序也可取,关键这个代替延时的程序段每次执行所花费的时间固定吗?<br /> 我的意思是用 时基 来计时 ,设定一个变量 cnt 假如程序的主时基是4ms的话 当检测到按键按下的时候 inc cnt 下一个回圈 再检测按键,如果还按下的话,cnt 再加一 ,当加到某个值的时候 可以认为 按键确实按下了这期间如果检测到又一次没按下,则clr cnt 重新开始。如果取cnt=10 则消抖时间是10*4=40ms<br /><br />贴出小弟的一段程序,<br />时基是2ms<br />key_scan:<br /> mov a,#01110000b <br /> or p0,a<br /> mov a,#01111000b<br /> mov p0ur,a<br /> mov a,#10000000b<br /> mov p0m,a<br /> mov a,#00000111b<br /> or p4,a<br /> mov p4ur,a<br /> mov a,#00000000b ;com3输入,关led<br /> mov p4m,a<br /> jmp $+1<br /> jmp $+1<br /> jmp $+1<br /> mov a,p4<br /> and a,#00000111b<br /> mov new_key,a<br /> bclr fc<br /> rlcm new_key<br /> rlcm new_key<br /> rlcm new_key<br /> mov a,p0<br /> and a,#01110000b<br /> mov r,a<br /> bclr fc<br /> rrcm r<br /> rrcm r<br /> rrcm r<br /> rrcm r<br /> mov a,r<br /> or new_key,a;00******=00seg6 seg5 seg4 seg3 seg2 seg1 <br /> bts0 f_key_rel <br /> jmp key_scan10 ;检测放键<br /> jmp key_scan20 ;检测按键<br />key_scan10:<br /> mov a,new_key<br /> cmprs a,#00111111b<br /> jmp key_scan30<br /> incms key_cnt<br /> mov a,key_cnt<br /> cmprs a,#15 ;30ms<br /> jmp key_scan90<br /> bclr f_key_rel<br /> jmp key_scan30<br />key_scan20:<br /> mov a,new_key<br /> cmprs a,old_key<br /> jmp key_scan21<br /> incms key_cnt<br /> mov a,key_cnt<br /> cmprs a,#30 ;60ms<br /> jmp key_scan90<br /> clr key_cnt<br /> jmp key_scan40<br />key_scan21:<br /> mov_ old_key,new_key<br />key_scan30:<br /> clr key_cnt<br /> jmp key_scan90<br />key_scan40:<br /> mov a,new_key <br /> cje a,#00111111b,key_scan90 ;无键按下不作处理<br /> cje a,#00111110b,key_scan41<br /> cje a,#00111101b,key_scan42<br /> cje a,#00111011b,key_scan43<br /> cje a,#00110111b,key_scan44<br /> cje a,#00101111b,key_scan45<br /> cje a,#00011111b,key_scan46<br /> cje a,#00001111b,key_scan47 <br /> jmp key_scan90 <br />key_scan41:<br /> mov_ event_buf,#1 ;POWER键键值1<br /> jmp key_scan80<br />key_scan42:<br /> mov_ event_buf,#2 ;osc键键值2<br /> jmp key_scan80<br />key_scan43:<br /> mov_ event_buf,#3 ;HI/LOW键键值3<br /> jmp key_scan80<br />key_scan44:<br /> mov_ event_buf,#4 ;timer键值4<br /> jmp key_scan80<br />key_scan45:<br /> mov_ event_buf,#5 ;+auto键键值5<br /> jmp key_scan80<br />key_scan46:<br /> mov_ event_buf,#6 ;-auto键键值6<br /> jmp key_scan80<br />key_scan47:<br /> mov_ event_buf,#7 ;+-auto同时键值7<br />key_scan80:<br /> bset f_key_rel<br /> call wrt_FIFO ;将键值写入event_FIFO<br />key_scan90:<br /> ret
gaohq
发表于 2009-7-26 17:40
能否上个C语言的注释全点的让我等初学看看。
时基 ?。。。。。<br />定时器中断X次就是一个时基?<br />检测到有键按下,A=0,定时中断一次 A++,<br />IF(A==20)比较键值,相同就确定有键按下?
ayb_ice
发表于 2009-7-26 18:05
有多任务思想这个问题就好解决
lwd110
发表于 2009-7-26 18:10
没看出和教科书有什么实质区别啊?
hyg1984
发表于 2009-7-26 20:17
板凳
观看
tyw
发表于 2009-7-26 21:09
要是这个软件延时用定时方法实现了呢?哈哈
在定时中断里做一个1mS的公共时标<br />当有键按下时对这个公共时标计数,比如计数30,则再检查键状态
yewuyi
发表于 2009-7-26 21:26
老掉牙的东西还有人讨论,说明老辈人写的书太差
呵呵。。。
程序匠人
发表于 2009-7-26 22:35
教科书误导了一茬又一茬的白菜
尽信书则不如无书
戒指320
发表于 2009-7-26 22:56
继续顶
iC921
发表于 2009-7-26 23:47
100ms太久,只争1ms
iC921
发表于 2009-7-26 23:49
现在的按键形式可丰富
s46410864
发表于 2009-7-27 08:19
延时长点不要紧
延时100MS,不算多,我们按一下的时间也不少,<br />100MS,比复位的时间还短,应该可以,而且最大的程度去抖动.<br />保证了键盘的稳定性,不错,还有如LZ所说DELAY不环保,用定时轮询..<br />很好的按键产生了..哦HOHO
gaohq
发表于 2009-7-27 08:57
大侠
可以设键标志,用一个或数个工作程序段的运行本身作延时。这样就不会有停止等待<br />_______________________________________________________<br />这个是怎么搞的呢?