按键扫描是每个搞单片机的都会遇到的问题,也是一个开发人员必须具备的基本功。先从最基本的说起。在此声明,没有代码,也不要向我要代码,也不想穿裤子,如果你看了帖子还写不出代码,那么我只能说你太笨了。。。。。。。。还是那句话,搞开发重要的是思想,而不是代码,代码只是工具
通常的按键扫描程序是这样做的
键盘按下?YES---延时去抖----键盘按下?YES-----确实按下了,按键有效---退出
NO NO
退出 退出
很多教材上都是这样写,但这个程序却是误人子第的
问题来了,这个程序不太好用,有时按一下,或按久一点,程序会认为你按了很多次!!为什么???
因为没有判断按键释放,当我们按下键盘时,程序可能已经跑了N个来回了。
好了,我们来个改进版的按键扫描程序
键盘按下?YES---延时去抖----键盘按下?YES-----确实按下了,按键有效---A按键释放?YES--退出
NO NO NO
退出 退出 返回A
这是大多数人的按键扫描程序,在一般的场合也能用。这个程序比{dy}个要好点,但也好不到哪里去。为什么?判断按键释放的方法太笨了,如果我们一直按下这个键盘会怎么样?程序在此死等,可能你说我还有中断,但中断处理完了你还得回来傻等!而且其他按键也将被屏蔽。
那么,让我们好好想想该怎么做。。。。。。。(未完待续,欢迎大家跟贴,谈一下自己的解决方法;看有没有同道中人)
继上:
==============================================================================
言归正传,其实楼下很多人都给出了较好的按键扫描程序,但没有人解释一下为什么要那么做。
现在我来谈谈自己的看法 。先假设按键平时是高电平,按下后是低电平。也就是按键低电平有效
那么一个完整的按键过程会发生什么?按键输入脚电平变化顺序是 高----》低----》高
未按键 按下键 键释放
真正的高手看到这里就恍然大悟,后面的基本不用看了。
好的按键扫描程序不是判断按键是否被按下,而是判断按键电平变化的变化顺序是否符合 高----》低
----》高 ,其他的按键电平变化顺序都是非法的 。这是按键扫描的基本原理。那么该怎么来判断呢?
进入按键扫描后,我们可能会扫到高电平,那么就需要判断到底是未按键导致的高电平还是按下后键释
放导致的高电平,这里用一个位变量(取名为键前状态,1=曾经按下,0=未按下)做为标志就可以了;
也可能会扫到低电平,那么需要判断这个低电平是由未按键到按下键得到的,还是扫描之前本来就是低
电平,这里也用一个位变量(取名为键有效1=有效,0=无效)做为标志。好了,下面给一个简单的流程
主程序初始化操作,键前状态=0,键有效=0
按键扫描流程
键盘===高电平----》键有效=1--》A1键盘曾经按下后变成高电平,键盘已释放,复位键前状态=0---》退出
! !
! --》键有效=0--》未按下---》退出
!
!
!
!===低电平----》键前状态=1--》键盘曾经按下,现在仍然是低电平--》退出
!
--》键前状态=0--》未按下---》A2键盘由高电平变成低电平,置键有效=1,键前状态=1;---》退出
为了突出重点,这个流程没有加去抖处理,想要稳定的效果,必须加延时去抖处理。按这个流程处理按键,响应速度快,
也不会误判。你就是按{yt}也,不会傻等。按键有效之后,每次只进来看一下就走。{zd0}的好处就是可以实现真正的模块化
按键处理xx由这个程序控制,不必在其他地方判断按键释放没有。
另外再简单谈一下长按,短按的判断。要判断长按,在按键有效之后(A2处)启动定时器,然后在按键释放(A1处)后判断时
间的长短,大于一定时间算长按。至于组合键盘的处理,在上面的流程上稍加改动就可以实现,等有时间再详谈。
转自:ouravr
QUOTE:
在中断里处理按键自然响应更快,不过你的这个方法有漏洞。如果在定时时间未到的时候按键松开一下又按下,那么在你定时时间到的时候认为是一直按下的。特别是判断长按的时候。可以这么做:开个定时器,定时间隔可以定为1毫秒。在定时器ISR里检测按键,采用一个全局变量对按下时长做计数。这样可以准确得出按键按下的时长,作为区分长短按的依据。