我是靠谱客的博主 坦率水池,这篇文章主要介绍一种相对高效的按键消抖方法,现在分享给大家,希望可以做个参考。

按键软件消抖自我接触单片机开始就已经存在这个问题了,网上的办法无非是延时消抖和定时轮询。对于写裸机的我来说这两种方法都不可避免的会有资源浪费掉,今天突然有了灵感,想到了一种相对高效的办法来解决消抖问题。

硬件平台:STM32F103RCT6开发板

开发环境:WIN7-64bit+MDK5+STD库

按键消抖的必要性在此我就不多说了。直接步入正题。

在使用本方法前请注意,本方法需要一个全局时间戳的支持。

第一步:初始化全局时间戳的定时器,一般采用SysTick定时器来产生,每ms一次tick即可。

第二步:初始化按键对应的IO,复用为边沿触发的外部中断。

第三步:在外部中断函数中添加按键事件处理函数。

代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct _Key_t { u32 last_time; enum { May_Press, Release, }private_state; enum { No_Press, Short_Press, Long_Press, }state; }Key_t; #define Is_ShortPress_Threshold 1500
简单定义一个按键状态的结构体,用于管理每个按键的状态。顺便再定义一个长短按的识别阈值,用于区分按键的长短按。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if(key_state.private_state==Release) { if(KEY==0) { key_state.private_state=May_Press; key_state.last_time=course_ms(); } } else if(key_state.private_state==May_Press) { if(KEY==1) { if((course_ms()-key_state.last_time>10)&&(course_ms()-key_state.last_time<Is_ShortPress_Threshold)) { key_state.state=Short_Press; key_state.private_state=Release; } else if(course_ms()-key_state.last_time>Is_ShortPress_Threshold) { key_state.state=Long_Press; key_state.private_state=Release; } else key_state.private_state=Release; } }
以上为需要添加到中断处理函数的按键事件处理函数,算法的核心是一个状态机。在本例中,按键被默认上拉,按下接地。course_ms()为获取全局时间戳的函数。

思路解释如下:按键状态结构体有一个用于识别的状态位,默认处于Release,也就是释放的状态。一旦按键被按下,中断触发,此时检查是否是Relase状态,如果是就检查按键是否被拉低,如果是,此时进入May_Press状态,也就是可能是按下的,并且记录此时的时间戳,这一步是消抖的关键。当按键被释放,由于是边沿触发,会再次进行处理,此时检查和上一次触发之间的时间戳之差,如果小于10ms我们就认为是抖动,此时不会对按键输出状态进行修改,而是直接将按键状态置回Relase状态,反之检查差值和长短按阈值之间的关系,将state置位为对应的状态。消抖的核心在于记录时间戳,而这只是一个简单的赋值操作,并不耗费时间。

效率上来说,延时消抖花费时间在无意义延时上,而相对较好的定时轮询还是不可避免的在轮询,而现在这种方式完全是中断性质的。唯一多出的开销(全局时间戳)并不是只可以用于按键消抖,另外在HAL库中存在直接获取tick的函数,这样实现就更方便了。经实际测试,消抖效果可以达到其他两种消抖算法的水平。




最后

以上就是坦率水池最近收集整理的关于一种相对高效的按键消抖方法的全部内容,更多相关一种相对高效内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(98)

评论列表共有 0 条评论

立即
投稿
返回
顶部