# 编码实现 - 事件采集与总线路由器 (Docs/60_coding/mod-event.md) 本文件对应物理按键及射频中断事件采集(输入)、环形消息队列缓冲、以及事件路由分配器(输出)的具体编码实现。 ## 1. 对应代码源文件 * [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (按键消抖 `Key_Scan_Process`、事件队列及 `Event_Dispatcher_Loop` 分发逻辑) * [Drivers/rf.c](file:///c:/workfile/105/stc32g12k128/Drivers/rf.c) (配置 `P2.1` 输入捕捉及解码逻辑) * [App/config.h](file:///c:/workfile/105/stc32g12k128/App/config.h) (`KeyEvent` 核心事件枚举类型声明) ## 2. 关键代码片段与逻辑实现 ### 2.1 事件采集输入(按键定时扫描与消抖) 定义按键 IO 宏,在 `Timer1` (10ms) 分频中读取并判定: ```c sbit KEY_UP = P0^1; // Pin 30 sbit KEY_CONFIRM = P0^2; // Pin 31 sbit KEY_DOWN = P0^3; // Pin 32 sbit KEY_SOS = P2^6; // Pin 27 (物理并联 SOS1/SOS2 按键) void Key_Scan_Process(void) { static u8 key_up_state = 0xFF; static u8 key_down_state = 0xFF; static u8 key_confirm_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_confirm_state = (key_confirm_state << 1) | KEY_CONFIRM; key_sos_state = (key_sos_state << 1) | KEY_SOS; // ▲ 键 (UP) 处理 if ((key_up_state & 0x07) == 0) { key_up_hold++; } else { if (key_up_hold > 2) { Event_Queue_Push(KEY_EVENT_UP_CLICK); } key_up_hold = 0; } // ▼ 键 (DOWN) 处理 (长按 2 秒退出或清除警报) if ((key_down_state & 0x07) == 0) { key_down_hold++; if (key_down_hold == 200) { Event_Queue_Push(KEY_EVENT_DOWN_LONG); } } else { if (key_down_hold > 2 && key_down_hold < 200) { Event_Queue_Push(KEY_EVENT_DOWN_CLICK); } key_down_hold = 0; } // ■ 确认键 (CONFIRM) 处理 (长按 3 秒进入菜单,短按确认) if ((key_confirm_state & 0x07) == 0) { key_confirm_hold++; if (key_confirm_hold == 300) { Event_Queue_Push(KEY_EVENT_SOS_LONG); // 长按事件 } } else { if (key_confirm_hold > 2 && key_confirm_hold < 300) { Event_Queue_Push(KEY_EVENT_SOS_CLICK); // 短击事件 } key_confirm_hold = 0; } // SOS 求救键 (下降沿低电平即刻触发) if ((key_sos_state & 0x07) == 0) { key_sos_hold++; if (key_sos_hold == 3) { Event_Queue_Push(KEY_SOS_ACTIVE); // 触发本地主动报警 } } else { key_sos_hold = 0; } } ``` ### 2.2 事件采集输入(射频数据解调) 射频数据接收线连在 `P2.1`。当发生跳变时触发 INT2 外部沿中断: ```c sbit RF_RX_DATA = P2^1; // Pin 22 bit EV1527_Decode(u32 *out_addr, u8 *out_type) { // 轮询或中断检测引脚 P2.1 沿变化 // 自适应同步低电平 T = low_time / 31 // 连续读取 24 位宽数据 (1:3 对应 0,3:1 对应 1) // 解密出地址和数据码,返回结果给事件总线 // ... return 1; } ``` ### 2.3 事件环形缓冲存储区 ```c #define EVENT_QUEUE_SIZE 4 KeyEvent idata event_queue[EVENT_QUEUE_SIZE]; u8 event_write_ptr = 0; u8 event_read_ptr = 0; u8 event_count = 0; bit Event_Queue_Push(KeyEvent evt) { if (event_count >= EVENT_QUEUE_SIZE) { return 0; // 溢出丢弃 } event_queue[event_write_ptr] = evt; event_write_ptr = (event_write_ptr + 1) % EVENT_QUEUE_SIZE; EA = 0; event_count++; EA = 1; return 1; } KeyEvent Event_Queue_Pop(void) { KeyEvent evt; if (event_count == 0) { return KEY_EVENT_NONE; } evt = event_queue[event_read_ptr]; event_read_ptr = (event_read_ptr + 1) % EVENT_QUEUE_SIZE; EA = 0; event_count--; EA = 1; return evt; } ``` ### 2.4 事件输出路由路由器 (Event Dispatcher) 在主循环 `while(1)` 内,系统以极速轮询该路由分发引擎: ```c void Event_Dispatcher_Loop(void) { KeyEvent evt = Event_Queue_Pop(); if (evt == KEY_EVENT_NONE) { return; // 无事件 } // 1. 本地最高优先级强占处理 if (evt == KEY_SOS_ACTIVE) { StartApp(APP_SOS); // 物理强制唤醒并抢占前台 return; } // 2. 无线报警/配对包推送给后台守护进程 if (evt == RF_EVENT_ALARM || evt == RF_EVENT_PAIR) { BgApp_Process_RF(evt); // 后台比对 Flash 决定是否启动 APP_ALARM 报警页 return; } // 3. 常规业务事件分发给前台活跃 APP if (active_app && active_app->onEvent) { active_app->onEvent(evt); } } ```