feat: 实现事件驱动应用框架,支持前台/后台分离、事件优先级和CPU占用控制
This commit is contained in:
262
App/appmgr.c
Normal file
262
App/appmgr.c
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "appmgr.h"
|
||||
#include "../Drivers/lcd.h"
|
||||
|
||||
/* =========================================================================
|
||||
* 应用管理器内部变量
|
||||
* ========================================================================= */
|
||||
|
||||
// 应用注册表:存储所有已注册的应用
|
||||
static WristbandApp app_registry[APP_ID_MAX];
|
||||
|
||||
// 当前活跃的前台应用指针
|
||||
static WristbandApp *active_app = NULL;
|
||||
|
||||
// 默认应用(时钟)
|
||||
#define DEFAULT_APP_ID APP_ID_CLOCK
|
||||
|
||||
/* =========================================================================
|
||||
* 应用生命周期辅助函数
|
||||
* ========================================================================= */
|
||||
|
||||
static void AppManager_ExecuteOnStart(WristbandApp *app)
|
||||
{
|
||||
if (app != NULL && app->OnStart != NULL)
|
||||
{
|
||||
app->OnStart();
|
||||
app->is_active = 1;
|
||||
app->is_running = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void AppManager_ExecuteOnClose(WristbandApp *app)
|
||||
{
|
||||
if (app != NULL && app->onClose != NULL)
|
||||
{
|
||||
app->onClose();
|
||||
app->is_active = 0;
|
||||
app->is_running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void AppManager_ExecuteOnRun(WristbandApp *app)
|
||||
{
|
||||
if (app != NULL && app->onRun != NULL && app->is_running)
|
||||
{
|
||||
// CPU占用控制:记录开始时间
|
||||
u16 start_tick = ms_tick;
|
||||
|
||||
// 执行应用的onRun回调
|
||||
app->onRun();
|
||||
|
||||
// 检测执行时间是否超限
|
||||
u16 elapsed_ticks = ms_tick - start_tick;
|
||||
if (elapsed_ticks > APP_ONRUN_MAX_TICKS)
|
||||
{
|
||||
// 应用执行时间过长,强制标记为非活跃
|
||||
// 但不直接关闭,允许应用在下一次循环中恢复
|
||||
app->is_running = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static EventResult AppManager_ExecuteOnEvent(WristbandApp *app, SystemEvent evt)
|
||||
{
|
||||
if (app != NULL && app->onEvent != NULL)
|
||||
{
|
||||
return app->onEvent(evt);
|
||||
}
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 应用管理器核心实现
|
||||
* ========================================================================= */
|
||||
|
||||
void AppManager_Init(void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
// 初始化所有应用描述符
|
||||
for (i = 0; i < APP_ID_MAX; i++)
|
||||
{
|
||||
app_registry[i].app_id = (AppID)i;
|
||||
app_registry[i].app_type = APP_TYPE_FOREGROUND;
|
||||
app_registry[i].app_name = "UNREGISTERED";
|
||||
app_registry[i].OnStart = NULL;
|
||||
app_registry[i].onRun = NULL;
|
||||
app_registry[i].onClose = NULL;
|
||||
app_registry[i].onEvent = NULL;
|
||||
app_registry[i].is_active = 0;
|
||||
app_registry[i].is_running = 0;
|
||||
}
|
||||
|
||||
// 默认启动时钟应用
|
||||
active_app = &app_registry[DEFAULT_APP_ID];
|
||||
AppManager_ExecuteOnStart(active_app);
|
||||
}
|
||||
|
||||
void AppManager_StartApp(AppID app_id)
|
||||
{
|
||||
// 参数有效性检查
|
||||
if (app_id >= APP_ID_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取目标应用指针
|
||||
WristbandApp *target_app = &app_registry[app_id];
|
||||
|
||||
// 目标应用必须是前台应用
|
||||
if (target_app->app_type != APP_TYPE_FOREGROUND)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 目标应用必须已注册(有OnStart回调)
|
||||
if (target_app->OnStart == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果目标应用已经是活跃应用,直接返回
|
||||
if (active_app == target_app)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 关闭当前活跃应用
|
||||
if (active_app != NULL)
|
||||
{
|
||||
AppManager_ExecuteOnClose(active_app);
|
||||
}
|
||||
|
||||
// 切换到新应用
|
||||
active_app = target_app;
|
||||
|
||||
// 启动新应用
|
||||
AppManager_ExecuteOnStart(active_app);
|
||||
}
|
||||
|
||||
void AppManager_CloseApp(void)
|
||||
{
|
||||
// 关闭当前活跃应用
|
||||
if (active_app != NULL)
|
||||
{
|
||||
AppManager_ExecuteOnClose(active_app);
|
||||
active_app = NULL;
|
||||
}
|
||||
|
||||
// 启动默认应用(时钟)
|
||||
active_app = &app_registry[DEFAULT_APP_ID];
|
||||
AppManager_ExecuteOnStart(active_app);
|
||||
}
|
||||
|
||||
AppID AppManager_GetActiveAppID(void)
|
||||
{
|
||||
if (active_app != NULL)
|
||||
{
|
||||
return active_app->app_id;
|
||||
}
|
||||
return DEFAULT_APP_ID;
|
||||
}
|
||||
|
||||
void AppManager_DispatchEvent(SystemEvent evt)
|
||||
{
|
||||
EventResult result;
|
||||
|
||||
// 步骤1:优先分发给当前活跃的前台应用
|
||||
if (active_app != NULL && active_app->is_active)
|
||||
{
|
||||
result = AppManager_ExecuteOnEvent(active_app, evt);
|
||||
|
||||
// 前台应用已处理,无需继续分发
|
||||
if (result == EVENT_HANDLED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤2:前台未处理,分发给所有后台应用
|
||||
// 遍历应用注册表,找到所有后台应用
|
||||
u8 i;
|
||||
for (i = 0; i < APP_ID_MAX; i++)
|
||||
{
|
||||
WristbandApp *bg_app = &app_registry[i];
|
||||
|
||||
// 跳过前台应用和未注册应用
|
||||
if (bg_app->app_type != APP_TYPE_BACKGROUND ||
|
||||
bg_app->onEvent == NULL ||
|
||||
!bg_app->is_running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 调用后台应用的事件处理函数
|
||||
result = AppManager_ExecuteOnEvent(bg_app, evt);
|
||||
|
||||
// 如果后台应用处理了事件,停止继续分发
|
||||
if (result == EVENT_HANDLED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤3:所有应用都未处理,事件被丢弃
|
||||
// 可以在这里添加日志记录(如果需要)
|
||||
}
|
||||
|
||||
void AppManager_RunActiveApp(void)
|
||||
{
|
||||
// 执行当前活跃应用的onRun回调(带CPU占用控制)
|
||||
if (active_app != NULL && active_app->is_active)
|
||||
{
|
||||
AppManager_ExecuteOnRun(active_app);
|
||||
}
|
||||
}
|
||||
|
||||
void AppManager_BroadcastToBackground(SystemEvent evt)
|
||||
{
|
||||
// 广播事件给所有后台应用
|
||||
u8 i;
|
||||
for (i = 0; i < APP_ID_MAX; i++)
|
||||
{
|
||||
WristbandApp *bg_app = &app_registry[i];
|
||||
|
||||
// 仅发送给后台应用
|
||||
if (bg_app->app_type == APP_TYPE_BACKGROUND &&
|
||||
bg_app->onEvent != NULL &&
|
||||
bg_app->is_running)
|
||||
{
|
||||
AppManager_ExecuteOnEvent(bg_app, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 应用注册接口(供各应用模块调用)
|
||||
* ========================================================================= */
|
||||
|
||||
void AppManager_RegisterApp(AppID app_id, AppType app_type, char *app_name,
|
||||
AppStartFunc on_start, AppRunFunc on_run,
|
||||
AppCloseFunc on_close, AppEventFunc on_event)
|
||||
{
|
||||
if (app_id >= APP_ID_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WristbandApp *app = &app_registry[app_id];
|
||||
|
||||
app->app_type = app_type;
|
||||
app->app_name = app_name;
|
||||
app->OnStart = on_start;
|
||||
app->onRun = on_run;
|
||||
app->onClose = on_close;
|
||||
app->onEvent = on_event;
|
||||
|
||||
// 后台应用默认处于运行状态
|
||||
if (app_type == APP_TYPE_BACKGROUND)
|
||||
{
|
||||
app->is_running = 1;
|
||||
}
|
||||
}
|
||||
33
App/appmgr.h
Normal file
33
App/appmgr.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __APPMGR_H__
|
||||
#define __APPMGR_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* =========================================================================
|
||||
* 应用管理器接口声明
|
||||
* ========================================================================= */
|
||||
|
||||
// 初始化应用管理器,注册所有应用
|
||||
void AppManager_Init(void);
|
||||
|
||||
// 启动指定应用(切换前台)
|
||||
// 参数:app_id - 目标应用ID
|
||||
void AppManager_StartApp(AppID app_id);
|
||||
|
||||
// 关闭当前前台应用,回退到默认应用(时钟)
|
||||
void AppManager_CloseApp(void);
|
||||
|
||||
// 获取当前活跃的前台应用ID
|
||||
AppID AppManager_GetActiveAppID(void);
|
||||
|
||||
// 事件分发函数:将事件分发给前台/后台应用
|
||||
// 分发逻辑:前台应用优先处理 -> 后台应用兜底处理 -> 未处理则丢弃
|
||||
void AppManager_DispatchEvent(SystemEvent evt);
|
||||
|
||||
// 运行当前活跃应用的onRun回调(带CPU占用控制)
|
||||
void AppManager_RunActiveApp(void);
|
||||
|
||||
// 广播事件给所有后台应用(用于系统级事件)
|
||||
void AppManager_BroadcastToBackground(SystemEvent evt);
|
||||
|
||||
#endif
|
||||
497
App/apps.c
Normal file
497
App/apps.c
Normal file
@@ -0,0 +1,497 @@
|
||||
#include "config.h"
|
||||
#include "appmgr.h"
|
||||
#include "../Drivers/lcd.h"
|
||||
#include "../Drivers/rf.h"
|
||||
|
||||
/* =========================================================================
|
||||
* 全局变量声明(从 main.c 迁移)
|
||||
* ========================================================================= */
|
||||
|
||||
extern volatile u16 ms_tick;
|
||||
extern volatile u32 pair_timeout_ms;
|
||||
extern volatile u16 alarm_timer_ms;
|
||||
extern volatile bit alarm_flash_flag;
|
||||
|
||||
extern SystemState current_state;
|
||||
extern u8 current_hour, current_min;
|
||||
extern u8 menu_select;
|
||||
extern u32 captured_addr;
|
||||
extern u8 captured_type;
|
||||
extern u8 alarm_sensor_slot;
|
||||
|
||||
extern Sensor_Slot xdata sensor_list[16];
|
||||
|
||||
extern sbit MOTOR;
|
||||
extern bit LED_R, LED_G, LED_B;
|
||||
extern bit rgb_test_mode;
|
||||
|
||||
extern char *code default_names[5];
|
||||
extern u8 code default_zones[5];
|
||||
extern char *code menu_items[5];
|
||||
|
||||
extern void Delay_ms(u16 ms);
|
||||
extern void Format_Sensor_Name(u8 slot, char *buf);
|
||||
extern void Uart_SendString(char *s);
|
||||
extern void Uart_SendHex8(u8 val);
|
||||
|
||||
/* =========================================================================
|
||||
* 应用私有状态变量
|
||||
* ========================================================================= */
|
||||
|
||||
// 时钟应用状态
|
||||
static bit clock_redraw_flag = 0;
|
||||
|
||||
// 配对应用状态
|
||||
static u8 pair_menu_select = 0;
|
||||
static u8 pair_state = 0; // 0: MENU, 1: WAIT, 2: CONFIRM, 3: SUCCESS, 4: FAIL
|
||||
|
||||
// 报警应用状态
|
||||
static u8 alarm_last_frame = 99;
|
||||
|
||||
// SOS应用状态
|
||||
static u8 sos_last_tx = 99;
|
||||
|
||||
/* =========================================================================
|
||||
* 时钟应用实现
|
||||
* ========================================================================= */
|
||||
|
||||
static void ClockApp_OnStart(void)
|
||||
{
|
||||
Uart_SendString("[APP] ClockApp Started\r\n");
|
||||
current_state = STATE_NORMAL;
|
||||
clock_redraw_flag = 1;
|
||||
}
|
||||
|
||||
static void ClockApp_onRun(void)
|
||||
{
|
||||
// 分钟变化时重绘时钟
|
||||
if (clock_redraw_flag)
|
||||
{
|
||||
clock_redraw_flag = 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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
u8 zone = default_zones[sensor_type];
|
||||
if (zone == 0 || current_state == STATE_ARMED)
|
||||
{
|
||||
captured_addr = rx_addr;
|
||||
alarm_sensor_slot = slot;
|
||||
AppManager_StartApp(APP_ID_ALARM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ClockApp_onClose(void)
|
||||
{
|
||||
Uart_SendString("[APP] ClockApp Closed\r\n");
|
||||
}
|
||||
|
||||
static EventResult ClockApp_onEvent(SystemEvent evt)
|
||||
{
|
||||
// 处理定时器发送的时钟更新事件(priority为LOW,key_event为NONE)
|
||||
if (evt.key_event == KEY_EVENT_NONE && evt.priority == EVENT_PRIORITY_LOW)
|
||||
{
|
||||
// 从extra_data中提取时间信息
|
||||
u8 hour = (u8)(evt.extra_data >> 8);
|
||||
u8 min = (u8)(evt.extra_data & 0xFF);
|
||||
|
||||
// 更新时钟显示
|
||||
UI_ShowClockPage(current_state, hour, min);
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
|
||||
switch (evt.key_event)
|
||||
{
|
||||
case KEY_EVENT_UP_DOWN_COMB:
|
||||
// 组合键进入菜单
|
||||
AppManager_StartApp(APP_ID_MENU);
|
||||
return EVENT_HANDLED;
|
||||
|
||||
case KEY_EVENT_SOS_CLICK:
|
||||
// 短按SOS进入求救模式
|
||||
AppManager_StartApp(APP_ID_SOS);
|
||||
return EVENT_HANDLED;
|
||||
|
||||
case KEY_EVENT_SOS_LONG:
|
||||
// 长按SOS绑定IPC
|
||||
UI_ShowBindingPage();
|
||||
RF_SetMode(2);
|
||||
EV1527_Transmit(CLONED_ADDR, 0x01);
|
||||
RF_SetMode(0);
|
||||
Delay_ms(2000);
|
||||
AppManager_StartApp(APP_ID_CLOCK);
|
||||
return EVENT_HANDLED;
|
||||
|
||||
default:
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 菜单应用实现
|
||||
* ========================================================================= */
|
||||
|
||||
static void MenuApp_OnStart(void)
|
||||
{
|
||||
Uart_SendString("[APP] MenuApp Started\r\n");
|
||||
pair_menu_select = 0;
|
||||
RF_SetMode(0);
|
||||
UI_ShowPairMenuPage(pair_menu_select);
|
||||
}
|
||||
|
||||
static void MenuApp_onRun(void)
|
||||
{
|
||||
// 菜单应用无持续运行逻辑
|
||||
}
|
||||
|
||||
static void MenuApp_onClose(void)
|
||||
{
|
||||
Uart_SendString("[APP] MenuApp Closed\r\n");
|
||||
RF_SetMode(1);
|
||||
}
|
||||
|
||||
static EventResult MenuApp_onEvent(SystemEvent evt)
|
||||
{
|
||||
switch (evt.key_event)
|
||||
{
|
||||
case KEY_EVENT_UP_CLICK:
|
||||
if (pair_menu_select > 0)
|
||||
{
|
||||
pair_menu_select--;
|
||||
UI_ShowPairMenuPage(pair_menu_select);
|
||||
}
|
||||
return EVENT_HANDLED;
|
||||
|
||||
case KEY_EVENT_DOWN_CLICK:
|
||||
if (pair_menu_select < 4)
|
||||
{
|
||||
pair_menu_select++;
|
||||
UI_ShowPairMenuPage(pair_menu_select);
|
||||
}
|
||||
return EVENT_HANDLED;
|
||||
|
||||
case KEY_EVENT_SOS_CLICK:
|
||||
// 确认进入配对等待
|
||||
MOTOR = 1;
|
||||
Delay_ms(100);
|
||||
MOTOR = 0;
|
||||
|
||||
AppManager_StartApp(APP_ID_PAIR);
|
||||
return EVENT_HANDLED;
|
||||
|
||||
case KEY_EVENT_DOWN_LONG:
|
||||
// 长按返回时钟
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
|
||||
default:
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 配对应用实现
|
||||
* ========================================================================= */
|
||||
|
||||
static void PairApp_OnStart(void)
|
||||
{
|
||||
Uart_SendString("[APP] PairApp Started\r\n");
|
||||
pair_state = 1; // 进入等待状态
|
||||
pair_timeout_ms = 0;
|
||||
captured_type = pair_menu_select;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void PairApp_onRun(void)
|
||||
{
|
||||
switch (pair_state)
|
||||
{
|
||||
case 1: // WAIT状态
|
||||
{
|
||||
// 雷达动画
|
||||
u8 frame = (u8)((ms_tick / 250) % 3);
|
||||
static u8 last_frame = 99;
|
||||
if (frame != last_frame)
|
||||
{
|
||||
last_frame = frame;
|
||||
UI_ShowPairWaitPage(frame);
|
||||
}
|
||||
|
||||
// 监听射频信号
|
||||
u32 rx_addr;
|
||||
u8 rx_data;
|
||||
if (EV1527_Decode(&rx_addr, &rx_data))
|
||||
{
|
||||
captured_addr = rx_addr;
|
||||
pair_state = 2; // 进入确认状态
|
||||
|
||||
RF_SetMode(0);
|
||||
UI_ShowPairConfirmPage(captured_addr);
|
||||
}
|
||||
|
||||
// 超时检测
|
||||
if (pair_timeout_ms >= 30000UL)
|
||||
{
|
||||
pair_timeout_ms = 0;
|
||||
UI_ShowPairFailPage(1);
|
||||
Delay_ms(2500);
|
||||
AppManager_CloseApp();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // CONFIRM状态
|
||||
// 等待用户操作
|
||||
break;
|
||||
|
||||
case 3: // SUCCESS状态
|
||||
// 成功动画已在事件处理中完成
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void PairApp_onClose(void)
|
||||
{
|
||||
Uart_SendString("[APP] PairApp Closed\r\n");
|
||||
RF_SetMode(1);
|
||||
pair_state = 0;
|
||||
}
|
||||
|
||||
static EventResult PairApp_onEvent(SystemEvent evt)
|
||||
{
|
||||
switch (pair_state)
|
||||
{
|
||||
case 1: // WAIT状态
|
||||
{
|
||||
if (evt.key_event == KEY_EVENT_DOWN_LONG)
|
||||
{
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // CONFIRM状态
|
||||
{
|
||||
if (evt.key_event == KEY_EVENT_SOS_LONG)
|
||||
{
|
||||
// 保存对码
|
||||
Add_Sensor(captured_addr, captured_type);
|
||||
|
||||
pair_state = 3; // 进入成功状态
|
||||
UI_ShowPairSuccessPage(captured_addr);
|
||||
|
||||
// 物理反馈
|
||||
MOTOR = 1;
|
||||
LED_G = 0;
|
||||
LED_R = 1;
|
||||
LED_B = 1;
|
||||
Delay_ms(400);
|
||||
MOTOR = 0;
|
||||
|
||||
Delay_ms(1600);
|
||||
LED_G = 1;
|
||||
|
||||
Delay_ms(500);
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
else if (evt.key_event == KEY_EVENT_DOWN_LONG)
|
||||
{
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 报警应用实现
|
||||
* ========================================================================= */
|
||||
|
||||
static void AlarmApp_OnStart(void)
|
||||
{
|
||||
Uart_SendString("[APP] AlarmApp Started\r\n");
|
||||
current_state = STATE_ALARM;
|
||||
|
||||
u8 slot = alarm_sensor_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;
|
||||
}
|
||||
|
||||
UI_ShowAlarmPage(name, 1);
|
||||
|
||||
// 重置报警定时器
|
||||
alarm_timer_ms = 0;
|
||||
}
|
||||
|
||||
static void AlarmApp_onRun(void)
|
||||
{
|
||||
// 警报边框闪烁效果
|
||||
if (alarm_flash_flag)
|
||||
{
|
||||
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
static void AlarmApp_onClose(void)
|
||||
{
|
||||
Uart_SendString("[APP] AlarmApp Closed\r\n");
|
||||
current_state = STATE_NORMAL;
|
||||
|
||||
// 停止报警效果
|
||||
MOTOR = 0;
|
||||
LED_R = 1;
|
||||
LED_G = 1;
|
||||
LED_B = 1;
|
||||
}
|
||||
|
||||
static EventResult AlarmApp_onEvent(SystemEvent evt)
|
||||
{
|
||||
// 任何按键都可以清除报警
|
||||
if (evt.key_event != KEY_EVENT_NONE)
|
||||
{
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* SOS应用实现
|
||||
* ========================================================================= */
|
||||
|
||||
static void SOSApp_OnStart(void)
|
||||
{
|
||||
Uart_SendString("[APP] SOSApp Started\r\n");
|
||||
current_state = STATE_SOS_EMITTED;
|
||||
UI_ShowSosPage();
|
||||
}
|
||||
|
||||
static void SOSApp_onRun(void)
|
||||
{
|
||||
// 每500ms发射一次射频求救帧
|
||||
u8 sec_phase = (u8)((ms_tick / 500) % 2);
|
||||
if (sec_phase != sos_last_tx)
|
||||
{
|
||||
sos_last_tx = sec_phase;
|
||||
RF_SetMode(2);
|
||||
EV1527_Transmit(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);
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
|
||||
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
static void SOSApp_onClose(void)
|
||||
{
|
||||
Uart_SendString("[APP] SOSApp Closed\r\n");
|
||||
current_state = STATE_NORMAL;
|
||||
|
||||
// 停止求救效果
|
||||
MOTOR = 0;
|
||||
LED_R = 1;
|
||||
LED_G = 1;
|
||||
LED_B = 1;
|
||||
}
|
||||
|
||||
static EventResult SOSApp_onEvent(SystemEvent evt)
|
||||
{
|
||||
// 长按任意键解除求救
|
||||
if (evt.key_event == KEY_EVENT_SOS_LONG ||
|
||||
evt.key_event == KEY_EVENT_UP_LONG ||
|
||||
evt.key_event == KEY_EVENT_DOWN_LONG)
|
||||
{
|
||||
AppManager_CloseApp();
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
|
||||
return EVENT_IGNORED;
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 应用注册函数
|
||||
* ========================================================================= */
|
||||
|
||||
void Apps_RegisterAll(void)
|
||||
{
|
||||
// 注册时钟应用(前台)
|
||||
AppManager_RegisterApp(APP_ID_CLOCK, APP_TYPE_FOREGROUND, "Clock",
|
||||
ClockApp_OnStart, ClockApp_onRun,
|
||||
ClockApp_onClose, ClockApp_onEvent);
|
||||
|
||||
// 注册菜单应用(前台)
|
||||
AppManager_RegisterApp(APP_ID_MENU, APP_TYPE_FOREGROUND, "Menu",
|
||||
MenuApp_OnStart, MenuApp_onRun,
|
||||
MenuApp_onClose, MenuApp_onEvent);
|
||||
|
||||
// 注册配对应用(前台)
|
||||
AppManager_RegisterApp(APP_ID_PAIR, APP_TYPE_FOREGROUND, "Pair",
|
||||
PairApp_OnStart, PairApp_onRun,
|
||||
PairApp_onClose, PairApp_onEvent);
|
||||
|
||||
// 注册报警应用(前台)
|
||||
AppManager_RegisterApp(APP_ID_ALARM, APP_TYPE_FOREGROUND, "Alarm",
|
||||
AlarmApp_OnStart, AlarmApp_onRun,
|
||||
AlarmApp_onClose, AlarmApp_onEvent);
|
||||
|
||||
// 注册SOS应用(前台)
|
||||
AppManager_RegisterApp(APP_ID_SOS, APP_TYPE_FOREGROUND, "SOS",
|
||||
SOSApp_OnStart, SOSApp_onRun,
|
||||
SOSApp_onClose, SOSApp_onEvent);
|
||||
|
||||
Uart_SendString("[APP] All applications registered\r\n");
|
||||
}
|
||||
70
App/config.h
70
App/config.h
@@ -37,6 +37,76 @@ typedef struct {
|
||||
unsigned char addr[3]; // 24位对码地址 (EV1527 20位物理地址 + 4位状态数据码)
|
||||
} Sensor_Slot;
|
||||
|
||||
/* =========================================================================
|
||||
* 应用框架核心定义
|
||||
* ========================================================================= */
|
||||
|
||||
// 应用ID定义
|
||||
typedef enum {
|
||||
APP_ID_CLOCK, // 0: 待机时钟应用
|
||||
APP_ID_MENU, // 1: 主菜单应用
|
||||
APP_ID_PAIR, // 2: 配对与微调应用
|
||||
APP_ID_ALARM, // 3: 传感器报警应用
|
||||
APP_ID_SOS, // 4: 主动求救应用
|
||||
APP_ID_MAX // 应用数量上限
|
||||
} AppID;
|
||||
|
||||
// 应用类型枚举
|
||||
typedef enum {
|
||||
APP_TYPE_FOREGROUND, // 前台应用:独占屏幕和用户交互
|
||||
APP_TYPE_BACKGROUND // 后台应用:无屏幕显示,仅监听事件
|
||||
} AppType;
|
||||
|
||||
// 事件处理返回值
|
||||
typedef enum {
|
||||
EVENT_HANDLED, // 事件已处理
|
||||
EVENT_IGNORED // 事件未处理,继续传递给下一个应用
|
||||
} EventResult;
|
||||
|
||||
// 事件优先级枚举
|
||||
typedef enum {
|
||||
EVENT_PRIORITY_LOW, // 低优先级:普通按键等
|
||||
EVENT_PRIORITY_NORMAL, // 正常优先级:大部分事件
|
||||
EVENT_PRIORITY_HIGH, // 高优先级:报警相关
|
||||
EVENT_PRIORITY_URGENT // 紧急优先级:SOS等,直接越过队列
|
||||
} EventPriority;
|
||||
|
||||
// 扩展事件结构体
|
||||
typedef struct {
|
||||
KeyEvent key_event; // 原始按键事件
|
||||
EventPriority priority; // 事件优先级
|
||||
u32 extra_data; // 额外数据(如射频地址等)
|
||||
u8 extra_size; // 额外数据大小
|
||||
} SystemEvent;
|
||||
|
||||
// 应用生命周期回调函数类型
|
||||
typedef void (*AppStartFunc)(void);
|
||||
typedef void (*AppRunFunc)(void);
|
||||
typedef void (*AppCloseFunc)(void);
|
||||
typedef EventResult (*AppEventFunc)(SystemEvent evt);
|
||||
|
||||
// 应用描述符结构体
|
||||
typedef struct {
|
||||
AppID app_id; // 应用唯一标识
|
||||
AppType app_type; // 应用类型(前台/后台)
|
||||
char *app_name; // 应用名称(用于调试)
|
||||
|
||||
AppStartFunc OnStart; // 启动回调:应用切入前台,加载资源、初始化显示
|
||||
AppRunFunc onRun; // 循环回调:主循环轮询调用,执行非阻塞业务逻辑
|
||||
AppCloseFunc onClose; // 关闭回调:应用退出前台,保存状态、清理外设
|
||||
AppEventFunc onEvent; // 事件回调:接收并处理来自事件层的系统事件
|
||||
|
||||
bit is_active; // 当前是否活跃(仅对前台应用有效)
|
||||
bit is_running; // 应用是否处于运行状态
|
||||
} WristbandApp;
|
||||
|
||||
/* =========================================================================
|
||||
* 事件队列配置
|
||||
* ========================================================================= */
|
||||
|
||||
#define EVENT_QUEUE_DEPTH 8 // 事件队列深度(环形缓冲区大小)
|
||||
#define APP_ONRUN_MAX_TICKS 5 // onRun最大执行时间限制(单位:1ms tick)
|
||||
|
||||
#define MAIN_Fosc 24000000UL
|
||||
#define CLONED_ADDR 0x37A86UL
|
||||
|
||||
|
||||
121
App/event.c
Normal file
121
App/event.c
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "event.h"
|
||||
|
||||
/* =========================================================================
|
||||
* 事件队列内部变量
|
||||
* ========================================================================= */
|
||||
|
||||
// 环形缓冲区存储数组
|
||||
static SystemEvent event_queue[EVENT_QUEUE_DEPTH];
|
||||
|
||||
// 队列读写指针
|
||||
static u8 queue_head = 0; // 读指针:指向即将读取的位置
|
||||
static u8 queue_tail = 0; // 写指针:指向即将写入的位置
|
||||
static u8 queue_count = 0; // 当前队列中的事件数量
|
||||
|
||||
// 队列锁标志(用于中断保护)
|
||||
static bit queue_locked = 0;
|
||||
|
||||
/* =========================================================================
|
||||
* 事件队列核心实现
|
||||
* ========================================================================= */
|
||||
|
||||
void EventQueue_Init(void)
|
||||
{
|
||||
queue_head = 0;
|
||||
queue_tail = 0;
|
||||
queue_count = 0;
|
||||
queue_locked = 0;
|
||||
}
|
||||
|
||||
bit EventQueue_IsEmpty(void)
|
||||
{
|
||||
return (queue_count == 0);
|
||||
}
|
||||
|
||||
bit EventQueue_IsFull(void)
|
||||
{
|
||||
return (queue_count >= EVENT_QUEUE_DEPTH);
|
||||
}
|
||||
|
||||
u8 EventQueue_GetCount(void)
|
||||
{
|
||||
return queue_count;
|
||||
}
|
||||
|
||||
bit EventQueue_Push(SystemEvent evt)
|
||||
{
|
||||
// 队列已满,丢弃事件
|
||||
if (EventQueue_IsFull())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 禁用中断保护队列操作
|
||||
EA = 0;
|
||||
|
||||
// 将事件写入环形缓冲区
|
||||
event_queue[queue_tail] = evt;
|
||||
|
||||
// 更新写指针(循环递增)
|
||||
queue_tail++;
|
||||
if (queue_tail >= EVENT_QUEUE_DEPTH)
|
||||
{
|
||||
queue_tail = 0;
|
||||
}
|
||||
|
||||
// 更新事件计数
|
||||
queue_count++;
|
||||
|
||||
// 恢复中断
|
||||
EA = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SystemEvent EventQueue_Pop(void)
|
||||
{
|
||||
SystemEvent evt;
|
||||
|
||||
// 初始化返回的空事件
|
||||
evt.key_event = KEY_EVENT_NONE;
|
||||
evt.priority = EVENT_PRIORITY_LOW;
|
||||
evt.extra_data = 0;
|
||||
evt.extra_size = 0;
|
||||
|
||||
// 队列为空,返回空事件
|
||||
if (EventQueue_IsEmpty())
|
||||
{
|
||||
return evt;
|
||||
}
|
||||
|
||||
// 禁用中断保护队列操作
|
||||
EA = 0;
|
||||
|
||||
// 从队列头部读取事件
|
||||
evt = event_queue[queue_head];
|
||||
|
||||
// 更新读指针(循环递增)
|
||||
queue_head++;
|
||||
if (queue_head >= EVENT_QUEUE_DEPTH)
|
||||
{
|
||||
queue_head = 0;
|
||||
}
|
||||
|
||||
// 更新事件计数
|
||||
queue_count--;
|
||||
|
||||
// 恢复中断
|
||||
EA = 1;
|
||||
|
||||
return evt;
|
||||
}
|
||||
|
||||
// 外部声明:应用管理器的事件分发函数
|
||||
extern void AppManager_DispatchEvent(SystemEvent evt);
|
||||
|
||||
void EventQueue_EmergencyDispatch(SystemEvent evt)
|
||||
{
|
||||
// 紧急事件直接调用应用管理器分发,跳过队列
|
||||
// 这种方式用于SOS等最高优先级事件,确保立即响应
|
||||
AppManager_DispatchEvent(evt);
|
||||
}
|
||||
33
App/event.h
Normal file
33
App/event.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __EVENT_H__
|
||||
#define __EVENT_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* =========================================================================
|
||||
* 事件队列模块接口声明
|
||||
* ========================================================================= */
|
||||
|
||||
// 初始化事件队列
|
||||
void EventQueue_Init(void);
|
||||
|
||||
// 将事件推入队列(非阻塞)
|
||||
// 返回值:1-成功,0-队列已满
|
||||
bit EventQueue_Push(SystemEvent evt);
|
||||
|
||||
// 从队列头部弹出一个事件
|
||||
// 返回值:事件结构体,若队列为空则 key_event 为 KEY_EVENT_NONE
|
||||
SystemEvent EventQueue_Pop(void);
|
||||
|
||||
// 判断队列是否为空
|
||||
bit EventQueue_IsEmpty(void);
|
||||
|
||||
// 判断队列是否已满
|
||||
bit EventQueue_IsFull(void);
|
||||
|
||||
// 获取队列中事件数量
|
||||
u8 EventQueue_GetCount(void);
|
||||
|
||||
// 紧急事件直通函数:跳过队列直接发送给应用层
|
||||
void EventQueue_EmergencyDispatch(SystemEvent evt);
|
||||
|
||||
#endif
|
||||
467
App/main.c
467
App/main.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user