打印

分享一下十几年我一直使用的按键处理方法

[复制链接]
1929|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhongke11|  楼主 | 2013-12-4 15:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 yewuyi 于 2013-12-4 15:56 编辑

分享一下十几年我一直使用的按键处理方法
看见大家发了那么多按键的处理方法,我也发一个。

刚参加工作的时候,对比学校里和同事的按键处理函数,发现总是不尽如人意,
有以下几点:
1. 消抖复杂,效率低。很多人直接在电平判断后使用delay()函数,进行消抖,
耽误时间;有人在按键电平中断中消抖,导致其他的中断,比如串口、定时等
反应很慢,不适合做实时系统;
2. 特殊功能按键的处理麻烦。使用简单电平判断的按键扫描,在需要长按响应、
复合按键响应、复合按键长按响应的时候,需要增加很多的标志位,反复使用
if..else判断,有时候把自个都搞乱了。
3. 不便于移植和修改。使用以上两点编写的函数,如果用在直接端口按键上的,
那么在行列扫描按键的时候,就很难适应。导致每个项目都要更改一次。

想了很久之后,我结合PC的键盘处理方法,编写了自己的按键函数,经过几次修改,
定了下来。这十几年来,一直在用,方便移植,而且比较清晰。
——至少我自己这么觉得。

它有以下几个特点:
1. 按键扫描和取值分开。
    在中断中(一般10ms),反复调用keyScan()进行按键扫描(包括消抖)。
    消抖之后的按键值不返回,作为消息放到全局变量中;
    在需要判断的地方使用getKeyValue()获取当前的键值,进行处理。

2. 每一个按键,都有单独的标志位和计时变量。
    消抖计时:
    如果按键按下,每调用一次10ms中断,gucKeyOkTimer增加;
    gucKeyOkTimer超过消抖的阀值(我一般10次,即100ms),则确认有按键了。
    任何一次扫描到按键没有按下,gucKeyOkTimer清空;

    标志位:
    如果一直按着(通过按键电平判断),会有gfOkPressing
    如果按下过一次,需要响应,会有gfOkNeedAck

    复合按键的响应:
    因为每个按键,包括复合按键都有自己的标志位和计时变量,可以跟物理按键的
    处理方法相同。只是消抖的条件,不是电平的判断,而是物理按键的pressing标志。

3. 我没有使用怪癖诡异的编程方法。有很多取巧的方法可使实现按键的扫描,甚至有
人写了三行代码就实现消抖。——我个人不喜欢这样的程序风格。我喜欢思路清晰的编程方法,
易于维护和移植。当然代价就是多了一些ROMRAM占用,但我觉得时间和代码的质量更重要。

如果你跟我的思路相同,也遇见过这样的困惑,可以考虑我的按键扫描方法

沙发
yewuyi| | 2013-12-4 15:56 | 只看该作者
勿发广告,已删除你的广告,否则只能删帖。

使用特权

评论回复
板凳
huangxz| | 2013-12-4 23:32 | 只看该作者
写的不错,

使用特权

评论回复
地板
yklstudent| | 2013-12-5 10:23 | 只看该作者
状态机的思路来做

使用特权

评论回复
5
sunabeng| | 2013-12-5 10:43 | 只看该作者
我以为有源码

使用特权

评论回复
6
kuheye| | 2013-12-19 21:35 | 只看该作者
本帖最后由 kuheye 于 2013-12-19 21:38 编辑

我也一直是这样做的,哈哈
所不同的是,我的KeyScan子程序是放到主循环中轮训,第一次读取后,间隔10ms再读取第二次,间隔10ms不用软件延时,用心跳来做(中断),而我的程序,全部采用状态机,有点像多任务系统
顺便说一下,我是骨灰级汇编,不会c,

由于节省RAM,集中去都动,没有每个按键独立消抖(这样会造成个别按键异常,而影响全局,尤其是采用74HC165扩展时,硬件不当而会影响全局)
当然,正如楼主所说,每个按键独立去抖动,需要更多的RAM,具体自己权衡

使用特权

评论回复
7
xiang2580| | 2013-12-21 16:08 | 只看该作者
产品不同,方法不同。用个合适自己产品的就好了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

43

帖子

2

粉丝