2026-07-15 15:57:37 +08:00
|
|
|
|
#include "config.h"
|
2026-07-15 16:14:30 +08:00
|
|
|
|
#include "rgb.h"
|
|
|
|
|
|
#include "event.h"
|
|
|
|
|
|
#include "app_manager.h"
|
|
|
|
|
|
#include "database.h"
|
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
|
#include "system.h"
|
2026-07-15 15:57:37 +08:00
|
|
|
|
#include "../Drivers/rf.h"
|
2026-07-15 16:14:30 +08:00
|
|
|
|
#include "../Drivers/lcd.h"
|
2026-07-31 13:57:06 +08:00
|
|
|
|
#include "../Drivers/timer.h"
|
2026-07-15 15:57:37 +08:00
|
|
|
|
|
2026-07-31 18:28:52 +08:00
|
|
|
|
/* =========================================================================
|
|
|
|
|
|
* 【烧录必读】STC-ISP 下载时时钟频率必须选择 24MHz,且不能只改这一处
|
|
|
|
|
|
* =========================================================================
|
|
|
|
|
|
* 本项目代码里多处对"芯片实际运行在 24MHz"这件事做了硬编码假设,而不是每处都
|
|
|
|
|
|
* 从 MAIN_Fosc 动态换算;如果烧录时在 STC-ISP 里选了别的 IRC 频率(或换成外部
|
|
|
|
|
|
* 晶振但频率不是 24MHz),下面这些地方会全部跟着出错,不是改一下 config.h 里的
|
|
|
|
|
|
* MAIN_Fosc 常量就能自动生效的:
|
|
|
|
|
|
* 1. App/config.h:169 MAIN_Fosc = 24000000UL —— 大部分模块的换算基准。
|
|
|
|
|
|
* 2. Drivers/timer.c Timer1_Init() 里 1ms 定时重装值由 MAIN_Fosc 动态算出,
|
|
|
|
|
|
* 跟着 MAIN_Fosc 改没问题。
|
|
|
|
|
|
* 3. App/database.c IAP_TPS 由 MAIN_Fosc 动态算出 (Flash 读写/擦除等待周期),
|
|
|
|
|
|
* 跟着 MAIN_Fosc 改没问题,但算错会导致 Flash 读写异常甚至数据损坏。
|
|
|
|
|
|
* 4. App/system.c Uart1_Init() 里 Timer2 波特率重装值 (T2L=0xCC, T2H=0xFF)
|
|
|
|
|
|
* 是按 24MHz/115200 手工算好直接硬编码的数字,***不会跟着 MAIN_Fosc 变化***,
|
|
|
|
|
|
* 实际主频不是 24MHz 时串口波特率会直接算错,调试串口输出全部变乱码。
|
|
|
|
|
|
* 5. Drivers/rf.c/timer.c 里所有 EV1527 时序阈值和 RF_Delay_us() 都基于
|
|
|
|
|
|
* "Timer0 工作在标准 12T 模式、1 个计数节拍 = 12/Fosc 秒"这个换算关系,
|
|
|
|
|
|
* 代码里到处写的 "0.5us/tick"、"* 2UL" 都是 12/24MHz = 0.5us 这个具体
|
|
|
|
|
|
* 数字,***同样不会跟着 MAIN_Fosc 变化***,主频不对会导致 RF 收发全部解码/
|
|
|
|
|
|
* 发射失败。
|
|
|
|
|
|
* 结论:必须保证 STC-ISP 烧录时选择的时钟频率就是 24MHz,代码里各处的计时也
|
|
|
|
|
|
* 都是按实际运行在 24MHz 主频来写的,两边必须一致。
|
|
|
|
|
|
* ========================================================================= */
|
|
|
|
|
|
|
2026-07-15 15:57:37 +08:00
|
|
|
|
/* =========================================================================
|
2026-07-15 16:14:30 +08:00
|
|
|
|
* 系统全局变量定义
|
2026-07-15 15:57:37 +08:00
|
|
|
|
* ========================================================================= */
|
2026-07-31 09:22:07 +08:00
|
|
|
|
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默认为正常时钟待机页
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-17 19:43:02 +08:00
|
|
|
|
|
2026-07-31 18:05:23 +08:00
|
|
|
|
u8 menu_select = 0; // 当前菜单高亮的选中项索引 (menu_app 0~3,pair_app 传感器类型选择 0~4)
|
2026-07-31 09:22:07 +08:00
|
|
|
|
u32 captured_addr = 0; // 配对或报警时,捕获到的传感器 24 位 EV1527 射频物理地址
|
|
|
|
|
|
u8 captured_type = 0; // 正在对码或触发警报的传感器设备类型 (0:门磁, 1:PIR...)
|
|
|
|
|
|
u8 alarm_sensor_slot = 0; // 触发警报的传感器在 sensor_list 数组中的索引槽位号
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 传感器存储列表数据库,位于单片机外部 XDATA 存储空间,总共 16 个槽位
|
2026-07-15 15:57:37 +08:00
|
|
|
|
Sensor_Slot xdata sensor_list[16];
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 全局滴答与定时中断计数变量,位于 volatile 防止被编译器优化
|
|
|
|
|
|
volatile u16 ms_tick = 0; // 定时中断 1ms 基准滴答累加器
|
|
|
|
|
|
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; // ▲ + ▼ 组合键按下时长累加
|
2026-07-15 15:57:37 +08:00
|
|
|
|
|
|
|
|
|
|
/* =========================================================================
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* 串口调试指令解析与事件派发封装
|
2026-07-15 16:14:30 +08:00
|
|
|
|
* ========================================================================= */
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* @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': 触发屏幕与无线控制引脚测试。
|
2026-07-31 15:53:15 +08:00
|
|
|
|
* - 'e'/'E': DEBUG,打印 RF 边沿中断解码排查计数器。
|
2026-07-30 13:46:44 +08:00
|
|
|
|
*/
|
|
|
|
|
|
/**
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* @brief 串口调试专属:RGB 物理颜色通道排查测试
|
|
|
|
|
|
* @details 依次发送纯红、纯绿、纯蓝的数据流,每个颜色亮起 2 秒,帮助肉眼校对物理灯珠的实际颜色映射关系
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-30 13:46:44 +08:00
|
|
|
|
void RGB_Diagnostic_Test(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendString("\r\n=== RGB LED Color Channel Test Starting ===\r\n");
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 1. 尝试发送红色控制数据 (G=0, R=150, B=0)
|
2026-07-30 13:46:44 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 熄灭
|
2026-07-30 13:46:44 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
Delay_ms(300);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 2. 尝试发送绿色控制数据 (G=150, R=0, B=0)
|
2026-07-30 13:46:44 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 熄灭
|
2026-07-30 13:46:44 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
Delay_ms(300);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 3. 尝试发送蓝色控制数据 (G=0, R=0, B=150)
|
2026-07-30 13:46:44 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 彻底熄灭
|
2026-07-30 13:46:44 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
Uart_SendString("=== RGB LED Color Channel Test Ended ===\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-15 16:14:30 +08:00
|
|
|
|
void Debug_ProcessCommand(char cmd)
|
|
|
|
|
|
{
|
|
|
|
|
|
SystemEvent debug_evt;
|
|
|
|
|
|
debug_evt.extra_data = 0;
|
|
|
|
|
|
debug_evt.extra_size = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (cmd == 'u') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_UP_CLICK;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-16 17:52:52 +08:00
|
|
|
|
EventQueue_Push(debug_evt); // 压入队尾
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_UP Clicked\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'U') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_UP_LONG;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_Push(debug_evt);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_UP Long Pressed\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'd') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_DOWN_CLICK;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_Push(debug_evt);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_DOWN Clicked\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'D') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_DOWN_LONG;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_Push(debug_evt);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_DOWN Long Pressed\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 's') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_SOS_CLICK;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_URGENT;
|
2026-07-31 09:22:07 +08:00
|
|
|
|
EventQueue_InsertFront(debug_evt); // 紧急事件插入队首
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_SOS Clicked\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'S') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_SOS_LONG;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_URGENT;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_InsertFront(debug_evt);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_SOS Long Pressed\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'c' || cmd == 'C') {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-15 16:14:30 +08:00
|
|
|
|
EventQueue_Push(debug_evt);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] KEY_UP+DOWN Combined\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'a' || cmd == 'A') {
|
2026-07-16 17:52:52 +08:00
|
|
|
|
u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址
|
2026-07-15 16:14:30 +08:00
|
|
|
|
u8 mock_slot;
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 如果本地数据库中没有匹配该射频,则强制登记进 1 号防区
|
2026-07-15 16:14:30 +08:00
|
|
|
|
if (!Check_Sensor_ID(mock_addr, &mock_slot)) {
|
|
|
|
|
|
Add_Sensor_With_Zone(mock_addr, 0, 1);
|
|
|
|
|
|
}
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.key_event = KEY_EVENT_NONE;
|
2026-07-31 09:22:07 +08:00
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_HIGH; // 入侵报警设为 HIGH 优先级
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.extra_data = mock_addr;
|
|
|
|
|
|
debug_evt.extra_size = 4;
|
|
|
|
|
|
EventQueue_InsertFront(debug_evt); // 高优先级插队
|
|
|
|
|
|
Uart_SendString("[UART] Mock RF Alarm\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'p' || cmd == 'P') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 只有当手环切入 Pair 模式时,模拟对码信号才有效
|
2026-07-17 19:43:02 +08:00
|
|
|
|
if (AppManager_GetActiveAppID() == APP_ID_PAIR) {
|
|
|
|
|
|
debug_evt.key_event = KEY_EVENT_NONE;
|
|
|
|
|
|
debug_evt.priority = EVENT_PRIORITY_NORMAL;
|
2026-07-31 09:22:07 +08:00
|
|
|
|
debug_evt.extra_data = 0x789ABC; // 设定模拟对码硬件地址
|
2026-07-17 19:43:02 +08:00
|
|
|
|
debug_evt.extra_size = 4;
|
|
|
|
|
|
EventQueue_Push(debug_evt);
|
|
|
|
|
|
Uart_SendString("[UART] Mock RF Pair Signal\r\n");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Uart_SendString("[UART] Not in PAIR mode\r\n");
|
|
|
|
|
|
}
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == '1') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 模拟切换至 正常撤防 (NORMAL) 状态并刷新时钟
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (AppManager_GetActiveAppID() == APP_ID_HOME) {
|
2026-07-15 15:57:37 +08:00
|
|
|
|
current_state = STATE_NORMAL;
|
2026-07-31 19:43:43 +08:00
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min, current_weekday, current_day, current_month);
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] State: NORMAL\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == '2') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 模拟切换至 已布防 (ARMED) 状态,普通门磁可触发警报
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (AppManager_GetActiveAppID() == APP_ID_HOME) {
|
2026-07-15 15:57:37 +08:00
|
|
|
|
current_state = STATE_ARMED;
|
2026-07-31 19:43:43 +08:00
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min, current_weekday, current_day, current_month);
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] State: ARMED\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == '3') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 模拟切换至 已撤防 (DISARMED) 状态,忽略普通报警
|
2026-07-31 18:05:23 +08:00
|
|
|
|
if (AppManager_GetActiveAppID() == APP_ID_HOME) {
|
2026-07-15 16:14:30 +08:00
|
|
|
|
current_state = STATE_DISARMED;
|
2026-07-31 19:43:43 +08:00
|
|
|
|
UI_ShowClockPage(current_state, current_hour, current_min, current_weekday, current_day, current_month);
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] State: DISARMED\r\n");
|
2026-07-15 16:14:30 +08:00
|
|
|
|
} else if (cmd == 'z' || cmd == 'Z') {
|
2026-07-31 18:49:03 +08:00
|
|
|
|
// 直接强制进入低功耗休眠,测试用 (原来靠伪造全局闲置计时器触发,现改为直接调用)
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("[UART] Force Entering Sleep mode!\r\n");
|
2026-07-31 18:49:03 +08:00
|
|
|
|
current_state = STATE_SLEEP;
|
|
|
|
|
|
Enter_Low_Power_Sleep();
|
|
|
|
|
|
AppManager_SwitchToForeground(&home_app); // 唤醒后强制重绘时钟画面
|
2026-07-30 13:46:44 +08:00
|
|
|
|
} else if (cmd == 'q' || cmd == 'Q') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
RGB_Diagnostic_Test(); // 启动 RGB 物理颜色通道排查测试
|
2026-07-16 17:52:52 +08:00
|
|
|
|
} else if (cmd == 't' || cmd == 'T') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
RF_DiagnosticMode('t'); // 触发射频连续发射诊断 (绿色爆闪)
|
2026-07-17 19:43:02 +08:00
|
|
|
|
} else if (cmd == 'r' || cmd == 'R') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监听诊断
|
2026-07-29 10:16:05 +08:00
|
|
|
|
} else if (cmd == 'l' || cmd == 'L') {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
Loopback_Test(); // 触发物理电气回环测试 (短路 P2.1 和 P3.6 自检)
|
2026-07-31 15:53:15 +08:00
|
|
|
|
} else if (cmd == 'e' || cmd == 'E') {
|
|
|
|
|
|
RF_PrintDebugCounters(); // DEBUG: 打印 RF 边沿中断解码排查计数器
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 13:57:06 +08:00
|
|
|
|
// ====== 调试用最小化启动开关 ======
|
|
|
|
|
|
// 置 1 时 main() 只做点亮屏幕这一件事,RF/自检/数据库/事件框架/Timer1 全部跳过,
|
2026-07-31 15:53:15 +08:00
|
|
|
|
// 用于定位"开机反复重启"问题的范围。
|
|
|
|
|
|
// 根因(isr_jump.asm 缺少 Port3 中断向量重定向、且该文件从未加入工程编译)已定位并修复,
|
|
|
|
|
|
// 现改回 0,恢复完整正常启动流程,测试整机端到端是否稳定。
|
|
|
|
|
|
#define DEBUG_MINIMAL_BOOT 0
|
2026-07-31 13:57:06 +08:00
|
|
|
|
|
2026-07-15 15:57:37 +08:00
|
|
|
|
/* =========================================================================
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* 主函数 (入口)
|
2026-07-15 15:57:37 +08:00
|
|
|
|
* ========================================================================= */
|
2026-07-31 13:57:06 +08:00
|
|
|
|
#if DEBUG_MINIMAL_BOOT
|
|
|
|
|
|
|
|
|
|
|
|
void main(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
// ====== STC32G 特殊功能寄存器内核基础初始化 ======
|
|
|
|
|
|
WTST = 0; // 设置程序 Flash 访问等待时间为 0 (最高速运行)
|
|
|
|
|
|
EAXFR = 1; // 允许访问扩展特殊功能寄存器 (XSFR)
|
|
|
|
|
|
CKCON = 0; // 外部总线时钟设定为最快
|
|
|
|
|
|
WDT_CONTR = 0x00; // 关闭看门狗定时器
|
|
|
|
|
|
|
|
|
|
|
|
// ====== 步骤 A:加回 RF_Init() 与 Timer1_Init(),先不打开 RF 接收 ======
|
|
|
|
|
|
GPIO_Init(); // 配置各个引脚的推挽输出/准双向模式及内部上拉 (锁存 PWR_HOLD=1)
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 上电第一时间强制发送 0 码关闭灯条,熄灭上电暂态引起的随机白光
|
|
|
|
|
|
RF_Init(); // 加回来:Timer0 常驻自由运行 + P3.6 常态双边沿中断 + 上拉,此时芯片仍 SHUT=1 关闭
|
|
|
|
|
|
Delay_ms(500); // 软启动延时,等待供电电容稳定
|
|
|
|
|
|
LCD_Init(); // 初始化 LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列并开启背光
|
|
|
|
|
|
Uart1_Init(); // 初始化串口 1 波特率 115200 供调试日志
|
|
|
|
|
|
Uart_SendString("Wristband System Initialized! (DEBUG_MINIMAL_BOOT=1, step A: RF_Init+Timer1_Init)\r\n");
|
|
|
|
|
|
|
2026-07-31 15:53:15 +08:00
|
|
|
|
Timer1_Init(); // 全局中断 EA=1 从这里开始生效,Timer0 溢出中断开始工作
|
2026-07-31 13:57:06 +08:00
|
|
|
|
|
2026-07-31 15:53:15 +08:00
|
|
|
|
// ====== 步骤 C:真正的病根 (isr_jump.asm 缺少 Port3 重定向、且该文件从未被加入工程编译) 已修复,
|
|
|
|
|
|
// P3.6 中断与 RF_HandleEdgeInterrupt 都已恢复为正常逻辑,现在测试真实功能是否稳定 ======
|
|
|
|
|
|
RF_SetMode(1);
|
|
|
|
|
|
|
|
|
|
|
|
LCD_ShowStringCentered(100, "STEP C OK", COLOR_WHITE, COLOR_BLACK);
|
|
|
|
|
|
LCD_ShowStringCentered(130, "ISR fixed", COLOR_GRAY, COLOR_BLACK);
|
2026-07-31 13:57:06 +08:00
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
|
Delay_ms(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
2026-07-15 15:57:37 +08:00
|
|
|
|
void main(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
char cmd;
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// ====== STC32G 特殊功能寄存器内核基础初始化 ======
|
|
|
|
|
|
WTST = 0; // 设置程序 Flash 访问等待时间为 0 (最高速运行)
|
|
|
|
|
|
EAXFR = 1; // 允许访问扩展特殊功能寄存器 (XSFR)
|
|
|
|
|
|
CKCON = 0; // 外部总线时钟设定为最快
|
2026-07-16 17:52:52 +08:00
|
|
|
|
WDT_CONTR = 0x00; // 关闭看门狗定时器
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// ====== 硬件各模块基础初始化 ======
|
|
|
|
|
|
GPIO_Init(); // 配置各个引脚的推挽输出/准双向模式及内部上拉 (锁存 PWR_HOLD=1)
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 【首要修正】:上电第一时间强制发送 0 码关闭灯条,熄灭上电暂态引起的随机白光!
|
|
|
|
|
|
RF_Init(); // 初始化射频芯片各引脚控制
|
|
|
|
|
|
Delay_ms(500); // 软启动延时,等待供电电容稳定
|
2026-07-31 18:09:39 +08:00
|
|
|
|
LCD_Init(); // 初始化 LHS114TC-IF03 (ST7789V) 屏幕控制寄存器序列 (背光保持关闭,避免闪烁)
|
2026-07-31 09:22:07 +08:00
|
|
|
|
Uart1_Init(); // 初始化串口 1 波特率 115200 供调试日志
|
2026-07-17 19:43:02 +08:00
|
|
|
|
Uart_SendString("Wristband System Initialized!\r\n");
|
2026-07-15 15:57:37 +08:00
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
Self_Test(); // 执行上电硬件自检 (PWR_HOLD锁存、P0.3 ADC按键常态、P1.3 电池电量)
|
|
|
|
|
|
Load_Database(); // 从 IAP Flash 第 254 扇区读取所有已绑定的传感器数据至 RAM
|
|
|
|
|
|
|
|
|
|
|
|
/* 步骤 1: 初始化事件环形缓冲区队列 */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
EventQueue_Init();
|
|
|
|
|
|
|
2026-07-31 18:05:23 +08:00
|
|
|
|
/* 步骤 2+5: 初始化应用管理器并登记所有前台应用,默认加载 HomeApp */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
AppManager_Init();
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 启动并挂载后台射频监控应用,开始侦听无线传感器信号 */
|
2026-07-28 18:34:28 +08:00
|
|
|
|
AppManager_AttachToBackground(&rf_monitor_app);
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 启动 1ms 系统基准定时器 Timer1 */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
Timer1_Init();
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 开机自动加载并运行待机时钟前台活跃应用 */
|
2026-07-31 18:05:23 +08:00
|
|
|
|
AppManager_StartApp(APP_ID_HOME);
|
2026-07-17 19:43:02 +08:00
|
|
|
|
|
|
|
|
|
|
Uart_SendString("[SYS] Event-driven framework ready\r\n");
|
2026-07-15 15:57:37 +08:00
|
|
|
|
|
2026-07-31 18:09:39 +08:00
|
|
|
|
// 所有初始化与首帧时钟界面绘制均已完成,此刻才点亮背光,避免开机过程中的中间画面被看到而产生闪烁
|
|
|
|
|
|
SGM_CTRL = 0;
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// ====== 主循环 ======
|
2026-07-15 15:57:37 +08:00
|
|
|
|
while (1) {
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 0. 检查主循环按键定时标志 (由 1ms 中断置位,主循环响应清除并处理) */
|
2026-07-28 18:03:20 +08:00
|
|
|
|
if (key_scan_flag) {
|
|
|
|
|
|
key_scan_flag = 0;
|
|
|
|
|
|
Event_KeyScan_Poll();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 18:49:03 +08:00
|
|
|
|
/* 0.5 检查整秒滴答标志 (由 Clock_IncMS 每秒置位一次),转换为事件入队分发;
|
|
|
|
|
|
* 各 App 自行决定要不要用它累计自己的闲置时长 (收到任何按键事件就清零),
|
|
|
|
|
|
* 不再由主循环维护一个全局的休眠倒计时。 */
|
|
|
|
|
|
if (second_tick_flag) {
|
|
|
|
|
|
second_tick_flag = 0;
|
|
|
|
|
|
{
|
|
|
|
|
|
SystemEvent tick_evt;
|
|
|
|
|
|
tick_evt.key_event = KEY_EVENT_SECOND_TICK;
|
|
|
|
|
|
tick_evt.priority = EVENT_PRIORITY_LOW;
|
|
|
|
|
|
tick_evt.extra_data = 0;
|
|
|
|
|
|
tick_evt.extra_size = 0;
|
|
|
|
|
|
EventQueue_Push(tick_evt);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 1. 串口非阻塞指令捕获 -> 装配为事件方式入队 */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
cmd = Uart_RxChar();
|
|
|
|
|
|
if (cmd != '\0') {
|
2026-07-15 16:14:30 +08:00
|
|
|
|
Debug_ProcessCommand(cmd);
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 2. 事件分发总线:循环轮询并处理队列中的所有有效事件 */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
while (!EventQueue_IsEmpty()) {
|
|
|
|
|
|
Event_Dispatcher_Loop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
/* 3. 应用调度中心:运行当前处于前台活跃状态的应用(集成了 CPU 运行时间超时挂起保护) */
|
2026-07-15 15:57:37 +08:00
|
|
|
|
AppManager_RunActiveApp();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-31 13:57:06 +08:00
|
|
|
|
#endif // DEBUG_MINIMAL_BOOT
|
|
|
|
|
|
|
2026-07-31 09:22:07 +08:00
|
|
|
|
// 唤醒源事件标志,由对应的外部中断 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; // 射频中断唤醒标志
|
2026-07-16 17:52:52 +08:00
|
|
|
|
|
2026-07-15 15:57:37 +08:00
|
|
|
|
/* =========================================================================
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* STC32G 端口掉电外部中断唤醒中断服务程序 (ISR)
|
2026-07-15 15:57:37 +08:00
|
|
|
|
* ========================================================================= */
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* @brief Port0 端口掉电中断服务函数 (由 isr_jump.asm 引导定位至此)
|
|
|
|
|
|
* @details 负责处理 P0.1, P0.2, P0.3 按键在休眠模式下的物理触发,并立刻禁用中断防止反复执行。
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 15:57:37 +08:00
|
|
|
|
void Port0_Isr(void) interrupt 13
|
|
|
|
|
|
{
|
2026-07-31 09:22:07 +08:00
|
|
|
|
EAXFR = 1; // 使能访问扩展寄存区
|
|
|
|
|
|
p0_wakeup_flag = P0INTF | 0x01;// 读取并备份 P0 中断标志寄存器值 (0x01作安全掩码)
|
|
|
|
|
|
P0INTF = 0x00; // 清除 P0 端口中断悬挂标志位
|
|
|
|
|
|
P0INTE = 0x00; // 【关键保护】:立即关闭 P0 中断允许,防止按键处于低电平期间反复触发 ISR 导致堆栈溢出
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 17:52:52 +08:00
|
|
|
|
/**
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* @brief Port2 端口掉电中断服务函数 (由 isr_jump.asm 引导定位至此)
|
|
|
|
|
|
* @details 负责处理 P2.6 (SOS按键) 与 P2.1 (射频数据脚) 在休眠模式下的物理跳变唤醒。
|
2026-07-16 17:52:52 +08:00
|
|
|
|
*/
|
2026-07-15 15:57:37 +08:00
|
|
|
|
void Port2_Isr(void) interrupt 15
|
|
|
|
|
|
{
|
2026-07-31 09:22:07 +08:00
|
|
|
|
EAXFR = 1; // 使能扩展寄存区
|
|
|
|
|
|
p2_wakeup_flag = P2INTF | 0x01;// 读取并备份 P2 中断标志寄存区的值
|
|
|
|
|
|
P2INTF = 0x00; // 清除 P2 端口中断悬挂标志位
|
|
|
|
|
|
P2INTE = 0x00; // 立即关闭 P2 中断通道,防止低电平期间反复重入
|
2026-07-15 15:57:37 +08:00
|
|
|
|
}
|
2026-07-17 19:43:02 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-31 09:22:07 +08:00
|
|
|
|
* @brief Port3 端口掉电中断服务函数 (由 isr_jump.asm 引导定位至此)
|
2026-07-31 16:39:06 +08:00
|
|
|
|
* @details P3.6 (RF_RX_DATA) 单边沿触发中断现在改为常态开启 (见 RF_Init()),身兼两职:
|
|
|
|
|
|
* 1. 休眠期间作为唤醒源,记录 p3_wakeup_flag 供 Wakeup_Restore() 判定唤醒来源
|
|
|
|
|
|
* (上升沿/下降沿均支持掉电唤醒);
|
|
|
|
|
|
* 2. 正常运行期间驱动 RF_HandleEdgeInterrupt() 增量解码 EV1527 信号 (内部会在
|
|
|
|
|
|
* 每次触发后软件翻转到相反边沿,模拟双边沿触发)。
|
2026-07-31 15:53:15 +08:00
|
|
|
|
* 不再像旧版那样在首次触发后自行关闭 P3INTE,否则第 1 项唤醒功能会在第一次边沿后失效。
|
2026-07-17 19:43:02 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Port3_Isr(void) interrupt 16
|
|
|
|
|
|
{
|
2026-07-31 09:22:07 +08:00
|
|
|
|
EAXFR = 1; // 使能访问扩展寄存器
|
|
|
|
|
|
p3_wakeup_flag = P3INTF | 0x01;// 读取并备份 P3 中断标志寄存器值 (0x01作安全掩码)
|
|
|
|
|
|
P3INTF = 0x00; // 清除 P3 端口中断悬挂标志位
|
2026-07-31 16:39:06 +08:00
|
|
|
|
RF_HandleEdgeInterrupt(); // 驱动 EV1527 边沿增量解码状态机
|
2026-07-17 19:43:02 +08:00
|
|
|
|
}
|