From 601e01e9543c5e4aced41e99935f1c9ea6e06be5 Mon Sep 17 00:00:00 2001 From: Antigravity IDE Date: Wed, 15 Jul 2026 17:05:22 +0800 Subject: [PATCH] Implement low power RF wake-up and filter mechanism --- App/config.h | 3 + App/main.c | 5 ++ App/system.c | 122 ++++++++++++++++++++++++++--------- App/system.h | 2 +- Docs/60_coding/mod-power.md | 23 ++----- Hardware/~text.kicad_pcb.lck | 1 + Hardware/~text.kicad_pro.lck | 1 + Hardware/~text.kicad_sch.lck | 1 + wristband.uvopt | 78 +++++++++++++++++++++- 9 files changed, 186 insertions(+), 50 deletions(-) create mode 100644 Hardware/~text.kicad_pcb.lck create mode 100644 Hardware/~text.kicad_pro.lck create mode 100644 Hardware/~text.kicad_sch.lck diff --git a/App/config.h b/App/config.h index 6f2523f..0a5b4dc 100644 --- a/App/config.h +++ b/App/config.h @@ -152,6 +152,9 @@ extern volatile u16 key_confirm_hold; extern volatile u16 key_sos_hold; extern volatile u16 comb_hold; +extern volatile u8 isr_p0_flag; +extern volatile u8 isr_p2_flag; + #define MAIN_Fosc 24000000UL #define CLONED_ADDR 0x37A86UL diff --git a/App/main.c b/App/main.c index ad70bba..1379ae1 100644 --- a/App/main.c +++ b/App/main.c @@ -38,6 +38,9 @@ volatile u16 key_confirm_hold = 0; volatile u16 key_sos_hold = 0; volatile u16 comb_hold = 0; +volatile u8 isr_p0_flag = 0; +volatile u8 isr_p2_flag = 0; + /* ========================================================================= * 串口调试指令解析与事件派发封装 * ========================================================================= */ @@ -195,6 +198,7 @@ void main(void) void Port0_Isr(void) interrupt 13 { EAXFR = 1; + isr_p0_flag = P0INTF; P0INTF = 0x00; // 清除 P0 端口中断悬挂标志 P0INTE = 0x00; // 立即禁用,防止低电平保持期间反复触发 } @@ -203,6 +207,7 @@ void Port0_Isr(void) interrupt 13 void Port2_Isr(void) interrupt 15 { EAXFR = 1; + isr_p2_flag = P2INTF; P2INTF = 0x00; // 清除 P2 端口中断悬挂标志 P2INTE = 0x00; // 立即禁用,防止低电平保持期间反复触发 } diff --git a/App/system.c b/App/system.c index 5553bb9..d9d1f6d 100644 --- a/App/system.c +++ b/App/system.c @@ -2,6 +2,9 @@ #include "rgb.h" #include "ui.h" #include "../Drivers/lcd.h" +#include "../Drivers/rf.h" +#include "database.h" +#include "app_manager.h" void GPIO_Init(void) { @@ -235,9 +238,14 @@ void Enter_Low_Power_Sleep(void) P2IM0 &= ~0x40; P2INTE |= 0x40; + // 8b. 配置 P2.1 (RF_RX_DATA) 为 低电平触发 唤醒 + P2IM1 |= 0x02; + P2IM0 &= ~0x02; + P2INTE |= 0x02; + // ===== 配置端口掉电唤醒使能寄存器 PxWKUE ===== - P0WKUE |= 0x0E; // 使使能 P0.1/P0.2/P0.3 掉电唤醒 - P2WKUE |= 0x40; // 使使能 P2.6 掉电唤醒 + P0WKUE |= 0x0E; // 使能 P0.1/P0.2/P0.3 掉电唤醒 + P2WKUE |= 0x42; // 使能 P2.6, P2.1 掉电唤醒 // 9. 不允许外部中断 2 (RF_RX_DATA) 沿触发唤醒源 EX2 = 0; @@ -251,28 +259,35 @@ void Enter_Low_Power_Sleep(void) EA = 1; // 12. 写入 PCON 掉电模式位,使 MCU 进入深度 Power-Down 挂起状态 - Uart_SendString("[SYS] Entering Power-Down mode...\r\n"); - PCON |= 0x02; // PD = 1 - _nop_(); - _nop_(); - _nop_(); - _nop_(); + while (1) { + Uart_SendString("[SYS] Entering Power-Down mode...\r\n"); + PCON |= 0x02; // PD = 1 + _nop_(); + _nop_(); + _nop_(); + _nop_(); - // 13. 唤醒并执行完 ISR 后,CPU 从这里继续执行 - Wakeup_Restore(); + // 13. 唤醒并执行完 ISR 后,CPU 从这里继续执行,如果是真唤醒,则打破挂起循环 + if (Wakeup_Restore() == 1) { + break; + } + } } -void Wakeup_Restore(void) +u8 Wakeup_Restore(void) { - u8 p0_flag; - u8 p2_flag; + u8 actual_p0; + u8 actual_p2; + u8 decoded = 0; // 确保 EAXFR=1 才能访问扩展 SFR (P0INTF/P2INTF/P0INTE/P2INTE) EAXFR = 1; - // [诊断] 在清除标志位之前先读取,判断唤醒来源 - p0_flag = P0INTF; - p2_flag = P2INTF; + // 读取并重置 ISR 中存下来的真实中断源,同时也要读取当前的寄存器以备万一 + actual_p0 = isr_p0_flag | P0INTF; + actual_p2 = isr_p2_flag | P2INTF; + isr_p0_flag = 0; + isr_p2_flag = 0; // 1. 立即禁用端口中断和唤醒,防止继续触发 P0INTE = 0x00; @@ -292,36 +307,85 @@ void Wakeup_Restore(void) ET1 = 1; // [诊断] 打印唤醒来源 - if (p0_flag & 0x0E) { + if (actual_p0 & 0x0E) { Uart_SendString("[WR] Woken by KEY P0 (P0INTF=0x"); - Uart_SendHex8(p0_flag); + Uart_SendHex8(actual_p0); Uart_SendString(")\r\n"); - } else if (p2_flag & 0x40) { + } else if (actual_p2 & 0x40) { Uart_SendString("[WR] Woken by KEY P2 (P2INTF=0x"); - Uart_SendHex8(p2_flag); + Uart_SendHex8(actual_p2); + Uart_SendString(")\r\n"); + } else if (actual_p2 & 0x02) { + Uart_SendString("[WR] Woken by RF P2.1 (P2INTF=0x"); + Uart_SendHex8(actual_p2); Uart_SendString(")\r\n"); } else { - Uart_SendString("[WR] Woken by TIMER (no key flag)\r\n"); + Uart_SendString("[WR] Woken by TIMER/OTHER\r\n"); } - // 3. 保持 SHUT 开启射频接收芯片工作 + // 3. 处理射频唤醒:判断是否真的有传感器报警 + if ((actual_p2 & 0x02) && !(actual_p0 & 0x0E) && !(actual_p2 & 0x40)) { + u8 i; + u32 rx_addr; + u8 rx_data; + + // 关闭全局中断进行解调,防止滴答中断干扰高精度脉宽采集 + EA = 0; + for (i = 0; i < 6; i++) { + if (EV1527_Decode(&rx_addr, &rx_data)) { + u8 slot; + if (Check_Sensor_ID(rx_addr, &slot)) { + u8 sensor_type = sensor_list[slot].type; + if (sensor_type < 5) { + // 只有在防区开启 (zone == 0) 或处于 STATE_ARMED (警戒) 状态下才触发 + if (sensor_list[slot].zone == 0 || current_state == STATE_ARMED) { + captured_addr = rx_addr; + alarm_sensor_slot = slot; + decoded = 1; + break; + } + } + } + } + Delay_ms(20); + } + EA = 1; + + if (!decoded) { + // 只是噪声或未配对的遥控器,无视,不亮屏直接返回 0 让主休眠循环继续挂起 + Uart_SendString("[WR] RF false alarm/noise. Re-sleeping.\r\n"); + return 0; + } + Uart_SendString("[WR] RF Alarm Decoded successfully!\r\n"); + } + + // 4. 到这里说明是真唤醒(或者是按键,或者是有效的射频警报解码成功) + // 开启射频接收芯片工作 SHUT = 1; - // 4. 拉高 SGM_CTRL 并发送脉冲使能 SGM3833 升压 + // 拉高 SGM_CTRL 并发送脉冲使能 SGM3833 升压 SGM_CTRL = 1; SGM_SendPulse(27); - // 5. 等待负压电轨充分稳定 + // 等待负压电轨充分稳定 Delay_ms(200); - // 6. 重做屏控制器 RM69310 寄存器组的初始化 + // 重做屏控制器 RM69310 寄存器组的初始化 LCD_Init(); - // 7. 重置闲置倒计时 + // 重置闲置倒计时 inactivity_timer = 0; - // 8. 直接绘制时钟界面(绕过 AppManager 早期返回保护) - current_state = STATE_NORMAL; - UI_ShowClockPage(current_state, current_hour, current_min); + // 根据唤醒源决定显示什么 + if (decoded) { + // 如果是有效的射频入侵触发,强制切到 Alarm 状态并启动应用 + AppManager_StartApp(APP_ID_ALARM); + } else { + // 如果是按键触发唤醒,显示主时间界面 + current_state = STATE_NORMAL; + UI_ShowClockPage(current_state, current_hour, current_min); + } + Uart_SendString("[SYS] Wakeup restored!\r\n"); + return 1; // 返回 1 表示真唤醒 } diff --git a/App/system.h b/App/system.h index 5c8d61e..3e1ca29 100644 --- a/App/system.h +++ b/App/system.h @@ -26,6 +26,6 @@ void FormatHex(u32 val, char *buf); // 电源管理与休眠唤醒 void Enter_Low_Power_Sleep(void); -void Wakeup_Restore(void); +u8 Wakeup_Restore(void); #endif diff --git a/Docs/60_coding/mod-power.md b/Docs/60_coding/mod-power.md index 8bf8816..69b84a0 100644 --- a/Docs/60_coding/mod-power.md +++ b/Docs/60_coding/mod-power.md @@ -9,19 +9,8 @@ ## 2. 关键代码片段与逻辑实现 ### 2.1 供电引脚初始化 -系统初始化时,配置 `SHUT`(控制 SGM3833 供电的引脚 `P2.2`)为推挽输出,并拉高以开启屏幕供电: -```c -sbit SHUT = P2^2; // Pin 23 -void Power_Init(void) { - // P2.2 (SHUT) 配置为推挽输出 - P2M1 &= ~(1 << 2); - P2M0 |= (1 << 2); - - // 拉高引脚,开启 SGM3833 负压供电 - SHUT = 1; -} -``` + ### 2.2 进入低功耗睡眠 (Enter_Low_Power_Sleep) 在 10 秒无按键操作发生后,关闭屏幕显示,断电,配置中断,并进入 Power-Down 挂起状态: @@ -31,7 +20,7 @@ void Enter_Low_Power_Sleep(void) { LCD_WriteCmd(0x10); // 2. 切断 SGM3833 电源,停止输出负压 - SHUT = 0; + // 3. 配置引脚中断 (P0.1, P0.2, P0.3, P2.6) 允许唤醒 // 允许 P0 / P2 端口中断以供按键唤醒 @@ -56,12 +45,12 @@ void Port0_Isr(void) interrupt 37 { P0INTF = 0x00; // 清除 P0 中断标志 Wakeup_Restore(); } - +//周期嗅探模式来接收信号源 void Wakeup_Restore(void) { - if (SHUT == 1) return; // 已经在工作状态,直接返回 + if // 已经在工作状态,直接返回 - // 1. 拉高 SHUT 重新使能 SGM3833 供电 - SHUT = 1; + // 重新使能 SGM3833 供电 + // 2. 延时约 50ms 等待升压/负压输出稳定 Delay50ms(); diff --git a/Hardware/~text.kicad_pcb.lck b/Hardware/~text.kicad_pcb.lck new file mode 100644 index 0000000..a031987 --- /dev/null +++ b/Hardware/~text.kicad_pcb.lck @@ -0,0 +1 @@ +{"hostname":"DESKTOP-0S8JI7H","username":"xtell"} \ No newline at end of file diff --git a/Hardware/~text.kicad_pro.lck b/Hardware/~text.kicad_pro.lck new file mode 100644 index 0000000..a031987 --- /dev/null +++ b/Hardware/~text.kicad_pro.lck @@ -0,0 +1 @@ +{"hostname":"DESKTOP-0S8JI7H","username":"xtell"} \ No newline at end of file diff --git a/Hardware/~text.kicad_sch.lck b/Hardware/~text.kicad_sch.lck new file mode 100644 index 0000000..a031987 --- /dev/null +++ b/Hardware/~text.kicad_sch.lck @@ -0,0 +1 @@ +{"hostname":"DESKTOP-0S8JI7H","username":"xtell"} \ No newline at end of file diff --git a/wristband.uvopt b/wristband.uvopt index acb73dc..eec9feb 100644 --- a/wristband.uvopt +++ b/wristband.uvopt @@ -171,7 +171,7 @@ App - 0 + 1 0 0 0 @@ -187,6 +187,78 @@ 0 0 + + 1 + 2 + 1 + 0 + 0 + 0 + .\App\rgb.c + rgb.c + 0 + 0 + + + 1 + 3 + 1 + 0 + 0 + 0 + .\App\event.c + event.c + 0 + 0 + + + 1 + 4 + 1 + 0 + 0 + 0 + .\App\app_manager.c + app_manager.c + 0 + 0 + + + 1 + 5 + 1 + 0 + 0 + 0 + .\App\database.c + database.c + 0 + 0 + + + 1 + 6 + 1 + 0 + 0 + 0 + .\App\ui.c + ui.c + 0 + 0 + + + 1 + 7 + 1 + 0 + 0 + 0 + .\App\system.c + system.c + 0 + 0 + @@ -197,7 +269,7 @@ 0 2 - 2 + 8 1 0 0 @@ -209,7 +281,7 @@ 2 - 3 + 9 1 0 0