共计 1177 个字符,预计需要花费 3 分钟才能阅读完成。
硬件消抖:从源头解决问题
机械按键的物理特性导致触点闭合时会产生 5 -10ms 的抖动(示波器实测如下图)。传统软件延时法在 12MHz 晶振 下会占用 CPU 至少 600 个时钟周期。推荐在硬件层面采用 10kΩ 电阻 +0.1μF 电容 组成 RC 低通滤波,计算公式:

// 临界频率计算(以抖动时间 5ms 为例)fc = 1/(2πRC) < 200Hz // 需低于抖动频率
状态机驱动:非阻塞检测核心
状态转移图示例(KEY_IDLE→KEY_DEBOUNCE→KEY_PRESSED):
stateDiagram
[*] --> KEY_IDLE
KEY_IDLE --> KEY_DEBOUNCE: 引脚变低
KEY_DEBOUNCE --> KEY_PRESSED: 持续 10ms 低电平
KEY_PRESSED --> KEY_IDLE: 引脚变高
实现代码(MISRA- C 兼容):
typedef enum {
KEY_IDLE,
KEY_DEBOUNCE,
KEY_PRESSED
} KeyState;
volatile KeyState key1_state = KEY_IDLE; // 必须加 volatile
void Key_Scan_Task(void) {
static uint8_t debounce_cnt;
switch(key1_state) {
case KEY_IDLE:
if(PIN_KEY1 == 0) {
key1_state = KEY_DEBOUNCE;
debounce_cnt = 0;
}
break;
case KEY_DEBOUNCE:
if(++debounce_cnt >= 10) { // 10ms@1ms 定时
key1_state = (PIN_KEY1 == 0) ? KEY_PRESSED : KEY_IDLE;
}
break;
case KEY_PRESSED:
if(PIN_KEY1 == 1) {PostMessage(MSG_KEY1_PRESS); // 消息队列通知
key1_state = KEY_IDLE;
}
break;
}
}
性能实测对比
| 消抖方案 | CPU 占用率 | 响应延迟 | 代码量 |
|---|---|---|---|
| 纯软件延时 | 98% | 15ms | 50B |
| 硬件 RC 滤波 | 2% | 0.1ms | 120B |
| 状态机 + 中断 | 1% | 1ms | 200B |
中断服务函数规范
- 严格遵循 快进快出 原则
- 仅做状态标记,禁止调用耗时函数
- 共享变量双重保护示例:
__interrupt void Timer0_ISR(void) {
static __bit key_flag;
key_flag = !key_flag;
if(key_flag) Key_Scan_Task(); // 分时处理}
多按键冲突规避
- 采用 时间片轮询 检测不同按键
- 组合键实现时增加300ms 释放延迟
- 状态机中引入 KEY_LOCKED 状态
扩展思考
尝试将状态机扩展为 4×4 矩阵键盘驱动时,需要考虑:
1. 行扫描消抖时机
2. 列线变化的边沿检测
3. 按键编码映射策略
建议用逻辑分析仪捕获实际波形,观察消抖效果是否满足 <5ms 毛刺过滤 的要求。
正文完
