feat: 实现事件驱动应用框架,支持前台/后台分离、事件优先级和CPU占用控制

This commit is contained in:
2026-07-10 11:30:48 +08:00
parent 00c00fb60e
commit b4fabf85b5
11 changed files with 2487 additions and 541 deletions

View File

@@ -1,6 +1,8 @@
#include "stc32g.h"
#include "intrins.h"
#include "config.h"
#include "event.h"
#include "appmgr.h"
#include "../Drivers/lcd.h"
#include "../Drivers/rf.h"
@@ -739,7 +741,15 @@ void Timer1_Isr(void) interrupt 3
current_hour = 0;
}
}
clock_updated = 1; // 标记时钟更新,在主循环中更新屏幕
// 通过事件队列通知时钟应用分钟变化
{
SystemEvent evt;
evt.key_event = KEY_EVENT_NONE;
evt.priority = EVENT_PRIORITY_LOW;
evt.extra_data = ((u32)current_hour << 8) | current_min;
evt.extra_size = 2;
EventQueue_Push(evt);
}
}
}
@@ -966,19 +976,38 @@ void Timer1_Isr(void) interrupt 3
}
/* =========================================================================
* 系统主循环逻辑 (交互状态机与射频匹配核心)
* 外部声明:应用注册函数
* ========================================================================= */
extern void Apps_RegisterAll(void);
/* =========================================================================
* 时钟更新回调:在定时器中断中触发,通知时钟应用重绘
* ========================================================================= */
void ClockApp_NotifyUpdate(void)
{
// 通过事件队列通知时钟应用分钟变化
SystemEvent evt;
evt.key_event = KEY_EVENT_NONE;
evt.priority = EVENT_PRIORITY_LOW;
evt.extra_data = ((u32)current_hour << 8) | current_min;
evt.extra_size = 2;
EventQueue_Push(evt);
}
/* =========================================================================
* 系统主循环逻辑 (事件驱动框架核心)
* ========================================================================= */
void main(void)
{
KeyEvent ev;
u8 state_changed = 0; // 用 u8 代替 bit 变量
u8 last_radar_sec = 99;
SystemEvent evt;
char cmd;
u8 last_led_r = 1;
u8 last_led_g = 1;
u8 last_led_b = 1;
u8 last_motor = 0;
char cmd;
// 单片机时钟与看门狗基础初始化
WTST = 0;
@@ -1007,10 +1036,12 @@ void main(void)
Load_Database();
Timer1_Init();
// 默认进入 NORMAL 待机模式,显示时钟,并将射频调制芯片置为被动接收模式
current_state = STATE_NORMAL;
UI_ShowClockPage(current_state, current_hour, current_min);
RF_SetMode(1); // 开接收天线
// 初始化事件队列和应用管理器
EventQueue_Init();
Apps_RegisterAll();
AppManager_Init();
Uart_SendString("[FRAMEWORK] Event-driven framework started\r\n");
while(1)
{
@@ -1018,76 +1049,96 @@ void main(void)
cmd = Uart_RxChar();
if (cmd != '\0')
{
SystemEvent sys_evt;
sys_evt.priority = EVENT_PRIORITY_NORMAL;
sys_evt.extra_data = 0;
sys_evt.extra_size = 0;
if (cmd == 'u')
{
key_event_buf = KEY_EVENT_UP_CLICK;
sys_evt.key_event = KEY_EVENT_UP_CLICK;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] KEY_UP Clicked\r\n");
}
else if (cmd == 'U')
{
key_event_buf = KEY_EVENT_UP_LONG;
sys_evt.key_event = KEY_EVENT_UP_LONG;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] KEY_UP Long Pressed\r\n");
}
else if (cmd == 'd')
{
key_event_buf = KEY_EVENT_DOWN_CLICK;
sys_evt.key_event = KEY_EVENT_DOWN_CLICK;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] KEY_DOWN Clicked\r\n");
}
else if (cmd == 'D')
{
key_event_buf = KEY_EVENT_DOWN_LONG;
sys_evt.key_event = KEY_EVENT_DOWN_LONG;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] KEY_DOWN Long Pressed\r\n");
}
else if (cmd == 's')
{
key_event_buf = KEY_EVENT_SOS_CLICK;
Uart_SendString("[UART SIM] KEY_SOS Clicked\r\n");
sys_evt.key_event = KEY_EVENT_SOS_CLICK;
sys_evt.priority = EVENT_PRIORITY_URGENT;
EventQueue_EmergencyDispatch(sys_evt);
Uart_SendString("[UART SIM] KEY_SOS Clicked (Emergency)\r\n");
}
else if (cmd == 'S')
{
key_event_buf = KEY_EVENT_SOS_LONG;
Uart_SendString("[UART SIM] KEY_SOS Long Pressed\r\n");
sys_evt.key_event = KEY_EVENT_SOS_LONG;
sys_evt.priority = EVENT_PRIORITY_URGENT;
EventQueue_EmergencyDispatch(sys_evt);
Uart_SendString("[UART SIM] KEY_SOS Long Pressed (Emergency)\r\n");
}
else if (cmd == 'c' || cmd == 'C')
{
key_event_buf = KEY_EVENT_UP_DOWN_COMB;
sys_evt.key_event = KEY_EVENT_UP_DOWN_COMB;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] KEY_UP + KEY_DOWN Combined\r\n");
}
else if (cmd == 'a' || cmd == 'A')
{
// 模拟报警事件
u32 mock_addr = 0x123456;
u8 mock_slot;
if (!Check_Sensor_ID(mock_addr, &mock_slot))
{
Add_Sensor(mock_addr, 0); // 0: 门磁
Add_Sensor(mock_addr, 0);
}
captured_addr = mock_addr;
current_state = STATE_ALARM;
state_changed = 1;
alarm_sensor_slot = mock_slot;
sys_evt.key_event = KEY_EVENT_NONE;
sys_evt.priority = EVENT_PRIORITY_HIGH;
sys_evt.extra_data = mock_addr;
sys_evt.extra_size = 4;
EventQueue_Push(sys_evt);
AppManager_StartApp(APP_ID_ALARM);
Uart_SendString("[UART SIM] Mock RF Alarm: ADDR 0x123456\r\n");
}
else if (cmd == 'p' || cmd == 'P')
{
if (current_state == STATE_PAIR_WAIT)
{
captured_addr = 0x789ABC;
captured_type = menu_select;
current_state = STATE_PAIR_CONFIRM;
state_changed = 1;
Uart_SendString("[UART SIM] Mock RF Pair Signal: ADDR 0x789ABC\r\n");
}
else
{
Uart_SendString("[UART SIM] Ignore: Not in PAIR WAIT state\r\n");
}
// 模拟配对信号
captured_addr = 0x789ABC;
captured_type = 0;
sys_evt.key_event = KEY_EVENT_NONE;
sys_evt.priority = EVENT_PRIORITY_NORMAL;
sys_evt.extra_data = 0x789ABC;
sys_evt.extra_size = 4;
EventQueue_Push(sys_evt);
Uart_SendString("[UART SIM] Mock RF Pair Signal: ADDR 0x789ABC\r\n");
}
else if (cmd == 't' || cmd == 'T')
{
Uart_SendString("[UART SIM] SPI 3MHz Clock Test on P2.5 (SCLK) and P2.3 (MOSI) active. Press reset to exit.\r\n");
// Configure SCLK (P2.5) and MOSI (P2.3) as push-pull output
P2M1 &= ~((1 << 3) | (1 << 5));
P2M0 |= ((1 << 3) | (1 << 5));
SPCTL = 0xD0; // SPI Master, 6.0 MHz (SYSCLK / 4)
SPCTL = 0xD0;
while(1)
{
SPSTAT = 0xC0;
@@ -1097,366 +1148,116 @@ void main(void)
}
else if (cmd == '1')
{
current_state = STATE_NORMAL;
state_changed = 1;
Uart_SendString("[UART SIM] Set State to: NORMAL (Standby)\r\n");
AppManager_StartApp(APP_ID_CLOCK);
Uart_SendString("[UART SIM] Set Active App to: Clock\r\n");
}
else if (cmd == '2')
{
current_state = STATE_ARMED;
state_changed = 1;
Uart_SendString("[UART SIM] Set State to: ARMED (Armed)\r\n");
Uart_SendString("[UART SIM] Set State to: ARMED\r\n");
}
else if (cmd == '3')
{
current_state = STATE_DISARMED;
state_changed = 1;
Uart_SendString("[UART SIM] Set State to: DISARMED (Disarmed)\r\n");
Uart_SendString("[UART SIM] Set State to: DISARMED\r\n");
}
else if (cmd == '4')
{
rgb_test_mode = 1;
LED_R = 0; LED_G = 1; LED_B = 1; // 红色亮 (0代表亮)
LED_R = 0; LED_G = 1; LED_B = 1;
Uart_SendString("[UART SIM] RGB Test -> RED\r\n");
}
else if (cmd == '5')
{
rgb_test_mode = 1;
LED_R = 1; LED_G = 0; LED_B = 1; // 绿色亮
LED_R = 1; LED_G = 0; LED_B = 1;
Uart_SendString("[UART SIM] RGB Test -> GREEN\r\n");
}
else if (cmd == '6')
{
rgb_test_mode = 1;
LED_R = 1; LED_G = 1; LED_B = 0; // 蓝色亮
LED_R = 1; LED_G = 1; LED_B = 0;
Uart_SendString("[UART SIM] RGB Test -> BLUE\r\n");
}
else if (cmd == '7')
{
rgb_test_mode = 1;
LED_R = 0; LED_G = 0; LED_B = 1; // 黄色亮 (红+绿)
LED_R = 0; LED_G = 0; LED_B = 1;
Uart_SendString("[UART SIM] RGB Test -> YELLOW\r\n");
}
else if (cmd == '8')
{
rgb_test_mode = 1;
LED_R = 0; LED_G = 1; LED_B = 0; // 紫色亮 (红+蓝)
LED_R = 0; LED_G = 1; LED_B = 0;
Uart_SendString("[UART SIM] RGB Test -> PURPLE\r\n");
}
else if (cmd == '9')
{
rgb_test_mode = 1;
LED_R = 1; LED_G = 0; LED_B = 0; // 青色亮 (绿+蓝)
LED_R = 1; LED_G = 0; LED_B = 0;
Uart_SendString("[UART SIM] RGB Test -> CYAN\r\n");
}
else if (cmd == '0')
{
rgb_test_mode = 1;
LED_R = 0; LED_G = 0; LED_B = 0; // 白色亮 (红+绿+蓝)
LED_R = 0; LED_G = 0; LED_B = 0;
Uart_SendString("[UART SIM] RGB Test -> WHITE\r\n");
}
else if (cmd == 'f' || cmd == 'F')
{
rgb_test_mode = 0;
LED_R = 1; LED_G = 1; LED_B = 1; // 熄灭
Uart_SendString("[UART SIM] RGB Test -> OFF (Normal Mode)\r\n");
LED_R = 1; LED_G = 1; LED_B = 1;
Uart_SendString("[UART SIM] RGB Test -> OFF\r\n");
}
}
// 1. 读取按键事件并自动清空
ev = key_event_buf;
key_event_buf = KEY_EVENT_NONE;
if (ev != KEY_EVENT_NONE)
// 1. 处理按键事件缓冲区(来自定时器中断)
if (key_event_buf != KEY_EVENT_NONE)
{
rgb_test_mode = 0; // 任何物理/按键事件触发时退出 RGB 测试模式
// 通过串口打印获取到的按键事件代号进行测试联调
Uart_SendString("Key Event Captured: ");
Uart_SendHex8((u8)ev);
Uart_SendString("\r\n");
// 根据不同的系统当前状态,执行状态迁移逻辑
if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED)
{
if (ev == KEY_EVENT_UP_DOWN_COMB) // 同时长按 UP + DOWN 3 秒进入配对菜单
{
current_state = STATE_PAIR_MENU;
menu_select = 0;
state_changed = 1;
}
else if (ev == KEY_EVENT_SOS_CLICK) // 短按 SOS 发射 SOS 报警
{
current_state = STATE_SOS_EMITTED;
state_changed = 1;
}
else if (ev == KEY_EVENT_SOS_LONG) // 长按 SOS 5 秒与 IPC 绑定
{
UI_ShowBindingPage();
RF_SetMode(2); // TX mode
EV1527_Transmit(CLONED_ADDR, 0x01); // 对码绑定电报数据为 0x01
RF_SetMode(0); // Idle
Delay_ms(2000); // 维持 2 秒
current_state = STATE_NORMAL;
state_changed = 1;
}
}
else if (current_state == STATE_PAIR_MENU)
{
if (ev == KEY_EVENT_UP_CLICK) // 菜单选择上移
{
if (menu_select > 0)
{
menu_select--;
state_changed = 1;
}
}
else if (ev == KEY_EVENT_DOWN_CLICK) // 菜单选择下移
{
if (menu_select < 4)
{
menu_select++;
state_changed = 1;
}
}
else if (ev == KEY_EVENT_SOS_CLICK) // 单击 SOS 确认选项,进入对码搜索并触发 100ms 短振与白灯快闪
{
MOTOR = 1;
Delay_ms(100);
MOTOR = 0;
current_state = STATE_PAIR_WAIT;
pair_timeout_ms = 0; // 重置对码超时计时器
state_changed = 1;
}
else if (ev == KEY_EVENT_DOWN_LONG) // 长按 DOWN 键 3 秒强行返回待机
{
current_state = STATE_NORMAL;
state_changed = 1;
}
}
else if (current_state == STATE_PAIR_WAIT)
{
if (ev == KEY_EVENT_DOWN_LONG) // 在雷达页面,长按 DOWN 3秒强行退出
{
current_state = STATE_NORMAL;
state_changed = 1;
}
}
else if (current_state == STATE_PAIR_CONFIRM)
{
if (ev == KEY_EVENT_SOS_LONG) // 在确认页面,长按 SOS 3 秒保存对码结果
{
Add_Sensor(captured_addr, captured_type);
current_state = STATE_PAIR_SUCCESS;
state_changed = 1;
}
else if (ev == KEY_EVENT_DOWN_LONG) // 在确认页面,长按 DOWN 3 秒放弃保存返回待机
{
current_state = STATE_NORMAL;
state_changed = 1;
}
}
else if (current_state == STATE_ALARM)
{
// 在防区报警闪烁状态下,短按任意物理按键均可清除报警声光
current_state = STATE_NORMAL;
state_changed = 1;
}
else if (current_state == STATE_SOS_EMITTED)
{
// 再次长按任意物理按键即可主动解除求救模式
if (ev == KEY_EVENT_SOS_LONG || ev == KEY_EVENT_UP_LONG || ev == KEY_EVENT_DOWN_LONG)
{
current_state = STATE_NORMAL;
state_changed = 1;
}
}
}
// 2. 对码雷达扫描 30 秒超时自动跳回时钟主界面检测
if (current_state == STATE_PAIR_WAIT && pair_timeout_ms >= 30000UL)
{
pair_timeout_ms = 0;
UI_ShowPairFailPage(1); // 调用 Fail 绘制接口并传入超时标志 1
Delay_ms(2500); // 维持 2.5 秒超时警告
current_state = STATE_NORMAL;
state_changed = 1;
}
// 3. 状态切换的屏幕重写渲染 (只有发生状态改变才清屏,杜绝频闪)
if (state_changed)
{
state_changed = 0; // 仅在此处清除状态改变标记,确保异步状态转移时屏幕能被正确重绘
rgb_test_mode = 0;
// 通过串口反馈状态机重绘过程
Uart_SendString("State Transition to: ");
Uart_SendHex8((u8)current_state);
Uart_SendString("\r\n");
if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED)
SystemEvent sys_evt;
sys_evt.key_event = key_event_buf;
sys_evt.extra_data = 0;
sys_evt.extra_size = 0;
// 设置事件优先级
if (key_event_buf == KEY_EVENT_SOS_CLICK ||
key_event_buf == KEY_EVENT_SOS_LONG)
{
RF_SetMode(1); // 切回接收模式监听防区
UI_ShowClockPage(current_state, current_hour, current_min);
}
else if (current_state == STATE_PAIR_MENU)
{
RF_SetMode(0); // 关闭射频节省能量
UI_ShowPairMenuPage(menu_select);
}
else if (current_state == STATE_PAIR_WAIT)
{
RF_SetMode(1); // 开启射频解调芯片,开始抓包
LCD_Clear(COLOR_BLACK);
LCD_ShowStringCentered(135, "RECHERCHE...", COLOR_WHITE, COLOR_BLACK);
LCD_ShowStringCentered(160, "DECLENCH. CAPT", COLOR_CYAN, COLOR_BLACK);
UI_ShowPairWaitPage(0);
last_radar_sec = 99; // 强行重置雷达波纹帧计数器
}
else if (current_state == STATE_PAIR_CONFIRM)
{
RF_SetMode(0); // 捕获成功,关闭射频
UI_ShowPairConfirmPage(captured_addr);
}
else if (current_state == STATE_PAIR_SUCCESS)
{
RF_SetMode(0);
UI_ShowPairSuccessPage(captured_addr);
// 触发对码成功物理反馈:强振 1 次 (400ms)LED 绿色常亮 2 秒
MOTOR = 1;
LED_G = 0; // 开启绿灯
LED_R = 1;
LED_B = 1;
Delay_ms(400); // 振动 400ms
MOTOR = 0; // 停止振动
Delay_ms(1600); // 维持绿灯常亮累计满 2 秒 (400 + 1600 = 2000ms)
LED_G = 1; // 熄灭绿灯
Delay_ms(500); // 补齐页面显示总时间 2.5 秒 (2000 + 500 = 2500ms)
current_state = STATE_NORMAL;
UI_ShowClockPage(current_state, current_hour, current_min);
RF_SetMode(1);
}
else if (current_state == STATE_ALARM)
{
u8 slot;
static char alarm_name[24];
char *name = "UNKNOWN SENSOR";
if (Check_Sensor_ID(captured_addr, &slot))
{
Format_Sensor_Name(slot, alarm_name);
name = alarm_name;
alarm_sensor_slot = slot;
}
UI_ShowAlarmPage(name, 1);
}
else if (current_state == STATE_SOS_EMITTED)
{
UI_ShowSosPage();
}
}
// 4. 定期局部刷新、动画更新与射频解调轮询
if (current_state == STATE_NORMAL || current_state == STATE_ARMED || current_state == STATE_DISARMED)
{
// 时钟分钟数字局部刷新 (防闪烁)
if (clock_updated)
{
clock_updated = 0;
UI_ShowClockPage(current_state, current_hour, current_min);
}
// 监听并解析防区发射的信号码
{
u32 rx_addr;
u8 rx_data;
if (EV1527_Decode(&rx_addr, &rx_data))
{
u8 slot;
if (Check_Sensor_ID(rx_addr, &slot)) // 检查接收 of 地址是否在配对列表中
{
u32 slot_addr = ((u32)sensor_list[slot].addr[0] << 16) |
((u32)sensor_list[slot].addr[1] << 8) |
sensor_list[slot].addr[2];
u8 sensor_type = slot_addr & 0x0F;
if (sensor_type < 5) // 仅触发普通防区传感器彻底过滤并排除SOS信号接收
{
u8 zone = default_zones[sensor_type];
// 24小时防区 (zone==0) 任何时候都触发,普通防区 (zone==1) 仅在 ARMED 状态下触发
if (zone == 0 || current_state == STATE_ARMED)
{
captured_addr = rx_addr;
current_state = STATE_ALARM;
state_changed = 1;
}
}
}
}
}
}
else if (current_state == STATE_PAIR_WAIT)
{
// 雷达搜索页面每 250ms 局部刷新一帧雷达天线波纹
u8 frame = (u8)((ms_tick / 250) % 3);
if (frame != last_radar_sec)
{
last_radar_sec = frame;
UI_ShowPairWaitPage(frame);
}
// 在对码搜索状态下监听任意 EV1527 无线电码
{
u32 rx_addr;
u8 rx_data;
if (EV1527_Decode(&rx_addr, &rx_data))
{
captured_addr = rx_addr;
captured_type = menu_select;
current_state = STATE_PAIR_CONFIRM; // 捕获到信号,移至确认页
state_changed = 1;
}
}
}
else if (current_state == STATE_SOS_EMITTED)
{
// 主动 SOS 求救状态下,每 500ms 通过 LT4455 发射一次射频求救帧
u8 sec_phase = (u8)((ms_tick / 500) % 2);
if (sec_phase != last_radar_sec)
{
last_radar_sec = sec_phase;
RF_SetMode(2); // 射频置为发射端模式
EV1527_Transmit(CLONED_ADDR, 0x08); // 发射手环自带地址 CLONED_ADDR 且数据为 0x08
RF_SetMode(0); // 发射完成复位,关闭发射机
}
// 双实线红色警告边框的闪烁效果
if (alarm_flash_flag)
{
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_WHITE);
sys_evt.priority = EVENT_PRIORITY_URGENT;
// 紧急事件直接分发,跳过队列
EventQueue_EmergencyDispatch(sys_evt);
}
else
{
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_BLACK);
sys_evt.priority = EVENT_PRIORITY_NORMAL;
EventQueue_Push(sys_evt);
}
key_event_buf = KEY_EVENT_NONE;
}
else if (current_state == STATE_ALARM)
// 2. 处理事件队列中的事件
while (!EventQueue_IsEmpty())
{
// 警报闪烁状态下,交替绘制红色和黑色边框
if (alarm_flash_flag)
evt = EventQueue_Pop();
if (evt.key_event != KEY_EVENT_NONE || evt.priority != EVENT_PRIORITY_LOW)
{
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
}
else
{
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
Uart_SendString("[EVENT] Processing event: ");
Uart_SendHex8((u8)evt.key_event);
Uart_SendString(" Priority: ");
Uart_SendHex8((u8)evt.priority);
Uart_SendString("\r\n");
AppManager_DispatchEvent(evt);
}
}
// 仿真 LED/马达状态串口输出
// 3. 运行当前活跃应用的 onRun 回调带CPU占用控制
AppManager_RunActiveApp();
// 4. 仿真 LED/马达状态串口输出
if (LED_R != last_led_r || LED_G != last_led_g || LED_B != last_led_b)
{
last_led_r = LED_R;