fix: 纠正低功耗休眠唤醒源,仅采用 P0.1/P0.2/P2.6 下降沿唤醒并排除 P0.3 模拟干扰,并在 main.c 本地安全清零按键计数与强保电源,彻底根除唤醒假死与断电故障

This commit is contained in:
2026-07-30 15:51:27 +08:00
parent 41bb78aa59
commit cf8a5f5796
2 changed files with 141 additions and 121 deletions

View File

@@ -9,84 +9,84 @@
#include "../Drivers/lcd.h"
/* =========================================================================
* 系统全局变量定义
* 绯荤粺鍏ㄥ眬鍙橀噺瀹氫箟
* ========================================================================= */
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态<EFBFBD><EFBFBD>为正常时钟待机<EFBFBD><EFBFBD>
SystemState current_state = STATE_NORMAL; // 绯荤粺鏁翠綋鐨勫綋鍓嶈繍琛岀姸鎬侊紝榛樿や负姝e父鏃堕挓寰呮満椤
u8 menu_select = 0; // 主菜单当前<EFBFBD><EFBFBD>中的<EFBFBD><EFBFBD><EFBFBD><EFBFBD>索引 (0~2)
u32 captured_addr = 0; // <EFBFBD><EFBFBD>或报<EFBFBD><EFBFBD>捕获到的传感器 24 <EFBFBD><EFBFBD> EV1527 <EFBFBD><EFBFBD>物理地<EFBFBD><EFBFBD>
u8 captured_type = 0; // 正在对码或触发<EFBFBD><EFBFBD>报的传感器设<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (0:<EFBFBD>, 1:PIR...)
u8 alarm_sensor_slot = 0; // 触发警报的传感器<EFBFBD><EFBFBD> sensor_list 数组<E695B0><E7BB84>的索引槽位号
u8 menu_select = 0; // 涓昏彍鍗曞綋鍓嶉変腑鐨勮岄珮浜绱㈠紩 (0~2)
u32 captured_addr = 0; // 閰嶅规垨鎶ヨ︽椂锛屾崟鑾峰埌鐨勪紶鎰熷櫒 24 EV1527 灏勯戠墿鐞嗗湴鍧
u8 captured_type = 0; // 姝e湪瀵圭爜鎴栬Е鍙戣︽姤鐨勪紶鎰熷櫒璁惧囩被鍨 (0:闂ㄧ, 1:PIR...)
u8 alarm_sensor_slot = 0; // 瑙﹀彂璀︽姤鐨勪紶鎰熷櫒鍦 sensor_list 鏁扮粍涓鐨勭储寮曟Ы浣嶅彿
// 传感器存储列表数<EFBFBD><EFBFBD>位于单片机<EFBFBD><EFBFBD>部 XDATA 存储空间<E997B4><EFBC8C>共 16 <20><>槽位
// 浼犳劅鍣ㄥ瓨鍌ㄥ垪琛ㄦ暟鎹搴擄紝浣嶄簬鍗曠墖鏈哄栭儴 XDATA 瀛樺偍绌洪棿锛屾诲叡 16 涓妲戒綅
Sensor_Slot xdata sensor_list[16];
// 全局滴答与定时中<EFBFBD><EFBFBD>计数变量<EFBFBD><EFBFBD> volatile 防<><E998B2><EFBFBD>编译器优<E599A8><E4BC98>
volatile u16 ms_tick = 0; // 定时<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 基准滴答<E6BBB4><E7AD94>加器
volatile u16 inactivity_timer = 0; // 用户闲置计时<EFBFBD><EFBFBD>用于无操作判定<EFBFBD><EFBFBD>: 10ms<EFBFBD><EFBFBD>
volatile u32 pair_timeout_ms = 0; // 传感器配对<EFBFBD><EFBFBD>码超时<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (上限 30000ms <EFBFBD><EFBFBD> 30s)
volatile u16 alarm_timer_ms = 0; // 入侵报<EFBFBD><EFBFBD>马达震动时序<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 motor_timer_ms = 0; // <EFBFBD><EFBFBD>立马达震动时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile bit alarm_flash_flag = 0; // <EFBFBD><EFBFBD>时红<EFBFBD><EFBFBD>周期<EFBFBD><EFBFBD>闪烁亮<EFBFBD><EFBFBD>标志<EFBFBD><EFBFBD>
// 鍏ㄥ眬婊寸瓟涓庡畾鏃朵腑鏂璁℃暟鍙橀噺锛屼綅浜 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; // 鎶ヨ︽椂绾㈡嗗懆鏈熸ч棯鐑佷寒鐏鏍囧織浣
// 物理按键<EFBFBD><EFBFBD>描与消抖长按计数<EFBFBD><EFBFBD> (10ms <EFBFBD><EFBFBD>描一<EFBFBD><EFBFBD>)
volatile u16 key_scan_timer = 0; // 10ms <EFBFBD><EFBFBD>描周期分频器
volatile u16 key_up_hold = 0; // <EFBFBD><EFBFBD> (KEY_UP) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_down_hold = 0; // <EFBFBD><EFBFBD> (KEY_DOWN) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_confirm_hold = 0; // <EFBFBD><EFBFBD> (KEY_CONFIRM) 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 key_sos_hold = 0; // SOS 按下时长<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
volatile u16 comb_hold = 0; // <EFBFBD><EFBFBD> + <EFBFBD><EFBFBD> 组合<E7BB84><E59088>按下时长<E697B6><E995BF><EFBFBD><EFBFBD>
// 鐗╃悊鎸夐敭鎵鎻忎笌娑堟姈闀挎寜璁℃暟鍣 (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; // + 鈻 缁勫悎閿鎸変笅鏃堕暱绱鍔
/* =========================================================================
* 串口调试指令解析与事件派发封<EFBFBD><EFBFBD>
* 涓插彛璋冭瘯鎸囦护瑙f瀽涓庝簨浠舵淳鍙戝皝瑁
* ========================================================================= */
/**
* @brief 解析通过串口 1 发<><E58F91>来的键盘及测试模拟指令
* @param cmd 接收到的 ASCII <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @details 负责将字符指令转化<EFBFBD><EFBFBD>应的系统按<EFBFBD><EFBFBD>或射频事件并推入事件队列以测试<EFBFBD><EFBFBD>件架构
* - 'u'/'U': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 <20><> <20><><EFBFBD><EFBFBD>
* - 'd'/'D': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 <20><> <20><><EFBFBD><EFBFBD>
* - 's'/'S': 模拟<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/长按 SOS 物理<E789A9><E79086>优先插入队首<E9A696><EFBC89>
* - 'c'/'C': 模拟组合<EFBFBD><EFBFBD>触发<EFBFBD><EFBFBD>
* - 'a'/'A': 模拟无线传感器入侵触发<EFBFBD><EFBFBD>报信号<EFBFBD><EFBFBD>固定<EFBFBD><EFBFBD> 0x123456zone=1<EFBFBD><EFBFBD>
* - 'p'/'P': 模拟对码期间捕获<EFBFBD><EFBFBD> 24 位无线<E697A0><E7BABF>码信号<EFBC8C><E59CB0>固定<E59BBA><E5AE9A> 0x789ABC<EFBFBD><EFBFBD>
* - '1'/'2'/'3': 模拟系统的<EFBFBD><EFBFBD>常、已布防、已撤防状<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000触发自动深度休眠<E4BC91>
* - 't'/'T': 触发屏幕与无线控制引脚测试<EFBFBD>
* @brief 瑙f瀽閫氳繃涓插彛 1 鍙戦佹潵鐨勯敭鐩樺強娴嬭瘯妯℃嫙鎸囦护
* @param cmd 鎺ユ敹鍒扮殑 ASCII 瀛楃﹀懡浠
* @details 璐熻矗灏嗗瓧绗︽寚浠よ浆鍖栧瑰簲鐨勭郴缁熸寜閿鎴栧皠棰戜簨浠讹紝骞舵帹鍏ヤ簨浠堕槦鍒椾互娴嬭瘯杞浠舵灦鏋勶細
* - 'u'/'U': 妯℃嫙鐭鎸/闀挎寜 鈻 閿銆
* - 'd'/'D': 妯℃嫙鐭鎸/闀挎寜 鈻 閿銆
* - 's'/'S': 妯℃嫙鐭鎸/闀挎寜 SOS 鐗╃悊閿锛堜紭鍏堟彃鍏ラ槦棣栵級銆
* - 'c'/'C': 妯℃嫙缁勫悎閿瑙﹀彂銆
* - 'a'/'A': 妯℃嫙鏃犵嚎浼犳劅鍣ㄥ叆渚佃Е鍙戣︽姤淇″彿锛屽湴鍧鍥哄畾涓 0x123456锛寊one=1
* - 'p'/'P': 妯℃嫙瀵圭爜鏈熼棿鎹曡幏鐨 24 浣嶆棤绾垮圭爜淇″彿锛屽湴鍧鍥哄畾涓 0x789ABC
* - '1'/'2'/'3': 妯℃嫙绯荤粺鐨勬e父銆佸凡甯冮槻銆佸凡鎾ら槻鐘舵佸垏鎹銆
* - 'z'/'Z': 妯℃嫙瓒呮椂锛屽己琛屼娇闂茬疆璁℃暟鍣ㄧ疆 6000锛岃Е鍙戣嚜鍔ㄦ繁搴︿紤鐪犮
* - 't'/'T': 瑙﹀彂灞忓箷涓庢棤绾挎帶鍒跺紩鑴氭祴璇曘
*/
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD><EFBFBD><EFBFBD><EFBFBD>RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<C9AB><CDA8><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>
* @details <EFBFBD><EFBFBD><EFBFBD>η<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><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>ϵ
* @brief 串口调试专属RGB 物理颜色通道排查测试
* @details 依次发送纯红、纯绿、纯蓝的数据流,每个颜色亮起 2 秒,帮助肉眼校对物理灯珠的实际颜色映射关系
*/
void RGB_Diagnostic_Test(void)
{
Uart_SendString("\r\n=== RGB LED Color Channel Test Starting ===\r\n");
// 1. <EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD>ͺ<EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=0, R=150, B=0)
// 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);
// Ϩ<EFBFBD><EFBFBD>
// 熄灭
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 2. <EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=150, R=0, B=0)
// 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);
// Ϩ<EFBFBD><EFBFBD>
// 熄灭
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 3. <EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (G=0, R=0, B=150)
// 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);
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϩ<EFBFBD><EFBFBD>
// 彻底熄灭
RGB_Send(0, 0, 0, 0, 0, 0);
Uart_SendString("=== RGB LED Color Channel Test Ended ===\r\n");
}
@@ -94,14 +94,14 @@ void RGB_Diagnostic_Test(void)
void Debug_ProcessCommand(char cmd)
{
SystemEvent debug_evt;
inactivity_timer = 0; // 收到指令立即重<EFBFBD><EFBFBD>用户的无操作闲置计时<EFBFBD><EFBFBD>
inactivity_timer = 0; // 鏀跺埌鎸囦护锛岀珛鍗抽噸缃鐢ㄦ埛鐨勬棤鎿嶄綔闂茬疆璁℃椂鍣
debug_evt.extra_data = 0;
debug_evt.extra_size = 0;
if (cmd == 'u') {
debug_evt.key_event = KEY_EVENT_UP_CLICK;
debug_evt.priority = EVENT_PRIORITY_NORMAL;
EventQueue_Push(debug_evt); // 压入队尾
EventQueue_Push(debug_evt); // 鍘嬪叆闃熷熬
Uart_SendString("[UART] KEY_UP Clicked\r\n");
} else if (cmd == 'U') {
debug_evt.key_event = KEY_EVENT_UP_LONG;
@@ -121,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); // <EFBFBD><EFBFBD>事件插入队<EFBFBD><EFBFBD>
EventQueue_InsertFront(debug_evt); // 绱фヤ簨浠舵彃鍏ラ槦棣
Uart_SendString("[UART] KEY_SOS Clicked\r\n");
} else if (cmd == 'S') {
debug_evt.key_event = KEY_EVENT_SOS_LONG;
@@ -134,24 +134,24 @@ void Debug_ProcessCommand(char cmd)
EventQueue_Push(debug_evt);
Uart_SendString("[UART] KEY_UP+DOWN Combined\r\n");
} else if (cmd == 'a' || cmd == 'A') {
u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址
u32 mock_addr = 0x123456; // 璁惧畾妯℃嫙鐨勬姤璀﹀皠棰戞簮鍦板潃
u8 mock_slot;
// 如果<EFBFBD><EFBFBD>地数<EFBFBD><EFBFBD>库中没有匹配该射频则强制登记进 1 号防<E58FB7><E998B2>
// 濡傛灉鏈鍦版暟鎹搴撲腑娌℃湁鍖归厤璇ュ皠棰戯紝鍒欏己鍒剁櫥璁拌繘 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; // 入侵报<EFBFBD><EFBFBD><EFBFBD><EFBFBD> HIGH 优先<EFBFBD><EFBFBD>
debug_evt.priority = EVENT_PRIORITY_HIGH; // 鍏ヤ镜鎶ヨ﹁句负 HIGH 浼樺厛绾
debug_evt.extra_data = mock_addr;
debug_evt.extra_size = 4;
EventQueue_InsertFront(debug_evt); // 高优先级插队
EventQueue_InsertFront(debug_evt); // 楂樹紭鍏堢骇鎻掗槦
Uart_SendString("[UART] Mock RF Alarm\r\n");
} else if (cmd == 'p' || cmd == 'P') {
// <EFBFBD><EFBFBD>有当手环切入 Pair 模式时模拟对码信号才有<E6898D><E69C89>
// 鍙鏈夊綋鎵嬬幆鍒囧叆 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; // 设定模拟对码<EFBFBD><EFBFBD>件地<EFBFBD><EFBFBD>
debug_evt.extra_data = 0x789ABC; // 璁惧畾妯℃嫙瀵圭爜纭浠跺湴鍧
debug_evt.extra_size = 4;
EventQueue_Push(debug_evt);
Uart_SendString("[UART] Mock RF Pair Signal\r\n");
@@ -159,157 +159,175 @@ void Debug_ProcessCommand(char cmd)
Uart_SendString("[UART] Not in PAIR mode\r\n");
}
} else if (cmd == '1') {
// 模拟切换<EFBFBD><EFBFBD> 正常撤防 (NORMAL) 状<><E78AB6>并刷新时钟
// 妯℃嫙鍒囨崲鑷 姝e父鎾ら槻 (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') {
// 模拟切换<EFBFBD><EFBFBD> 已布<E5B7B2><E5B883> (ARMED) 状<><E78AB6><EFBFBD><EFBC8C>通门磁可触发警报
// 妯℃嫙鍒囨崲鑷 宸插竷闃 (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') {
// 模拟切换<EFBFBD><EFBFBD> 已撤<E5B7B2><E692A4> (DISARMED) 状<><E78AB6>忽略<E5BFBD><E795A5>通报<E9809A><E68AA5>
// 妯℃嫙鍒囨崲鑷 宸叉挙闃 (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 秒超时强制触发主循<E4B8BB><E5BEAA>深度休眠
inactivity_timer = 6000; // 妯℃嫙闂茬疆 60 绉掕秴鏃讹紝寮哄埗瑙﹀彂涓诲惊鐜娣卞害浼戠湢
Uart_SendString("[UART] Force Entering Sleep mode!\r\n");
} else if (cmd == 'q' || cmd == 'Q') {
RGB_Diagnostic_Test(); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> RGB <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RGB_Diagnostic_Test(); // 启动 RGB 物理颜色通道排查测试
} else if (cmd == 't' || cmd == 'T') {
RF_DiagnosticMode('t'); // 触发射<EFBFBD><EFBFBD><EFBFBD><EFBFBD>发射诊断 (绿色爆闪)
RF_DiagnosticMode('t'); // 瑙﹀彂灏勯戣繛缁鍙戝皠璇婃柇 (缁胯壊鐖嗛棯)
} else if (cmd == 'r' || cmd == 'R') {
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监<E694B6><E79B91>诊断
RF_DiagnosticMode('r'); // 瑙﹀彂 5 绉掑皠棰戞帴鏀剁洃鍚璇婃柇
} else if (cmd == 'l' || cmd == 'L') {
Loopback_Test(); // 触发物理电气回环测试 (<28><><EFBFBD><EFBFBD> P2.1 <EFBFBD><EFBFBD> P3.6 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
Loopback_Test(); // 瑙﹀彂鐗╃悊鐢垫皵鍥炵幆娴嬭瘯 (鐭璺 P2.1 P3.6 鑷妫)
}
}
/* =========================================================================
* 主函<EFBFBD><EFBFBD> (入口)
* 涓诲嚱鏁 (鍏ュ彛)
* ========================================================================= */
void main(void)
{
char cmd;
// ====== STC32G 特殊功能寄存器内核基<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ======
WTST = 0; // 设置程序 Flash 访问等待时间<EFBFBD><EFBFBD> 0 (<28><><EFBFBD><E9AB98><EFBFBD><E8BF90>)
EAXFR = 1; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>问扩展特殊功能寄存<EFBFBD><EFBFBD> (XSFR)
CKCON = 0; // 外部总线时钟设定为最<EFBFBD><EFBFBD>
WDT_CONTR = 0x00; // 关闭看门狗定时器
// ====== STC32G 鐗规畩鍔熻兘瀵勫瓨鍣ㄥ唴鏍稿熀纭鍒濆嬪寲 ======
WTST = 0; // 璁剧疆绋嬪簭 Flash 璁块棶绛夊緟鏃堕棿涓 0 (鏈楂橀熻繍琛)
EAXFR = 1; // 鍏佽歌块棶鎵╁睍鐗规畩鍔熻兘瀵勫瓨鍣 (XSFR)
CKCON = 0; // 澶栭儴鎬荤嚎鏃堕挓璁惧畾涓烘渶蹇
WDT_CONTR = 0x00; // 鍏抽棴鐪嬮棬鐙楀畾鏃跺櫒
// ====== <EFBFBD><EFBFBD>件各模块基<EFBFBD><EFBFBD><EFBFBD> ======
GPIO_Init(); // 配置各个引脚的推挽输<EFBFBD><EFBFBD>/准双向模式及内部上拉 (锁存 PWR_HOLD=1)
RGB_Send(0, 0, 0, 0, 0, 0); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>修正<EFBFBD><EFBFBD>上电<EFBFBD><EFBFBD><EFBFBD><EFBFBD>时间强制发<EFBFBD> 0 码关<E7A081><E585B3><EFBFBD><EFBFBD>熄灭上电暂<E794B5><E69A82>引起的随机白光<E799BD><E58589>
RF_Init(); // <EFBFBD><EFBFBD>化射<EFBFBD><EFBFBD>芯片各引脚控制
Delay_ms(500); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>动延时等待供电电<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LCD_Init(); // <EFBFBD><EFBFBD> LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列并<EFBFBD><EFBFBD><EFBFBD><EFBFBD>背光
Uart1_Init(); // <EFBFBD><EFBFBD>化串口 1 波特<E6B3A2><E789B9> 115200 供调试日<EFBFBD><EFBFBD>
// ====== 纭浠跺悇妯″潡鍩虹鍒濆嬪寲 ======
GPIO_Init(); // 閰嶇疆鍚勪釜寮曡剼鐨勬帹鎸借緭鍑/鍑嗗弻鍚戞ā寮忓強鍐呴儴涓婃媺 (閿佸瓨 PWR_HOLD=1)
RGB_Send(0, 0, 0, 0, 0, 0); // 銆愰栬佷慨姝c戯細涓婄數绗涓鏃堕棿寮哄埗鍙戦 0 鐮佸叧闂鐏鏉★紝鐔勭伃涓婄數鏆傛佸紩璧风殑闅忔満鐧藉厜锛
RF_Init(); // 鍒濆嬪寲灏勯戣姱鐗囧悇寮曡剼鎺у埗
Delay_ms(500); // 杞鍚鍔ㄥ欢鏃讹紝绛夊緟渚涚數鐢靛圭ǔ瀹
LCD_Init(); // 鍒濆嬪寲 LHS114TC-IF03 (ST7789V) 灞忓箷鎺у埗瀵勫瓨鍣ㄥ簭鍒楀苟寮鍚鑳屽厜
Uart1_Init(); // 鍒濆嬪寲涓插彛 1 娉㈢壒鐜 115200 渚涜皟璇曟棩蹇
Uart_SendString("Wristband System Initialized!\r\n");
Self_Test(); // <EFBFBD><EFBFBD>上电硬件自<EFBFBD><EFBFBD> (PWR_HOLD锁存、P0.3 ADC按键常<EFBFBD><EFBFBD><EFBFBD><EFBFBD>P1.3 电池电量)
Load_Database(); // <EFBFBD><EFBFBD> IAP Flash <EFBFBD><EFBFBD> 254 扇区读取<EFBFBD><EFBFBD>有已绑定的传感器数据<EFBFBD><EFBFBD> RAM
Self_Test(); // 鎵ц屼笂鐢电‖浠惰嚜妫 (PWR_HOLD閿佸瓨銆丳0.3 ADC鎸夐敭甯告併丳1.3 鐢垫睜鐢甸噺)
Load_Database(); // IAP Flash 254 鎵囧尯璇诲彇鎵鏈夊凡缁戝畾鐨勪紶鎰熷櫒鏁版嵁鑷 RAM
/* <EFBFBD> 1: <EFBFBD><EFBFBD>化事件<EFBFBD><EFBFBD>形缓冲区队列 */
/* 姝ラ 1: 鍒濆嬪寲浜嬩欢鐜褰㈢紦鍐插尯闃熷垪 */
EventQueue_Init();
/* <EFBFBD> 2+5: <EFBFBD><EFBFBD>化应用管理器并登<EFBFBD><EFBFBD>所有前台应<EFBFBD><EFBFBD>默认加<EFBFBD><EFBFBD> ClockApp */
/* 姝ラ 2+5: 鍒濆嬪寲搴旂敤绠$悊鍣ㄥ苟鐧昏版墍鏈夊墠鍙板簲鐢锛岄粯璁ゅ姞杞 ClockApp */
AppManager_Init();
/* <EFBFBD><EFBFBD>动并挂载后台射<EFBFBD><EFBFBD>监控应<EFBFBD><EFBFBD>开始侦<EFBFBD><EFBFBD>无线传感器信<EFBFBD><EFBFBD> */
/* 鍚鍔ㄥ苟鎸傝浇鍚庡彴灏勯戠洃鎺у簲鐢锛屽紑濮嬩睛鍚鏃犵嚎浼犳劅鍣ㄤ俊鍙 */
AppManager_AttachToBackground(&rf_monitor_app);
/* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 系统基准定时<EFBFBD><EFBFBD> Timer1 */
/* 鍚鍔 1ms 绯荤粺鍩哄噯瀹氭椂鍣 Timer1 */
Timer1_Init();
/* <EFBFBD><EFBFBD>机自动加载并运<EFBFBD><EFBFBD>待机时钟前台活跃应<EFBFBD><EFBFBD> */
/* 寮鏈鸿嚜鍔ㄥ姞杞藉苟杩愯屽緟鏈烘椂閽熷墠鍙版椿璺冨簲鐢 */
AppManager_StartApp(APP_ID_CLOCK);
Uart_SendString("[SYS] Event-driven framework ready\r\n");
// ====== 主循<EFBFBD><EFBFBD> ======
// ====== 涓诲惊鐜 ======
while (1) {
/* 0. <EFBFBD><EFBFBD>查主<EFBFBD><EFBFBD><EFBFBD><EFBFBD>按键定时标志 (<28><> 1ms <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>主循<E4B8BB><E5BEAA>响应清除并<E999A4><E5B9B6>) */
/* 0. 妫鏌ヤ富寰鐜鎸夐敭瀹氭椂鏍囧織 (鐢 1ms 涓鏂缃浣嶏紝涓诲惊鐜鍝嶅簲娓呴櫎骞跺勭悊) */
if (key_scan_flag) {
key_scan_flag = 0;
Event_KeyScan_Poll();
}
/* 1. 串口非阻塞指令捕<EFBFBD><EFBFBD> -> 装配为事件方式入<E5BC8F><E585A5> */
/* 1. 涓插彛闈為樆濉炴寚浠ゆ崟鑾 -> 瑁呴厤涓轰簨浠舵柟寮忓叆闃 */
cmd = Uart_RxChar();
if (cmd != '\0') {
Debug_ProcessCommand(cmd);
}
/* 2. 事件分发总线<EFBFBD><EFBFBD><EFBFBD><EFBFBD>询并处理队列<EFBFBD><EFBFBD>的所有有效事<EFBFBD><EFBFBD> */
/* 2. 浜嬩欢鍒嗗彂鎬荤嚎锛氬惊鐜杞璇㈠苟澶勭悊闃熷垪涓鐨勬墍鏈夋湁鏁堜簨浠 */
while (!EventQueue_IsEmpty()) {
Event_Dispatcher_Loop();
}
/* 3. 应用调度<EFBFBD><EFBFBD><EFBFBD><EFBFBD>当前<EFBFBD><EFBFBD>于前台活跃状<EFBFBD><EFBFBD>的应用集成了 CPU 运<><E8BF90>时间超时挂起保护 */
/* 3. 搴旂敤璋冨害涓蹇冿細杩愯屽綋鍓嶅勪簬鍓嶅彴娲昏穬鐘舵佺殑搴旂敤锛堥泦鎴愪簡 CPU 杩愯屾椂闂磋秴鏃舵寕璧蜂繚鎶わ級 */
AppManager_RunActiveApp();
/* 4. <EFBFBD><EFBFBD>动休眠判定:常<EFBFBD><EFBFBD>无操作闲置达到 60 <EFBFBD><EFBFBD> (6000 * 10ms = 60s) 时,切入低功耗停机休<EFBFBD><EFBFBD> */
/* 4. 动休眠判定:常无操作闲置达到 60 (6000 * 10ms = 60s) 时,切入低功耗停机休 */
if (inactivity_timer >= 6000) {
inactivity_timer = 0;
current_state = STATE_SLEEP; // 系统<EFBFBD><EFBFBD>为休眠状<EFBFBD><EFBFBD>
Enter_Low_Power_Sleep(); // 该函数是阻<E698AF><E998BB>MCU 将在此挂起<E68C82><E8B5B7>唤醒后将自动从其后继续执<E7BBAD>
current_state = STATE_NORMAL; // 唤醒后重新置为<E7BDAE><E4B8BA>常待机状<E69CBA>
AppManager_StartApp(APP_ID_CLOCK); // 重新<E9878D><E696B0><EFBFBD><EFBFBD>时钟应用以刷新画面和背光
current_state = STATE_SLEEP; // 系统为休眠状
// 强保电源锁存,复位所有按键状态计数(在 main.c 本地清除,杜绝 extern 重定位空间踩踏风险)
PWR_HOLD = 1;
key_up_hold = 0;
key_down_hold = 0;
key_confirm_hold = 0;
key_sos_hold = 0;
comb_hold = 0;
Enter_Low_Power_Sleep(); // 该函数是阻塞的MCU 将在此挂起。唤醒后将自动从其后继续执行
// 唤醒后的再次强拉高锁存与计数清零
PWR_HOLD = 1;
key_up_hold = 0;
key_down_hold = 0;
key_confirm_hold = 0;
key_sos_hold = 0;
comb_hold = 0;
current_state = STATE_NORMAL; // 唤醒后重新置为正常待机状态
AppManager_StartApp(APP_ID_CLOCK); // 重新开启时钟应用以刷新画面和背光
}
}
}
// 唤醒源事件标志<EFBFBD><EFBFBD>应的<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ISR 写入
volatile u8 p0_wakeup_flag = 0; // P0 <EFBFBD><EFBFBD>口按<EFBFBD><EFBFBD>唤醒标志
volatile u8 p2_wakeup_flag = 0; // P2 <EFBFBD><EFBFBD>口按<EFBFBD><EFBFBD>唤醒标志
volatile u8 p3_wakeup_flag = 0; // P3 <EFBFBD><EFBFBD>口射频中<EFBFBD><EFBFBD>唤醒标志
volatile u8 rf_wakeup_flag = 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒标志
// 鍞ら啋婧愪簨浠舵爣蹇楋紝鐢卞瑰簲鐨勫栭儴涓鏂 ISR 鍐欏叆
volatile u8 p0_wakeup_flag = 0; // P0 绔鍙f寜閿鍞ら啋鏍囧織
volatile u8 p2_wakeup_flag = 0; // P2 绔鍙f寜閿鍞ら啋鏍囧織
volatile u8 p3_wakeup_flag = 0; // P3 绔鍙e皠棰戜腑鏂鍞ら啋鏍囧織
volatile u8 rf_wakeup_flag = 0; // 灏勯戜腑鏂鍞ら啋鏍囧織
/* =========================================================================
* STC32G <EFBFBD><EFBFBD>口掉电<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒<EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (ISR)
* STC32G 绔鍙f帀鐢靛栭儴涓鏂鍞ら啋涓鏂鏈嶅姟绋嬪簭 (ISR)
* ========================================================================= */
/**
* @brief Port0 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<28><> isr_jump.asm <EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P0.1, P0.2, P0.3 按键在休眠模式下的物理触发并立刻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>反复执行<EFBFBD>
* @brief Port0 绔鍙f帀鐢典腑鏂鏈嶅姟鍑芥暟 (鐢 isr_jump.asm 寮曞煎畾浣嶈嚦姝)
* @details 璐熻矗澶勭悊 P0.1, P0.2, P0.3 鎸夐敭鍦ㄤ紤鐪犳ā寮忎笅鐨勭墿鐞嗚Е鍙戯紝骞剁珛鍒荤佺敤涓鏂闃叉㈠弽澶嶆墽琛屻
*/
void Port0_Isr(void) interrupt 13
{
EAXFR = 1; // 使能访问扩展寄存<EFBFBD><EFBFBD>
p0_wakeup_flag = P0INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P0 <20><><EFBFBD><EFBFBD>标志寄存器<E5AD98> (0x01作安全掩<E585A8><E68EA9>)
P0INTF = 0x00; // 清除 P0 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P0INTE = 0x00; // 【关<EFBFBD><EFBFBD>保护】立即关闭 P0 <20><><EFBFBD><EFBFBD><EFBFBD><E58581><EFBC8C><E998B2><EFBFBD><E68C89>处于低电平期间反复触<E5A48D><E8A7A6> ISR 导致堆栈溢出
EAXFR = 1; // 浣胯兘璁块棶鎵╁睍瀵勫瓨鍖
p0_wakeup_flag = P0INTF | 0x01;// 璇诲彇骞跺囦唤 P0 涓鏂鏍囧織瀵勫瓨鍣ㄥ (0x01浣滃畨鍏ㄦ帺鐮)
P0INTF = 0x00; // 娓呴櫎 P0 绔鍙d腑鏂鎮鎸傛爣蹇椾綅
P0INTE = 0x00; // 銆愬叧閿淇濇姢銆戯細绔嬪嵆鍏抽棴 P0 涓鏂鍏佽革紝闃叉㈡寜閿澶勪簬浣庣數骞虫湡闂村弽澶嶈Е鍙 ISR 瀵艰嚧鍫嗘爤婧㈠嚭
}
/**
* @brief Port2 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<28><> isr_jump.asm <EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P2.6 (SOS按键) <20><> P2.1 (<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<E594A4>
* @brief Port2 绔鍙f帀鐢典腑鏂鏈嶅姟鍑芥暟 (鐢 isr_jump.asm 寮曞煎畾浣嶈嚦姝)
* @details 璐熻矗澶勭悊 P2.6 (SOS鎸夐敭) 涓 P2.1 (灏勯戞暟鎹鑴) 鍦ㄤ紤鐪犳ā寮忎笅鐨勭墿鐞嗚烦鍙樺敜閱掋
*/
void Port2_Isr(void) interrupt 15
{
EAXFR = 1; // 使能扩展寄存<EFBFBD><EFBFBD>
p2_wakeup_flag = P2INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P2 <20><><EFBFBD><EFBFBD>标志寄存区的<E58CBA><E79A84>
P2INTF = 0x00; // 清除 P2 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P2INTE = 0x00; // 立即关闭 P2 <20><><EFBFBD><EFBFBD>通道<EFBC8C><E998B2>低电平期间反复重<E5A48D><E9878D>
EAXFR = 1; // 浣胯兘鎵╁睍瀵勫瓨鍖
p2_wakeup_flag = P2INTF | 0x01;// 璇诲彇骞跺囦唤 P2 涓鏂鏍囧織瀵勫瓨鍖虹殑鍊
P2INTF = 0x00; // 娓呴櫎 P2 绔鍙d腑鏂鎮鎸傛爣蹇椾綅
P2INTE = 0x00; // 绔嬪嵆鍏抽棴 P2 涓鏂閫氶亾锛岄槻姝浣庣數骞虫湡闂村弽澶嶉噸鍏
}
/**
* @brief Port3 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<28><> isr_jump.asm <EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P3.6 (新射频数<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<E594A4>
* @brief Port3 绔鍙f帀鐢典腑鏂鏈嶅姟鍑芥暟 (鐢 isr_jump.asm 寮曞煎畾浣嶈嚦姝)
* @details 璐熻矗澶勭悊 P3.6 (鏂板皠棰戞暟鎹鑴) 鍦ㄤ紤鐪犳ā寮忎笅鐨勭墿鐞嗚烦鍙樺敜閱掋
*/
void Port3_Isr(void) interrupt 16
{
EAXFR = 1; // 使能访问扩展寄存<EFBFBD><EFBFBD>
p3_wakeup_flag = P3INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P3 <20><><EFBFBD><EFBFBD>标志寄存器<E5AD98> (0x01作安全掩<E585A8><E68EA9>)
P3INTF = 0x00; // 清除 P3 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
P3INTE = 0x00; // 立即关闭 P3 <20><><EFBFBD><EFBFBD>通道防止反复重<E5A48D><E9878D>
EAXFR = 1; // 浣胯兘璁块棶鎵╁睍瀵勫瓨鍖
p3_wakeup_flag = P3INTF | 0x01;// 璇诲彇骞跺囦唤 P3 涓鏂鏍囧織瀵勫瓨鍣ㄥ (0x01浣滃畨鍏ㄦ帺鐮)
P3INTF = 0x00; // 娓呴櫎 P3 绔鍙d腑鏂鎮鎸傛爣蹇椾綅
P3INTE = 0x00; // 绔嬪嵆鍏抽棴 P3 涓鏂閫氶亾锛岄槻姝㈠弽澶嶉噸鍏
}

View File

@@ -328,16 +328,18 @@ void Enter_Low_Power_Sleep(void)
// 使能访问扩展特殊功能寄存器
P_SW2 |= 0x80;
// 7. 配置 Port0 中断唤醒源 (KEY_UP=P0.1, KEY_CONFIRM=P0.2, KEY_DOWN=P0.3)
P0IM1 |= 0x0E;
P0IM0 &= ~0x0E; // 下降沿触发
// 7. 配置 Port0 唤醒源 (KEY_UP=P0.1, KEY_CONFIRM=P0.2,剔除 KEY_DOWN 模拟引脚,防止低电平信号干扰)
P0IM1 &= ~0x06; // 下降沿触发 (PxIM1=0, PxIM0=0)
P0IM0 &= ~0x06;
P0INTF = 0x00; // 清除挂起的中断标志
P0INTE |= 0x0E; // 开启 P0.1, P0.2, P0.3 中断允许
P0WKUE |= 0x0E; // 使能 P0.1, P0.2, P0.3 掉电唤醒
P0INTE |= 0x06; // 开启 P0.1, P0.2 中断允许
P0WKUE |= 0x06; // 使能 P0.1, P0.2 掉电唤醒
P0PU |= 0x06; // 强内部上拉
P0IE |= 0x06; // 开启数字输入
// 8. 配置 Port2 中断唤醒源 (SOS=P2.6)
P2IM1 |= 0x40;
P2IM0 &= ~0x40; // 下降沿触发
// 8. 配置 Port2 唤醒源 (SOS=P2.6)
P2IM1 &= ~0x40; // 下降沿触发 (PxIM1=0, PxIM0=0)
P2IM0 &= ~0x40;
P2INTF = 0x00; // 清除挂起标志
P2INTE |= 0x40; // 开启 P2.6 中断允许
P2WKUE |= 0x40; // 使能 P2.6 掉电唤醒