stm32按键消抖
- 一 问题背景
- 二 解决思路
- 三 代码实现
一 问题背景
开关按钮:按下信号为0,正常信号为1
在按下时,表面上看我们只按了一下,但信号的传递并不是单纯的由1直接变为0。这是由于机械触点断开/闭合时会有抖动,信号如图示会在1和0之间抖动。这种抖动对人来说是感觉不到的,但对单片机来说,这段时间还是很漫长的。(摘自百度知道)
在这段抖动的时间,仍然会执行程序,进行信号的判定。造成我们写代码时,容易步入一个逻辑误区。详见下图对一次按下和松开按钮进行详细分析:
二 解决思路
思路:判定一次按钮按下无非是判定信号的01变化或10变化,然而根据上图我们必须清楚几个结论:
- 1 按钮正常时信号稳定为1,按下按键稳定后为信号0
- 2
按下
和松开
的瞬间,会反复进行:010101 信号抖动,约5~10ms - 3 假设无外部情况干扰,只有 第2点 中的两种情况,才会导致连续的01或10的变化
- 4 所以判定按钮是否被按下(也就是判断01交替),要同时考虑到
按下和松开瞬间
两种抖动情况
三 代码实现
判断一次按钮按下然后松开
方法1
//B5引脚检测信号为0时,判断两种情况
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0){ //(1)刚按下按键发生抖动(2)上一次的按键松开发生抖动
Delay_ms(20);//(1)若为1,度过按下抖动,信号稳定为0
//(2)若为2,度过松手抖动,信号稳定为1
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0){ //检测信号仍为0,去掉情况(2)
while((GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5) == 0)) ;//(1) 松开时,检测到信号从0变1退出循环,此信号必定为松开抖动
run(); //执行对应操作,已确定按键按下然后松开。且按键松开抖动不影响本方法判定
}
}
方法2
//去掉方法1的第二次if判定,增加一次delay延时
//B5引脚检测信号为0时,两种情况分析
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0){ //(1)刚按下按键发生抖动(2)上一次的按键松开发生抖动
Delay_ms(20);//(1)若为1,度过按下抖动,信号稳定为0
//(2)若为2,度过松手抖动,信号稳定为1
while((GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5) == 0)) ;// (1) 等待松开,检测到松开波动信号1时,退出循环
//(2)立刻通过判定
Delay_ms(20);//(1)度过松手抖动,信号稳定1,故情况2被检测的前提不成立,该程序不会检测到松手抖动
//(2)若没有这一句Delay语句:按键松手瞬间会执行下方语句,可能会遇到:按一次按钮执行两次操作的情况
run(); //只有情况(1)可以执行,能够检测一次按下按键并松开并执行对应操作
}