Files
stc32g128k/Docs/60_coding/mod-event.md
2026-07-15 15:57:37 +08:00

4.8 KiB
Raw Permalink Blame History

编码实现 - 事件采集与总线路由器 (Docs/60_coding/mod-event.md)

本文件对应物理按键及射频中断事件采集(输入)、环形消息队列缓冲、以及事件路由分配器(输出)的具体编码实现。

1. 对应代码源文件

  • App/main.c (按键消抖 Key_Scan_Process、事件队列及 Event_Dispatcher_Loop 分发逻辑)
  • Drivers/rf.c (配置 P2.1 输入捕捉及解码逻辑)
  • App/config.h (KeyEvent 核心事件枚举类型声明)

2. 关键代码片段与逻辑实现

2.1 事件采集输入(按键定时扫描与消抖)

定义按键 IO 宏,在 Timer1 (10ms) 分频中读取并判定:

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 外部沿中断:

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 对应 03:1 对应 1)
    // 解密出地址和数据码,返回结果给事件总线
    // ...
    return 1;
}

2.3 事件环形缓冲存储区

#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) 内,系统以极速轮询该路由分发引擎:

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);
    }
}