# 编码实现 - 按键扫描与事件判定 (Docs/60_coding/mod-key.md) 本文件对应按键状态消抖、确认键长按 3 秒判定以及主键事件注入的具体编码实现细节。 ## 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_confirm_state = 0xFF; static u8 key_sos1_state = 0xFF; static u8 key_sos2_state = 0xFF; u8 key_sos_state; key_up_state = (key_up_state << 1) | KEY_UP; key_down_state = (key_down_state << 1) | KEY_DOWN; key_confirm_state = (key_confirm_state << 1) | KEY_CONFIRM; key_sos1_state = (key_sos1_state << 1) | KEY_SOS1; key_sos2_state = (key_sos2_state << 1) | KEY_SOS2; // 双上部 SOS 键的逻辑并联 key_sos_state = key_sos1_state & key_sos2_state; // 2. 按键长按与短按状态机扫描 // ▲ 键 (UP) 处理 if ((key_up_state & 0x07) == 0) { key_up_hold++; } else { if (key_up_hold > 2) { key_event_buf = KEY_UP_SHORT; } key_up_hold = 0; } // ▼ 键 (DOWN) 处理 (支持长按 2 秒清除报警/退出) if ((key_down_state & 0x07) == 0) { key_down_hold++; if (key_down_hold == 200) { // 2秒 key_event_buf = KEY_DOWN_LONG; } } else { if (key_down_hold > 2 && key_down_hold < 200) { key_event_buf = KEY_DOWN_SHORT; } key_down_hold = 0; } // ■ 确认键 (CONFIRM) 处理 (支持长按 3 秒进入/退出) if ((key_confirm_state & 0x07) == 0) { key_confirm_hold++; if (key_confirm_hold == 300) { // 3秒 key_event_buf = KEY_CONFIRM_LONG; } } else { if (key_confirm_hold > 2 && key_confirm_hold < 300) { key_event_buf = KEY_CONFIRM_CLICK; } key_confirm_hold = 0; } // 并联 SOS 键 if ((key_sos_state & 0x07) == 0) { key_sos_hold++; if (key_sos_hold == 3) { key_event_buf = KEY_SOS_ACTIVE; } } else { key_sos_hold = 0; } } ``` ### 2.2 事件异步处理与分发 (Process_System_Event 示例) 在主循环事件分发中,对各个状态下的事件进行处理: ```c void Process_System_Event(KeyEvent evt) { switch (current_state) { case STATE_MENU: if (evt == KEY_UP_SHORT) { // 菜单滚动 if (menu_index > 0) menu_index--; Redraw = 1; } else if (evt == KEY_DOWN_SHORT) { if (menu_index < 3) menu_index++; Redraw = 1; } else if (evt == KEY_CONFIRM_CLICK) { // 点击确认进入选中分支 Enter_Menu_Branch(menu_index); } else if (evt == KEY_CONFIRM_LONG) { // 长按 3 秒退出菜单返回时钟待机 current_state = STATE_CLOCK; Redraw = 1; } break; case STATE_PAIR_CONFIRM: if (confirm_edit_focus == 0) { // 第一步:编辑传感器类型 if (evt == KEY_UP_SHORT) { if (selected_type < 6) selected_type++; else selected_type = 0; Redraw = 1; } else if (evt == KEY_DOWN_SHORT) { if (selected_type > 0) selected_type--; else selected_type = 6; Redraw = 1; } else if (evt == KEY_CONFIRM_CLICK) { // 点击确认,锁定类型,跳入第二步选择序号 confirm_edit_focus = 1; Redraw = 1; } } else if (confirm_edit_focus == 1) { // 第二步:编辑序号后缀 if (evt == KEY_UP_SHORT) { if (selected_suffix < 99) selected_suffix++; Redraw = 1; } else if (evt == KEY_DOWN_SHORT) { if (selected_suffix > 1) selected_suffix--; Redraw = 1; } else if (evt == KEY_CONFIRM_CLICK) { // 点击确认,完成最终写入保存,返回时钟 Add_Sensor(captured_addr, selected_type, selected_suffix); current_state = STATE_CLOCK; Redraw = 1; } } // 长按 CONFIRM 3 秒退出不保存 if (evt == KEY_CONFIRM_LONG) { current_state = STATE_CLOCK; Redraw = 1; } break; case STATE_IPC_BIND: // IPC 绑定连发状态中支持物理长按退出 if (evt == KEY_CONFIRM_LONG || evt == KEY_DOWN_LONG) { current_state = STATE_CLOCK; Redraw = 1; } else if (evt == KEY_CONFIRM_CLICK) { // 重发绑定信号 EV1527_Transmit(bracelet_factory_id, 0x01); } break; // 其它状态处理... } } ```