按键去抖
由于机械按键的特性(例如轻触开关),在开关的瞬间,不会稳定地闭合或断开,一连串的抖动信号可以轻易被单片机捕获,因此单片机可能会误判按键状态。为了能够让单片机正确识别按键状态,必须对输入的按键信号进行去抖,分为硬件去抖和软件去抖。实际项目中最常用的去抖方案就是软件定时器 + 硬件电容滤波。
1.抖动波形
正常人类操作按键的时间约几百毫秒到几秒不等,而按键的抖动信号的持续时间约5ms到20ms。按键的闭合以及松开的瞬间均会产生抖动信号。
按键在空闲时(稳定松开状态)默认高电平,以下分析上升沿:按键在按下状态,松开瞬间的波形,也就是从低电平变为高电平的瞬间。
2.创建工程
STM32CubeMX创建工程,设置PA2
为GPIO_EXTI2
(配置为外部中断触发),同时设置PC13
作为GPIO输出。
生成工程并导入到EIDE
中,在/* USER CODE BEGIN 4 */
代码块之间插入代码,意思是在GPIO的输入中断里切换PC13
的电平(切换LED灯显示),编译烧录到STM32开发板中
1 |
|
3.波形分析
将一个轻触开关的一端接入PA2
,另一端接入GND
,多次按下按键,观察LED状态,发现不能每次都稳定地切换LED灯状态。将示波器接入PA2
,参数设置如下,开启单次触发,观察波形不难看出在按键松开的过程中发生了多次抖动
触发类型 | 触发方式 | 时基 | 幅值 |
---|---|---|---|
上升沿 | 常规 | 100uS | 1V |
4.软件去抖
4.1 延时
延时的方式相当直观简单,在主循环中,只要检测到PA2
为低电平,也就是按键按下,延迟10ms再次检测是否为低电平,如果是说明按键按下。
1 |
|
虽然延时判断的方式简单有效,但是会极大影响系统的实时性(系统在延时期间无法处理其他任务)。正常情况下不会应用到实际项目中,除非是简单验证功能或者项目没有实时性的要求。
4.2 定时器
STM32CubeMX添加定时器TIM1
,参数如下。定时器中断去抖的本质上就是检测在某一段时间内是否有连续相同的电平状态。
以下函数均在main.c
文件中实现
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
5.硬件去抖
5.1 电容滤波
最常见的硬件去抖方式是电容滤波,给按键并联一个电容和串联一个电阻,利用电容的充放电特性实现一定程度的滤波。
以电容取值100nF,电阻取值10KΩ为例,原理图如下,将示波器探头接入PA2
,观察按键松开时的波形
底部的测量参数上升沿1.524ms,实际从低电平爬升至高电平需要3-4ms左右,因此电容的取值不能过大,否则爬升时间太长可能会影响按键的有效判断。
5.2 RS触发器
RS触发器就是使用两个与非门的级联,其中一个与非门的输出作为另一个与非门的输入,描述方法是现态$Q^{n}$和次态$Q^{n+1}$,通常用于没有MCU的场合,使用较少。
单击此处可以在线模拟RS触发器按键效果,单击切换开关,观察底部的示波器波形,示意图如下
根据与非门的先与后非的运算规则,只要输入0,一定输出1,真值表如下
R输入 | S输入 | Q输出 |
---|---|---|
0 | 0 | 1 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
- 当R1稳定连接,
R1 = 0
,则S2一定稳定断开(单刀双掷开关不能可能同时导通),S2 = 1
;根据与非门规则:Q1 = 1
;根据图中R2与Q1直连,因此R2 = Q1 = 1
, 因此Q2 = 0
;S1与Q2直连,因此S1 = Q2 = 0
- 当R1开始断开, R1状态不稳定,随机1或0,但是因为且S2状态不变,
S1 = 0
也不变,因此Q1状态不变Q1 = 1
- 当R1完全断开,
R1 = 1
,Q1保持 - 当S2开始连接,S2状态不稳定,随机1或0;当S2第一次等于0,则
Q2 = 1
,S1 = Q2 = 1
,因为R1稳定断开R1 = 1
,因此Q1 = 0
,R2 = Q1 = 0
,后续就算是S2再变成1,因为R2已经稳定,因此Q1稳定 - 当S2稳定连接,
S2 = 0
,Q1不变Q1 = 0
按照目前按键的生产工艺,抖动的情况已经有比较好的改善,甚至有些品质较好的按键都已经不会产生抖动信号。
另外,有一些单片机在其GPIO功能上就内置了按键去抖功能,在初始化GPIO输入的时候,设置结构体的deboune
成员变量为10ms即可。相对与自行实现的按键去抖方案,不仅实现起来简单,而且还节省一个定时器资源。