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