feat: 增加调试串口指令 'q'/'Q',支持自动轮流点亮红、绿、蓝三色以校准物理灯珠通道顺序

This commit is contained in:
2026-07-30 13:46:44 +08:00
parent be397fba76
commit 41bb78aa59
2 changed files with 141 additions and 103 deletions

View File

@@ -69,13 +69,13 @@ static void SOSApp_onRun(void)
XTELL_LOG("[SOSApp] SOS Radio packet emitted\r\n"); XTELL_LOG("[SOSApp] SOS Radio packet emitted\r\n");
} }
// ====== 2. 控制 RGB 双灯珠以 300ms 周期进行特定的交替闪烁 ====== // ====== 2. 控制 RGB 双灯珠以 50ms 频率进行高频左右交替红蓝爆闪 ======
{ {
u8 flash = (ms_tick / 300) % 2; u8 flash = (ms_tick / 50) % 2;
if (flash) { if (flash) {
RGB_Send(0, 200, 0, 0, 0, 0); // 灯1先亮红灯2灭 RGB_Send(0, 200, 0, 0, 0, 200); // 灯 1 亮红 (GRB 中 R=200),灯 2 亮蓝 (B=200)
} else { } else {
RGB_Send(0, 0, 200, 0, 200, 0); // 灯1变蓝灯2亮红 RGB_Send(0, 0, 200, 0, 200, 0); // 灯 1 亮蓝,灯 2 亮红
} }
} }

View File

@@ -11,54 +11,90 @@
/* ========================================================================= /* =========================================================================
* 系统全局变量定义 * 系统全局变量定义
* ========================================================================= */ * ========================================================================= */
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默为正常时钟待机 SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默<EFBFBD><EFBFBD>为正常时钟待机<EFBFBD><EFBFBD>
u8 menu_select = 0; // 主菜单当前选中的行高亮索引 (0~2) u8 menu_select = 0; // 主菜单当前<EFBFBD><EFBFBD>中的<EFBFBD><EFBFBD><EFBFBD><EFBFBD>索引 (0~2)
u32 captured_addr = 0; // 配对或报警时,捕获到的传感器 24 EV1527 射物理地 u32 captured_addr = 0; // 配<EFBFBD><EFBFBD>或报<EFBFBD><EFBFBD>时,捕获到的传感器 24 <EFBFBD><EFBFBD> EV1527 射<EFBFBD><EFBFBD>物理地<EFBFBD><EFBFBD>
u8 captured_type = 0; // 正在对码或触发报的传感器设备类型 (0:门, 1:PIR...) u8 captured_type = 0; // 正在对码或触发<EFBFBD><EFBFBD>报的传感器设<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (0:门<EFBFBD>, 1:PIR...)
u8 alarm_sensor_slot = 0; // 触发警报的传感器 sensor_list 数组的索引槽位号 u8 alarm_sensor_slot = 0; // 触发警报的传感器<EFBFBD><EFBFBD> sensor_list 数组<EFBFBD><EFBFBD>的索引槽位号
// 传感器存储列表数库,位于单片机部 XDATA 存储空间,共 16 槽位 // 传感器存储列表数<EFBFBD><EFBFBD>库,位于单片机<EFBFBD><EFBFBD>部 XDATA 存储空间,<EFBFBD><EFBFBD>共 16 <EFBFBD><EFBFBD>槽位
Sensor_Slot xdata sensor_list[16]; Sensor_Slot xdata sensor_list[16];
// 全局滴答与定时中计数变量,位 volatile 防止被编译器优 // 全局滴答与定时中<EFBFBD><EFBFBD>计数变量,位<EFBFBD><EFBFBD> volatile 防<EFBFBD><EFBFBD><EFBFBD>编译器优<EFBFBD><EFBFBD>
volatile u16 ms_tick = 0; // 定时中断 1ms 基准滴答加器 volatile u16 ms_tick = 0; // 定时<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 基准滴答<EFBFBD><EFBFBD>加器
volatile u16 inactivity_timer = 0; // 用户闲置计时,用于无操作判定(单: 10ms volatile u16 inactivity_timer = 0; // 用户闲置计时<EFBFBD><EFBFBD>,用于无操作判定(单<EFBFBD><EFBFBD>: 10ms<EFBFBD><EFBFBD>
volatile u32 pair_timeout_ms = 0; // 传感器配对码超时毫秒计时器 (上限 30000ms 30s) volatile u32 pair_timeout_ms = 0; // 传感器配对<EFBFBD><EFBFBD>码超时<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (上限 30000ms <EFBFBD><EFBFBD> 30s)
volatile u16 alarm_timer_ms = 0; // 入侵报马达震动时序计数器 volatile u16 alarm_timer_ms = 0; // 入侵报<EFBFBD><EFBFBD>马达震动时序<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 motor_timer_ms = 0; // 立马达震动时长计数器 volatile u16 motor_timer_ms = 0; // <EFBFBD><EFBFBD>立马达震动时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile bit alarm_flash_flag = 0; // 报警时红框周期性闪烁亮灭标志位 volatile bit alarm_flash_flag = 0; // 报<EFBFBD><EFBFBD>时红<EFBFBD><EFBFBD>周期<EFBFBD><EFBFBD>闪烁亮<EFBFBD><EFBFBD>标志<EFBFBD><EFBFBD>
// 物理按键描与消抖长按计数 (10ms 扫描一次) // 物理按键<EFBFBD><EFBFBD>描与消抖长按计数<EFBFBD><EFBFBD> (10ms <EFBFBD><EFBFBD>描一<EFBFBD><EFBFBD>)
volatile u16 key_scan_timer = 0; // 10ms 描周期分频器 volatile u16 key_scan_timer = 0; // 10ms <EFBFBD><EFBFBD>描周期分频器
volatile u16 key_up_hold = 0; // (KEY_UP) 按下时长累加 volatile u16 key_up_hold = 0; // <EFBFBD><EFBFBD> (KEY_UP) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_down_hold = 0; // (KEY_DOWN) 按下时长累加 volatile u16 key_down_hold = 0; // <EFBFBD><EFBFBD> (KEY_DOWN) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_confirm_hold = 0; // (KEY_CONFIRM) 按下时长累加 volatile u16 key_confirm_hold = 0; // <EFBFBD><EFBFBD> (KEY_CONFIRM) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_sos_hold = 0; // SOS 按下时长累加 volatile u16 key_sos_hold = 0; // SOS 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 comb_hold = 0; // + 组合按下时长累加 volatile u16 comb_hold = 0; // <EFBFBD><EFBFBD> + <EFBFBD><EFBFBD> 组合<EFBFBD><EFBFBD>按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* ========================================================================= /* =========================================================================
* 串口调试指令解析与事件派发封 * 串口调试指令解析与事件派发封<EFBFBD><EFBFBD>
* ========================================================================= */ * ========================================================================= */
/** /**
* @brief 解析通过串口 1 发来的键盘及测试模拟指令 * @brief 解析通过串口 1 发<EFBFBD><EFBFBD>来的键盘及测试模拟指令
* @param cmd 接收到的 ASCII 字符命令 * @param cmd 接收到的 ASCII 字<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @details 负责将字符指令转化应的系统按或射频事件,并推入事件队列以测试件架构: * @details 负责将字符指令转化<EFBFBD><EFBFBD>应的系统按<EFBFBD><EFBFBD>或射频事件,并推入事件队列以测试<EFBFBD><EFBFBD>件架构:
* - 'u'/'U': 模拟短按/长按 ▲ 键。 * - 'u'/'U': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 <20><> <20><><EFBFBD><EFBFBD>
* - 'd'/'D': 模拟短按/长按 ▼ 键。 * - 'd'/'D': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 <20><> <20><><EFBFBD><EFBFBD>
* - 's'/'S': 模拟短按/长按 SOS 物理(优先插入队首) * - 's'/'S': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 SOS 物理<EFBFBD><EFBFBD>(优先插入队首)<EFBFBD><EFBFBD>
* - 'c'/'C': 模拟组合键触发。 * - 'c'/'C': 模拟组合<EFBFBD><EFBFBD>触发<EFBFBD><EFBFBD>
* - 'a'/'A': 模拟无线传感器入侵触发报信号,地址固定为 0x123456zone=1 * - 'a'/'A': 模拟无线传感器入侵触发<EFBFBD><EFBFBD>报信号,地<EFBFBD><EFBFBD>固定<EFBFBD><EFBFBD> 0x123456zone=1<EFBFBD><EFBFBD>
* - 'p'/'P': 模拟对码期间捕获 24 位无线码信号,地址固定为 0x789ABC * - 'p'/'P': 模拟对码期间捕获<EFBFBD><EFBFBD> 24 位无线<EFBFBD><EFBFBD>码信号,地<EFBFBD><EFBFBD>固定<EFBFBD><EFBFBD> 0x789ABC<EFBFBD><EFBFBD>
* - '1'/'2'/'3': 模拟系统的常、已布防、已撤防状态切换。 * - '1'/'2'/'3': 模拟系统的<EFBFBD><EFBFBD>常、已布防、已撤防状<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000触发自动深度休眠 * - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000触发自动深度休眠<EFBFBD>
* - 't'/'T': 触发屏幕与无线控制引脚测试 * - 't'/'T': 触发屏幕与无线控制引脚测试<EFBFBD>
*/ */
/**
* @brief <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD>RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<C9AB><CDA8><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>
* @details <20><><EFBFBD>η<EFBFBD><CEB7>ʹ<EFBFBD><CDB4><EFBFBD><ECA1A2><EFBFBD>̡<EFBFBD><CCA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD> 2 <20><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ɫӳ<C9AB><D3B3><EFBFBD><EFBFBD>ϵ
*/
void RGB_Diagnostic_Test(void)
{
Uart_SendString("\r\n=== RGB LED Color Channel Test Starting ===\r\n");
// 1. <20><><EFBFBD>Է<EFBFBD><D4B7>ͺ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=0, R=150, B=0)
Uart_SendString("[RGB-TEST] 1. Sending RED command -> G=0, R=150, B=0\r\n");
RGB_Send(0, 150, 0, 0, 150, 0);
Delay_ms(2000);
// Ϩ<><CFA8>
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 2. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=150, R=0, B=0)
Uart_SendString("[RGB-TEST] 2. Sending GREEN command -> G=150, R=0, B=0\r\n");
RGB_Send(150, 0, 0, 150, 0, 0);
Delay_ms(2000);
// Ϩ<><CFA8>
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 3. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=0, R=0, B=150)
Uart_SendString("[RGB-TEST] 3. Sending BLUE command -> G=0, R=0, B=150\r\n");
RGB_Send(0, 0, 150, 0, 0, 150);
Delay_ms(2000);
// <20><><EFBFBD><EFBFBD>Ϩ<EFBFBD><CFA8>
RGB_Send(0, 0, 0, 0, 0, 0);
Uart_SendString("=== RGB LED Color Channel Test Ended ===\r\n");
}
void Debug_ProcessCommand(char cmd) void Debug_ProcessCommand(char cmd)
{ {
SystemEvent debug_evt; SystemEvent debug_evt;
inactivity_timer = 0; // 收到指令,立即重用户的无操作闲置计时 inactivity_timer = 0; // 收到指令,立即重<EFBFBD><EFBFBD>用户的无操作闲置计时<EFBFBD><EFBFBD>
debug_evt.extra_data = 0; debug_evt.extra_data = 0;
debug_evt.extra_size = 0; debug_evt.extra_size = 0;
@@ -85,7 +121,7 @@ void Debug_ProcessCommand(char cmd)
} else if (cmd == 's') { } else if (cmd == 's') {
debug_evt.key_event = KEY_EVENT_SOS_CLICK; debug_evt.key_event = KEY_EVENT_SOS_CLICK;
debug_evt.priority = EVENT_PRIORITY_URGENT; debug_evt.priority = EVENT_PRIORITY_URGENT;
EventQueue_InsertFront(debug_evt); // 紧事件插入队 EventQueue_InsertFront(debug_evt); // 紧<EFBFBD><EFBFBD>事件插入队<EFBFBD><EFBFBD>
Uart_SendString("[UART] KEY_SOS Clicked\r\n"); Uart_SendString("[UART] KEY_SOS Clicked\r\n");
} else if (cmd == 'S') { } else if (cmd == 'S') {
debug_evt.key_event = KEY_EVENT_SOS_LONG; debug_evt.key_event = KEY_EVENT_SOS_LONG;
@@ -100,22 +136,22 @@ void Debug_ProcessCommand(char cmd)
} else if (cmd == 'a' || cmd == 'A') { } else if (cmd == 'a' || cmd == 'A') {
u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址 u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址
u8 mock_slot; u8 mock_slot;
// 如果本地数据库中没有匹配该射频,则强制登记进 1 号防 // 如果<EFBFBD><EFBFBD>地数<EFBFBD><EFBFBD>库中没有匹配该射频,则强制登记进 1 号防<EFBFBD><EFBFBD>
if (!Check_Sensor_ID(mock_addr, &mock_slot)) { if (!Check_Sensor_ID(mock_addr, &mock_slot)) {
Add_Sensor_With_Zone(mock_addr, 0, 1); Add_Sensor_With_Zone(mock_addr, 0, 1);
} }
debug_evt.key_event = KEY_EVENT_NONE; debug_evt.key_event = KEY_EVENT_NONE;
debug_evt.priority = EVENT_PRIORITY_HIGH; // 入侵报警设为 HIGH 优先 debug_evt.priority = EVENT_PRIORITY_HIGH; // 入侵报<EFBFBD><EFBFBD><EFBFBD><EFBFBD>为 HIGH 优先<EFBFBD><EFBFBD>
debug_evt.extra_data = mock_addr; debug_evt.extra_data = mock_addr;
debug_evt.extra_size = 4; debug_evt.extra_size = 4;
EventQueue_InsertFront(debug_evt); // 高优先级插队 EventQueue_InsertFront(debug_evt); // 高优先级插队
Uart_SendString("[UART] Mock RF Alarm\r\n"); Uart_SendString("[UART] Mock RF Alarm\r\n");
} else if (cmd == 'p' || cmd == 'P') { } else if (cmd == 'p' || cmd == 'P') {
// 有当手环切入 Pair 模式时,模拟对码信号才有 // <EFBFBD><EFBFBD>有当手环切入 Pair 模式时,模拟对码信号才有<EFBFBD><EFBFBD>
if (AppManager_GetActiveAppID() == APP_ID_PAIR) { if (AppManager_GetActiveAppID() == APP_ID_PAIR) {
debug_evt.key_event = KEY_EVENT_NONE; debug_evt.key_event = KEY_EVENT_NONE;
debug_evt.priority = EVENT_PRIORITY_NORMAL; debug_evt.priority = EVENT_PRIORITY_NORMAL;
debug_evt.extra_data = 0x789ABC; // 设定模拟对码硬件地址 debug_evt.extra_data = 0x789ABC; // 设定模拟对码<EFBFBD><EFBFBD>件地<EFBFBD><EFBFBD>
debug_evt.extra_size = 4; debug_evt.extra_size = 4;
EventQueue_Push(debug_evt); EventQueue_Push(debug_evt);
Uart_SendString("[UART] Mock RF Pair Signal\r\n"); Uart_SendString("[UART] Mock RF Pair Signal\r\n");
@@ -123,155 +159,157 @@ void Debug_ProcessCommand(char cmd)
Uart_SendString("[UART] Not in PAIR mode\r\n"); Uart_SendString("[UART] Not in PAIR mode\r\n");
} }
} else if (cmd == '1') { } else if (cmd == '1') {
// 模拟切换 正常撤防 (NORMAL) 状并刷新时钟 // 模拟切换<EFBFBD><EFBFBD> 正常撤防 (NORMAL) 状<EFBFBD><EFBFBD>并刷新时钟
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) { if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
current_state = STATE_NORMAL; current_state = STATE_NORMAL;
UI_ShowClockPage(current_state, current_hour, current_min); UI_ShowClockPage(current_state, current_hour, current_min);
} }
Uart_SendString("[UART] State: NORMAL\r\n"); Uart_SendString("[UART] State: NORMAL\r\n");
} else if (cmd == '2') { } else if (cmd == '2') {
// 模拟切换 已布 (ARMED) 状态,普通门磁可触发警报 // 模拟切换<EFBFBD><EFBFBD> 已布<EFBFBD><EFBFBD> (ARMED) 状<EFBFBD><EFBFBD><EFBFBD><EFBFBD>通门磁可触发警报
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) { if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
current_state = STATE_ARMED; current_state = STATE_ARMED;
UI_ShowClockPage(current_state, current_hour, current_min); UI_ShowClockPage(current_state, current_hour, current_min);
} }
Uart_SendString("[UART] State: ARMED\r\n"); Uart_SendString("[UART] State: ARMED\r\n");
} else if (cmd == '3') { } else if (cmd == '3') {
// 模拟切换 已撤 (DISARMED) 状,忽略普通报警 // 模拟切换<EFBFBD><EFBFBD> 已撤<EFBFBD><EFBFBD> (DISARMED) 状<EFBFBD><EFBFBD>,忽略<EFBFBD><EFBFBD>通报<EFBFBD><EFBFBD>
if (AppManager_GetActiveAppID() == APP_ID_CLOCK) { if (AppManager_GetActiveAppID() == APP_ID_CLOCK) {
current_state = STATE_DISARMED; current_state = STATE_DISARMED;
UI_ShowClockPage(current_state, current_hour, current_min); UI_ShowClockPage(current_state, current_hour, current_min);
} }
Uart_SendString("[UART] State: DISARMED\r\n"); Uart_SendString("[UART] State: DISARMED\r\n");
} else if (cmd == 'z' || cmd == 'Z') { } else if (cmd == 'z' || cmd == 'Z') {
inactivity_timer = 6000; // 模拟闲置 60 秒超时,强制触发主循深度休眠 inactivity_timer = 6000; // 模拟闲置 60 秒超时,强制触发主循<EFBFBD><EFBFBD>深度休眠
Uart_SendString("[UART] Force Entering Sleep mode!\r\n"); Uart_SendString("[UART] Force Entering Sleep mode!\r\n");
} else if (cmd == 'q' || cmd == 'Q') {
RGB_Diagnostic_Test(); // <20><><EFBFBD><EFBFBD> RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<C9AB><CDA8><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>
} else if (cmd == 't' || cmd == 'T') { } else if (cmd == 't' || cmd == 'T') {
RF_DiagnosticMode('t'); // 触发射频连续发射诊断 (绿色爆闪) RF_DiagnosticMode('t'); // 触发射<EFBFBD><EFBFBD><EFBFBD><EFBFBD>发射诊断 (绿色爆闪)
} else if (cmd == 'r' || cmd == 'R') { } else if (cmd == 'r' || cmd == 'R') {
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监诊断 RF_DiagnosticMode('r'); // 触发 5 秒射频接收监<EFBFBD><EFBFBD>诊断
} else if (cmd == 'l' || cmd == 'L') { } else if (cmd == 'l' || cmd == 'L') {
Loopback_Test(); // 触发物理电气回环测试 (短路 P2.1 P3.6 自检) Loopback_Test(); // 触发物理电气回环测试 (<EFBFBD><EFBFBD><EFBFBD><EFBFBD> P2.1 <EFBFBD><EFBFBD> P3.6 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
} }
} }
/* ========================================================================= /* =========================================================================
* 主函 (入口) * 主函<EFBFBD><EFBFBD> (入口)
* ========================================================================= */ * ========================================================================= */
void main(void) void main(void)
{ {
char cmd; char cmd;
// ====== STC32G 特殊功能寄存器内核基础初始化 ====== // ====== STC32G 特殊功能寄存器内核基<EFBFBD><EFBFBD><EFBFBD><EFBFBD>化 ======
WTST = 0; // 设置程序 Flash 访问等待时间 0 (最高速运行) WTST = 0; // 设置程序 Flash 访问等待时间<EFBFBD><EFBFBD> 0 (<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
EAXFR = 1; // 允许访问扩展特殊功能寄存 (XSFR) EAXFR = 1; // 允<EFBFBD><EFBFBD><EFBFBD><EFBFBD>问扩展特殊功能寄存<EFBFBD><EFBFBD> (XSFR)
CKCON = 0; // 外部总线时钟设定为最 CKCON = 0; // 外部总线时钟设定为最<EFBFBD><EFBFBD>
WDT_CONTR = 0x00; // 关闭看门狗定时器 WDT_CONTR = 0x00; // 关闭看门狗定时器
// ====== 件各模块基础初始化 ====== // ====== <EFBFBD><EFBFBD>件各模块基<EFBFBD><EFBFBD><EFBFBD>化 ======
GPIO_Init(); // 配置各个引脚的推挽输/准双向模式及内部上拉 (锁存 PWR_HOLD=1) GPIO_Init(); // 配置各个引脚的推挽输<EFBFBD><EFBFBD>/准双向模式及内部上拉 (锁存 PWR_HOLD=1)
RGB_Send(0, 0, 0, 0, 0, 0); // 【首要修正】:上电第一时间强制发 0 码关闭灯条,熄灭上电暂引起的随机白光 RGB_Send(0, 0, 0, 0, 0, 0); // 【<EFBFBD><EFBFBD><EFBFBD><EFBFBD>修正<EFBFBD><EFBFBD>上电<EFBFBD><EFBFBD><EFBFBD><EFBFBD>时间强制发<EFBFBD> 0 码关<EFBFBD><EFBFBD><EFBFBD><EFBFBD>条,熄灭上电暂<EFBFBD><EFBFBD>引起的随机白光<EFBFBD><EFBFBD>
RF_Init(); // 初始化射频芯片各引脚控制 RF_Init(); // 初<EFBFBD><EFBFBD>化射<EFBFBD><EFBFBD>芯片各引脚控制
Delay_ms(500); // 软启动延时,等待供电电容稳定 Delay_ms(500); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>动延时,等待供电电<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LCD_Init(); // 初化 LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列并开启背光 LCD_Init(); // 初<EFBFBD><EFBFBD>化 LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列并<EFBFBD><EFBFBD><EFBFBD><EFBFBD>背光
Uart1_Init(); // 初化串口 1 波特 115200 供调试日 Uart1_Init(); // 初<EFBFBD><EFBFBD>化串口 1 波特<EFBFBD><EFBFBD> 115200 供调试日<EFBFBD><EFBFBD>
Uart_SendString("Wristband System Initialized!\r\n"); Uart_SendString("Wristband System Initialized!\r\n");
Self_Test(); // 执上电硬件自 (PWR_HOLD锁存、P0.3 ADC按键常态、P1.3 电池电量) Self_Test(); // 执<EFBFBD><EFBFBD>上电硬件自<EFBFBD><EFBFBD> (PWR_HOLD锁存、P0.3 ADC按键常<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P1.3 电池电量)
Load_Database(); // IAP Flash 254 扇区读取有已绑定的传感器数据 RAM Load_Database(); // <EFBFBD><EFBFBD> IAP Flash <EFBFBD><EFBFBD> 254 扇区读取<EFBFBD><EFBFBD>有已绑定的传感器数据<EFBFBD><EFBFBD> RAM
/* 步 1: 初化事件形缓冲区队列 */ /* 步<EFBFBD> 1: 初<EFBFBD><EFBFBD>化事件<EFBFBD><EFBFBD>形缓冲区队列 */
EventQueue_Init(); EventQueue_Init();
/* 步 2+5: 初化应用管理器并登所有前台应,默认加 ClockApp */ /* 步<EFBFBD> 2+5: 初<EFBFBD><EFBFBD>化应用管理器并登<EFBFBD><EFBFBD>所有前台应<EFBFBD><EFBFBD>,默认加<EFBFBD><EFBFBD> ClockApp */
AppManager_Init(); AppManager_Init();
/* 动并挂载后台射监控应,开始侦无线传感器信 */ /* <EFBFBD><EFBFBD>动并挂载后台射<EFBFBD><EFBFBD>监控应<EFBFBD><EFBFBD>,开始侦<EFBFBD><EFBFBD>无线传感器信<EFBFBD><EFBFBD> */
AppManager_AttachToBackground(&rf_monitor_app); AppManager_AttachToBackground(&rf_monitor_app);
/* 启动 1ms 系统基准定时 Timer1 */ /* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 系统基准定时<EFBFBD><EFBFBD> Timer1 */
Timer1_Init(); Timer1_Init();
/* 机自动加载并运待机时钟前台活跃应 */ /* <EFBFBD><EFBFBD>机自动加载并运<EFBFBD><EFBFBD>待机时钟前台活跃应<EFBFBD><EFBFBD> */
AppManager_StartApp(APP_ID_CLOCK); AppManager_StartApp(APP_ID_CLOCK);
Uart_SendString("[SYS] Event-driven framework ready\r\n"); Uart_SendString("[SYS] Event-driven framework ready\r\n");
// ====== 主循 ====== // ====== 主循<EFBFBD><EFBFBD> ======
while (1) { while (1) {
/* 0. 检查主循环按键定时标志 ( 1ms 中断置位,主循响应清除并理) */ /* 0. <EFBFBD><EFBFBD>查主<EFBFBD><EFBFBD><EFBFBD><EFBFBD>按键定时标志 (<EFBFBD><EFBFBD> 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>位,主循<EFBFBD><EFBFBD>响应清除并<EFBFBD><EFBFBD>理) */
if (key_scan_flag) { if (key_scan_flag) {
key_scan_flag = 0; key_scan_flag = 0;
Event_KeyScan_Poll(); Event_KeyScan_Poll();
} }
/* 1. 串口非阻塞指令捕 -> 装配为事件方式入 */ /* 1. 串口非阻塞指令捕<EFBFBD><EFBFBD> -> 装配为事件方式入<EFBFBD><EFBFBD> */
cmd = Uart_RxChar(); cmd = Uart_RxChar();
if (cmd != '\0') { if (cmd != '\0') {
Debug_ProcessCommand(cmd); Debug_ProcessCommand(cmd);
} }
/* 2. 事件分发总线:循环轮询并处理队列的所有有效事 */ /* 2. 事件分发总线:循<EFBFBD><EFBFBD><EFBFBD><EFBFBD>询并处理队列<EFBFBD><EFBFBD>的所有有效事<EFBFBD><EFBFBD> */
while (!EventQueue_IsEmpty()) { while (!EventQueue_IsEmpty()) {
Event_Dispatcher_Loop(); Event_Dispatcher_Loop();
} }
/* 3. 应用调度心:运行当前处于前台活跃状的应用(集成了 CPU 运时间超时挂起保护) */ /* 3. 应用调度<EFBFBD><EFBFBD>心:运<EFBFBD><EFBFBD>当前<EFBFBD><EFBFBD>于前台活跃状<EFBFBD><EFBFBD>的应用(集成了 CPU 运<EFBFBD><EFBFBD>时间超时挂起保护) */
AppManager_RunActiveApp(); AppManager_RunActiveApp();
/* 4. 动休眠判定:常无操作闲置达到 60 (6000 * 10ms = 60s) 时,切入低功耗停机休 */ /* 4. <EFBFBD><EFBFBD>动休眠判定:常<EFBFBD><EFBFBD>无操作闲置达到 60 <EFBFBD><EFBFBD> (6000 * 10ms = 60s) 时,切入低功耗停机休<EFBFBD><EFBFBD> */
if (inactivity_timer >= 6000) { if (inactivity_timer >= 6000) {
inactivity_timer = 0; inactivity_timer = 0;
current_state = STATE_SLEEP; // 系统为休眠状 current_state = STATE_SLEEP; // 系统<EFBFBD><EFBFBD>为休眠状<EFBFBD><EFBFBD>
Enter_Low_Power_Sleep(); // 该函数是阻MCU 将在此挂起唤醒后将自动从其后继续执 Enter_Low_Power_Sleep(); // 该函数是阻<EFBFBD><EFBFBD>MCU 将在此挂起<EFBFBD><EFBFBD>唤醒后将自动从其后继续执<EFBFBD>
current_state = STATE_NORMAL; // 唤醒后重新置为常待机状 current_state = STATE_NORMAL; // 唤醒后重新置为<EFBFBD><EFBFBD>常待机状<EFBFBD>
AppManager_StartApp(APP_ID_CLOCK); // 重新开启时钟应用以刷新画面和背光 AppManager_StartApp(APP_ID_CLOCK); // 重新<EFBFBD><EFBFBD><EFBFBD><EFBFBD>时钟应用以刷新画面和背光
} }
} }
} }
// 唤醒源事件标志,由对应的外部中断 ISR 写入 // 唤醒源事件标志,由<EFBFBD><EFBFBD>应的<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ISR 写入
volatile u8 p0_wakeup_flag = 0; // P0 端口按键唤醒标志 volatile u8 p0_wakeup_flag = 0; // P0 <EFBFBD><EFBFBD>口按<EFBFBD><EFBFBD>唤醒标志
volatile u8 p2_wakeup_flag = 0; // P2 端口按键唤醒标志 volatile u8 p2_wakeup_flag = 0; // P2 <EFBFBD><EFBFBD>口按<EFBFBD><EFBFBD>唤醒标志
volatile u8 p3_wakeup_flag = 0; // P3 口射频中唤醒标志 volatile u8 p3_wakeup_flag = 0; // P3 <EFBFBD><EFBFBD>口射频中<EFBFBD><EFBFBD>唤醒标志
volatile u8 rf_wakeup_flag = 0; // 射频中断唤醒标志 volatile u8 rf_wakeup_flag = 0; // 射<EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒标志
/* ========================================================================= /* =========================================================================
* STC32G 口掉电外部中断唤醒中断服务程序 (ISR) * STC32G <EFBFBD><EFBFBD>口掉电<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒<EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (ISR)
* ========================================================================= */ * ========================================================================= */
/** /**
* @brief Port0 口掉电中服务函数 ( isr_jump.asm 引定位至) * @brief Port0 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P0.1, P0.2, P0.3 按键在休眠模式下的物理触发,并立刻禁用中断防止反复执行 * @details 负责处理 P0.1, P0.2, P0.3 按键在休眠模式下的物理触发,并立刻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>反复执行<EFBFBD>
*/ */
void Port0_Isr(void) interrupt 13 void Port0_Isr(void) interrupt 13
{ {
EAXFR = 1; // 使能访问扩展寄存 EAXFR = 1; // 使能访问扩展寄存<EFBFBD><EFBFBD>
p0_wakeup_flag = P0INTF | 0x01;// 读取并份 P0 中断标志寄存器 (0x01作安全掩) p0_wakeup_flag = P0INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存器<EFBFBD> (0x01作安全掩<EFBFBD><EFBFBD>)
P0INTF = 0x00; // 清除 P0 端口中断悬挂标志位 P0INTF = 0x00; // 清除 P0 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P0INTE = 0x00; // 【关保护】:立即关闭 P0 中断允许,防止按键处于低电平期间反复触 ISR 导致堆栈溢出 P0INTE = 0x00; // 【关<EFBFBD><EFBFBD>保护】:立即关闭 P0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>处于低电平期间反复触<EFBFBD><EFBFBD> ISR 导致堆栈溢出
} }
/** /**
* @brief Port2 口掉电中服务函数 ( isr_jump.asm 引定位至) * @brief Port2 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P2.6 (SOS按键) P2.1 (射频数据脚) 在休眠模式下的物理跳变唤醒 * @details 负责处理 P2.6 (SOS按键) <EFBFBD><EFBFBD> P2.1 (射<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<EFBFBD>
*/ */
void Port2_Isr(void) interrupt 15 void Port2_Isr(void) interrupt 15
{ {
EAXFR = 1; // 使能扩展寄存 EAXFR = 1; // 使能扩展寄存<EFBFBD><EFBFBD>
p2_wakeup_flag = P2INTF | 0x01;// 读取并份 P2 中断标志寄存区的 p2_wakeup_flag = P2INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存区的<EFBFBD><EFBFBD>
P2INTF = 0x00; // 清除 P2 端口中断悬挂标志位 P2INTF = 0x00; // 清除 P2 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P2INTE = 0x00; // 立即关闭 P2 中断通道,防低电平期间反复重 P2INTE = 0x00; // 立即关闭 P2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>通道,防<EFBFBD><EFBFBD>低电平期间反复重<EFBFBD><EFBFBD>
} }
/** /**
* @brief Port3 口掉电中服务函数 ( isr_jump.asm 引定位至) * @brief Port3 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P3.6 (新射频数据脚) 在休眠模式下的物理跳变唤醒 * @details 负责处理 P3.6 (新射频数<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<EFBFBD>
*/ */
void Port3_Isr(void) interrupt 16 void Port3_Isr(void) interrupt 16
{ {
EAXFR = 1; // 使能访问扩展寄存 EAXFR = 1; // 使能访问扩展寄存<EFBFBD><EFBFBD>
p3_wakeup_flag = P3INTF | 0x01;// 读取并份 P3 中断标志寄存器 (0x01作安全掩) p3_wakeup_flag = P3INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存器<EFBFBD> (0x01作安全掩<EFBFBD><EFBFBD>)
P3INTF = 0x00; // 清除 P3 端口中断悬挂标志位 P3INTF = 0x00; // 清除 P3 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P3INTE = 0x00; // 立即关闭 P3 中断通道,防止反复重 P3INTE = 0x00; // 立即关闭 P3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>通道,防止反复重<EFBFBD><EFBFBD>
} }