在嵌入式开发中,我们使用机械开关时经常碰到抖动问题:引脚电平在短时间内反复变化。
怎么读到确定的按键状态?
1. 通过硬件读取外设状态
- 方法一:连续读很多次,直到数值稳定:浪费CPU资源
- 方法二:使用定时器:要结合中断来使用 (事件触发的方式)
对于第2种方法,处理方法如下图所示,按下按键后:
在t1产生中断,这时不马上确定按键,而是复位定时器,假设周期时20ms,超时时间为"t1+20ms"
由于抖动,在t2再次产生中断,再次复位定时器,超时时间变为"t2+20ms"
由于抖动,在t3再次产生中断,再次复位定时器,超时时间变为"t3+20ms"
在"t3+20ms"处,按键已经稳定,读取按键值
2. 通过逻辑运算实现按键消抖
uint8_t state = getKeysState(); // 此函数为自定义函数,实现功能为对应按键电平为高
/* 通过逻辑运算实现消抖 */
// 按下状态
KeyFalling = state & (state ^ KeyOldState); // 第一步,第x位(x=0,1,2,3)电位变化了,这一位就变成1,其余置0
// 第二步,如果第x位是刚刚按下(也就是从0变1),将第x位置1,其余的(两种情况:
// 1)第y位刚刚松开;2)第y位根本没有状态变化)都置0
// 松开状态
KeyRising = ~state & (state ^ KeyOldState);
// 保存本次按键的值
KeyOldState = state;
两种方法哪个好?
选择消抖方法通常取决于具体的应用场景和系统要求。
-
逻辑运算实现消抖:
- 优点: 相对简单,不需要额外的硬件支持,适用于资源有限的嵌入式系统。
- 缺点: 对按键状态的检测是基于状态变化的,可能会受到噪声或抖动的影响,可能需要调整参数以平衡检测的灵敏度和抗抖动性。
-
定时器结合中断实现消抖:
- 优点: 更精确,可以通过定时器中断周期性地检测按键状态,减少对抖动的敏感度,提高稳定性。
- 缺点: 需要额外的硬件支持,可能占用更多的系统资源,适用于对稳定性和精确性要求较高的系统。
选择哪种方法取决于具体的应用需求和系统资源的限制。在一些简单的嵌入式系统中,逻辑运算的方法可能足够满足要求。在对按键响应时间、稳定性等要求较高的系统中,使用定时器结合中断的方法可能更为合适。