docs: restructure framework, extract app execution module, group event collection & align GPIOs
This commit is contained in:
@@ -1,16 +1,99 @@
|
||||
# 编码实现 - 事件总线与缓冲路由 (Docs/60_coding/mod-event.md)
|
||||
# 编码实现 - 事件采集与总线路由器 (Docs/60_coding/mod-event.md)
|
||||
|
||||
本文件对应环形事件缓冲区(Event Queue)与事件路由分发器的具体编码实现细节。
|
||||
本文件对应物理按键及射频中断事件采集(输入)、环形消息队列缓冲、以及事件路由分配器(输出)的具体编码实现。
|
||||
|
||||
## 1. 对应代码源文件
|
||||
|
||||
* [App/main.c](file:///c:/workfile/105/stc32g12k128/App/main.c) (事件队列定义、`Event_Queue_Push` / `Event_Queue_Pop` / `Event_Dispatcher_Loop` 的底层 C 语言实现)
|
||||
* [App/config.h](file:///c:/workfile/105/stc32g12k128/App/config.h) (`KeyEvent` 枚举量定义)
|
||||
* [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 环形队列定义与入队出队函数
|
||||
在 `main.c` 中,定义深度为 4 级的事件队列缓冲数组及读写位置指针:
|
||||
### 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
|
||||
|
||||
@@ -19,70 +102,54 @@ u8 event_write_ptr = 0;
|
||||
u8 event_read_ptr = 0;
|
||||
u8 event_count = 0;
|
||||
|
||||
// 初始化队列
|
||||
void Event_Queue_Init(void) {
|
||||
event_write_ptr = 0;
|
||||
event_read_ptr = 0;
|
||||
event_count = 0;
|
||||
}
|
||||
|
||||
// 压入事件入队 (非阻塞,中断安全)
|
||||
bit Event_Queue_Push(KeyEvent evt) {
|
||||
if (event_count >= EVENT_QUEUE_SIZE) {
|
||||
return 0; // 缓冲区溢出,写入失败
|
||||
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.2 事件轮询分发器 (Event Dispatcher)
|
||||
在主循环 `main()` 中,系统定时轮询事件总线,读取事件并路由给前后台应用:
|
||||
### 2.4 事件输出路由路由器 (Event Dispatcher)
|
||||
在主循环 `while(1)` 内,系统以极速轮询该路由分发引擎:
|
||||
```c
|
||||
void Event_Dispatcher_Loop(void) {
|
||||
KeyEvent evt = Event_Queue_Pop();
|
||||
if (evt == KEY_EVENT_NONE) {
|
||||
return; // 队列为空,直接跳过
|
||||
return; // 无事件
|
||||
}
|
||||
|
||||
// 1. 优先判定物理抢占型事件 (如 SOS 键)
|
||||
// 1. 本地最高优先级强占处理
|
||||
if (evt == KEY_SOS_ACTIVE) {
|
||||
StartApp(APP_SOS); // 强行强占前台,启动紧急求救页面
|
||||
StartApp(APP_SOS); // 物理强制唤醒并抢占前台
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 无线报警事件路由给后台进程进行防区匹配
|
||||
// 2. 无线报警/配对包推送给后台守护进程
|
||||
if (evt == RF_EVENT_ALARM || evt == RF_EVENT_PAIR) {
|
||||
BgApp_Process_RF(evt); // 后台比对数据库,若匹配且在布防状态下,唤醒强占报警App
|
||||
BgApp_Process_RF(evt); // 后台比对 Flash 决定是否启动 APP_ALARM 报警页
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 常规按键事件分发给当前活跃的前台 APP
|
||||
// 3. 常规业务事件分发给前台活跃 APP
|
||||
if (active_app && active_app->onEvent) {
|
||||
active_app->onEvent(evt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user