中国自动化学会专家咨询工作委员会指定宣传媒体
免费注册 登录 广告服务 | 客服中心
您现在所在的是:

单片机论坛

抖音 德嘉 泓格论坛 FLIR红外热像论坛
工控论坛首页 单片机论坛 → 浏览主题: [分享]一个移植性和复合按键处理最好的按键扫描方法
发表新帖 回复该主题
回帖:2个,阅读:1048 [上一页] [1] [下一页]
* 帖子主题:

[分享]一个移植性和复合按键处理最好的按键扫描方法

分享到
644
铭为科技
文章数:8
年度积分:50
历史总积分:644
注册时间:2013/7/17
发站内信
发表于:2013/7/22 11:31:19
#0楼
看见大家发了那么多按键的处理方法,我也发一个。

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

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

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

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

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

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

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

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

我摘录了与按键相关的部分,如果有疑问,欢迎通过邮件或QQ沟通。
附件:key.rar
[本地下载]
[此贴子已经被作者于2013/7/24 8:23:42编辑过]
——比开发板更实用的产品开发学习系统——
www.magic-wing.com
mwtech.taobao.com
1094
972001057
文章数:126
年度积分:50
历史总积分:1094
注册时间:2011/10/24
发站内信
发表于:2013/7/29 9:59:35
#1楼
我是初学者,可以说是完全不懂,看了很多贴,都说想学好单片机,用学C,因为C比较适用,而且方便移植。看了阁下的文章,应该是一位资深人士,向你多学习学习。不知有没有什么经验可以分享一下给我们这些初学者呢?期待。
644
铭为科技
文章数:8
年度积分:50
历史总积分:644
注册时间:2013/7/17
发站内信
发表于:2013/7/29 22:05:38
#2楼
回复 #1楼 972001057
单片机就是一种工具,学习很重要,实用更重要。
现在无论51还是ARM编程,C都是主流了,不学不行的。——除非你还在空调、微波炉等简单控制器行业,还是转C吧。
要想把学习跟实用结合起来,建议你看看我们的产品开发学习系统。
mwtech.taobao.com
希望能够帮到你。
——比开发板更实用的产品开发学习系统——
www.magic-wing.com
mwtech.taobao.com
工控学堂推荐视频:

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

46.8003