# 编码实现 - 按键扫描与事件判定 (docs/60_coding/mod-key.md) 本文件对应按键状态消抖、长按计时判定以及组合按键识别的具体编码实现细节。 ## 1. 对应代码源文件 * [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (定时中断内的按键扫描、按键状态累加、主循环事件处理) ## 2. 关键代码片段与逻辑实现 ### 2.1 按键中断定时器扫描 (每 10ms 调度一次) 在 `Timer1_Isr` (1ms 滴答) 内,通过 `key_scan_timer` 进行 10ms 分频并调用 `Key_Scan_Process()`: ```c void Key_Scan_Process(void) { // 1. 读取引脚状态并消抖 static u8 key_up_state = 0xFF; static u8 key_down_state = 0xFF; static u8 key_sos_state = 0xFF; key_up_state = (key_up_state << 1) | KEY_UP; key_down_state = (key_down_state << 1) | KEY_DOWN; key_sos_state = (key_sos_state << 1) | KEY_SOS; // 2. 长按与组合按键计时器累加 if ((key_up_state & 0x07) == 0 && (key_down_state & 0x07) == 0) { // ▲ + ▼ 组合键按住 comb_hold++; if (comb_hold == 300) { // 3秒 key_event_buf = KEY_COMB_LONG; } } else { comb_hold = 0; // 单个按键:▲ 键 if ((key_up_state & 0x07) == 0) { key_up_hold++; } else { if (key_up_hold > 2 && key_up_hold < 200) { key_event_buf = KEY_UP_SHORT; } key_up_hold = 0; } // 单个按键:SOS 键 if ((key_sos_state & 0x07) == 0) { key_sos_hold++; if (key_sos_hold == 500) { // 5秒 key_event_buf = KEY_SOS_LONG; } } else { if (key_sos_hold > 2 && key_sos_hold < 500) { key_event_buf = KEY_SOS_SHORT; } key_sos_hold = 0; } // ▼ 键处理同上... } } ``` ### 2.2 事件异步读取与清除 主循环在其周期内轮询 `key_event_buf`。一旦发现其非 `KEY_EVENT_NONE`,拷贝并立即重置该缓冲区为 `KEY_EVENT_NONE` 以防止重复触发: ```c if (key_event_buf != KEY_EVENT_NONE) { KeyEvent evt = key_event_buf; key_event_buf = KEY_EVENT_NONE; // 清空事件缓冲区 // 执行具体事件动作,如在常态下短按 SOS 进入 SOS 警报发射状态等 // ... } ``` 通过该缓冲区实现了按键中断采集与主循环处理的解耦。