fix: 修复 main.c/event.c/lcd.c 的中文注释乱码,统一为 UTF-8 编码
lcd.c 原本整体是 GBK 编码,直接转码即可。main.c 与 event.c 曾被 Keil 环境以错误编码保存导致部分注释损坏,本次以历史提交中未损坏的 版本为基底恢复正确注释文本,并将其后新增的真实代码改动(RGB 三色 诊断指令、SOS 按键状态机解锁)对应的注释一并还原,不涉及任何代码逻辑变更。
This commit is contained in:
178
App/event.c
178
App/event.c
@@ -6,17 +6,17 @@
|
||||
#include "xtell.h"
|
||||
#include "../Drivers/adc.h"
|
||||
|
||||
// 定义事件<EFBFBD><EFBFBD>形队列的<EFBFBD><EFBFBD>大深度为 8
|
||||
// 定义事件环形队列的最大深度为 8
|
||||
#define EVENT_QUEUE_DEPTH 8
|
||||
|
||||
// <EFBFBD><EFBFBD>形队列存储数<EFBFBD><EFBFBD> (存放在单片机 xdata 拓展 RAM区中)
|
||||
// 环形队列存储数组 (存放在单片机 xdata 拓展 RAM区中)
|
||||
static SystemEvent xdata event_queue[EVENT_QUEUE_DEPTH];
|
||||
static u8 queue_head = 0; // 队<EFBFBD><EFBFBD><EFBFBD><EFBFBD>指<EFBFBD><EFBFBD>
|
||||
static u8 queue_tail = 0; // 队尾写指<EFBFBD><EFBFBD>
|
||||
static u8 queue_count = 0; // 当前队列内有效事件<EFBFBD><EFBFBD>数
|
||||
static u8 queue_head = 0; // 队首读指针
|
||||
static u8 queue_tail = 0; // 队尾写指针
|
||||
static u8 queue_count = 0; // 当前队列内有效事件总数
|
||||
|
||||
/**
|
||||
* @brief 初<EFBFBD><EFBFBD>化/清空事件队列
|
||||
* @brief 初始化/清空事件队列
|
||||
*/
|
||||
void EventQueue_Init(void)
|
||||
{
|
||||
@@ -26,63 +26,63 @@ void EventQueue_Init(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将普通事件压入队<EFBFBD><EFBFBD>
|
||||
* @param evt 输入的系统事<EFBFBD><EFBFBD>
|
||||
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
|
||||
* @brief 将普通事件压入队尾
|
||||
* @param evt 输入的系统事件
|
||||
* @return bit 1-成功,0-失败
|
||||
*/
|
||||
bit EventQueue_Push(SystemEvent evt)
|
||||
{
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,丢弃事件
|
||||
EA = 0; // 关闭全局<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,保护临界区操作的原子<EFBFBD>
|
||||
EA = 0; // 关闭全局中断,保护临界区操作的原子性
|
||||
event_queue[queue_tail] = evt; // 存入队尾
|
||||
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针向后移<EFBFBD><EFBFBD>,回<EFBFBD><EFBFBD>
|
||||
queue_count++; // 有效计数<EFBFBD><EFBFBD> 1
|
||||
EA = 1; // 恢<EFBFBD><EFBFBD>全<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针向后移动,回环
|
||||
queue_count++; // 有效计数加 1
|
||||
EA = 1; // 恢复全局中断
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将高优先<EFBFBD><EFBFBD>/紧<><E7B4A7>事件强行插到队<EFBFBD><EFBFBD>
|
||||
* @param evt 输入的系统事<EFBFBD><EFBFBD>
|
||||
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
|
||||
* @brief 将高优先级/紧急事件强行插到队首
|
||||
* @param evt 输入的系统事件
|
||||
* @return bit 1-成功,0-失败
|
||||
*/
|
||||
bit EventQueue_InsertFront(SystemEvent evt)
|
||||
{
|
||||
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,插队失败
|
||||
EA = 0; // 屏蔽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// 头指针向前移动一位(带回<EFBFBD><EFBFBD>防溢出)
|
||||
EA = 0; // 屏蔽中断
|
||||
// 头指针向前移动一位(带回环防溢出)
|
||||
queue_head = (queue_head - 1 + EVENT_QUEUE_DEPTH) % EVENT_QUEUE_DEPTH;
|
||||
event_queue[queue_head] = evt; // 存入腾出的队首位<EFBFBD><EFBFBD>
|
||||
queue_count++; // 计数<EFBFBD><EFBFBD> 1
|
||||
EA = 1; // 恢<EFBFBD><EFBFBD>中<EFBFBD><EFBFBD>
|
||||
event_queue[queue_head] = evt; // 存入腾出的队首位置
|
||||
queue_count++; // 计数加 1
|
||||
EA = 1; // 恢复中断
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从队首弹出一<EFBFBD><EFBFBD>缓冲事件
|
||||
* @return SystemEvent 返回弹出的事件<EFBFBD><EFBFBD>若空返回空闲事<EFBFBD><EFBFBD>
|
||||
* @brief 从队首弹出一个缓冲事件
|
||||
* @return SystemEvent 返回弹出的事件。若空返回空闲事件
|
||||
*/
|
||||
SystemEvent EventQueue_Pop(void)
|
||||
{
|
||||
SystemEvent evt;
|
||||
// 默<EFBFBD><EFBFBD>空事件属<EFBFBD>
|
||||
// 默认空事件属性
|
||||
evt.key_event = KEY_EVENT_NONE;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
evt.extra_data = 0;
|
||||
evt.extra_size = 0;
|
||||
|
||||
if (queue_count == 0) return evt; // 队空,直接返回空闲事<EFBFBD><EFBFBD>
|
||||
|
||||
EA = 0; // 屏蔽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
evt = event_queue[queue_head]; // 读取队<EFBFBD><EFBFBD>数<EFBFBD><EFBFBD>
|
||||
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针向后移<EFBFBD><EFBFBD>,回<EFBFBD><EFBFBD>
|
||||
queue_count--; // 有效计数<EFBFBD><EFBFBD> 1
|
||||
EA = 1; // 恢<EFBFBD><EFBFBD>中<EFBFBD><EFBFBD>
|
||||
|
||||
if (queue_count == 0) return evt; // 队空,直接返回空闲事件
|
||||
|
||||
EA = 0; // 屏蔽中断
|
||||
evt = event_queue[queue_head]; // 读取队首数据
|
||||
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针向后移动,回环
|
||||
queue_count--; // 有效计数减 1
|
||||
EA = 1; // 恢复中断
|
||||
return evt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断队列<EFBFBD><EFBFBD>否为<EFBFBD><EFBFBD>
|
||||
* @brief 判断队列是否为空
|
||||
*/
|
||||
bit EventQueue_IsEmpty(void)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ bit EventQueue_IsEmpty(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断队列<EFBFBD><EFBFBD>否已<EFBFBD><EFBFBD>
|
||||
* @brief 判断队列是否已满
|
||||
*/
|
||||
bit EventQueue_IsFull(void)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ bit EventQueue_IsFull(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前队列<EFBFBD><EFBFBD>的事件<EFBFBD><EFBFBD>数
|
||||
* @brief 获取当前队列中的事件总数
|
||||
*/
|
||||
u8 EventQueue_GetCount(void)
|
||||
{
|
||||
@@ -106,98 +106,98 @@ u8 EventQueue_GetCount(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 事件分发器核心轮询<EFBFBD><EFBFBD>辑
|
||||
* @details 逐一处理队列<EFBFBD><EFBFBD>的事件,并根<EFBFBD><EFBFBD>系统当前的运行模式进行拦<EFBFBD><EFBFBD>、跳<EFBFBD><EFBFBD>或下发派发<EFBFBD>
|
||||
* @brief 事件分发器核心轮询逻辑
|
||||
* @details 逐一处理队列中的事件,并根据系统当前的运行模式进行拦截、跳转或下发派发。
|
||||
*/
|
||||
void Event_Dispatcher_Loop(void)
|
||||
{
|
||||
SystemEvent evt = EventQueue_Pop(); // 弹出<EFBFBD><EFBFBD><EFBFBD><EFBFBD>事件
|
||||
|
||||
// 如果<EFBFBD><EFBFBD>无事发生的空事件,直接<EFBFBD><EFBFBD><EFBFBD>
|
||||
SystemEvent evt = EventQueue_Pop(); // 弹出一个事件
|
||||
|
||||
// 如果是无事发生的空事件,直接退出
|
||||
if (evt.key_event == KEY_EVENT_NONE && evt.extra_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时<EFBFBD><EFBFBD>,重<EFBFBD><EFBFBD>闲置超时
|
||||
|
||||
|
||||
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时器,重置闲置超时
|
||||
|
||||
// 串口打印调试信息
|
||||
XTELL_LOG("[EVENT] key=");
|
||||
XTELL_LOG_HEX8((u8)evt.key_event);
|
||||
XTELL_LOG("\r\n");
|
||||
|
||||
// SOS 按键紧<EFBFBD><EFBFBD><EFBFBD><EFBFBD>理:若当前前台不为 SOS 应用,接收到 SOS <EFBFBD><EFBFBD>动作,立即强行切入到 SOS_APP 并执行求<EFBFBD><EFBFBD>
|
||||
// SOS 按键紧急处理:若当前前台不为 SOS 应用,接收到 SOS 键动作,立即强行切入到 SOS_APP 并执行求救
|
||||
if ((evt.key_event == KEY_EVENT_SOS_CLICK || evt.key_event == KEY_EVENT_SOS_LONG) &&
|
||||
AppManager_GetActiveAppID() != APP_ID_SOS) {
|
||||
AppManager_StartApp(APP_ID_SOS);
|
||||
return;
|
||||
}
|
||||
|
||||
// 关机事件处理:捕获到长按关机指令,直接调<EFBFBD><EFBFBD> Power_Off 关断电源
|
||||
// 关机事件处理:捕获到长按关机指令,直接调用 Power_Off 关断电源
|
||||
if (evt.key_event == KEY_EVENT_POWER_OFF) {
|
||||
Power_Off();
|
||||
return;
|
||||
}
|
||||
|
||||
// 常<EFBFBD><EFBFBD>事件(如普通的按键点击)直接<EFBFBD><EFBFBD>传分发给当前<EFBFBD><EFBFBD>于前台活跃的应<EFBFBD><EFBFBD>
|
||||
// 常规事件(如普通的按键点击)直接透传分发给当前处于前台活跃的应用
|
||||
AppManager_DispatchEvent(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 定时<EFBFBD><EFBFBD> 1 初<EFBFBD><EFBFBD>化,<EFBFBD><EFBFBD>定 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD>周期
|
||||
* @brief 定时器 1 初始化,设定 1ms 中断周期
|
||||
*/
|
||||
void Timer1_Init(void)
|
||||
{
|
||||
AUXR |= 0x40; // 设定定时<EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD> 1T 模式 (无分频,主<EFBFBD><EFBFBD>直接输<EFBFBD><EFBFBD>)
|
||||
TMOD &= 0x0F; // 设置定时<EFBFBD><EFBFBD> 1 模式寄存<EFBFBD><EFBFBD>,保留低四位 (定时<EFBFBD><EFBFBD>0配置)
|
||||
AUXR |= 0x40; // 设定定时器 1 为 1T 模式 (无分频,主频直接输入)
|
||||
TMOD &= 0x0F; // 设置定时器 1 模式寄存器,保留低四位 (定时器0配置)
|
||||
{
|
||||
// 按照系统主<EFBFBD> (MAIN_Fosc) 计算 1ms 对应的重装载<EFBFBD><EFBFBD>
|
||||
// 按照系统主频 (MAIN_Fosc) 计算 1ms 对应的重装载值
|
||||
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
|
||||
TL1 = (u8)reload; // 载入<EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD>
|
||||
TH1 = (u8)(reload >> 8);// 载入<EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD>
|
||||
TL1 = (u8)reload; // 载入低 8 位
|
||||
TH1 = (u8)(reload >> 8);// 载入高 8 位
|
||||
}
|
||||
ET1 = 1; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>定时<EFBFBD><EFBFBD> 1 <20><><EFBFBD><EFBFBD>允<EFBFBD>
|
||||
TR1 = 1; // <EFBFBD><EFBFBD>动定时器 1 计数
|
||||
EA = 1; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>全局<EFBFBD><EFBFBD><EFBFBD><EFBFBD>允<EFBFBD>
|
||||
ET1 = 1; // 开启定时器 1 中断允许
|
||||
TR1 = 1; // 启动定时器 1 计数
|
||||
EA = 1; // 开启全局中断允许
|
||||
}
|
||||
|
||||
// 全局按键<EFBFBD><EFBFBD>描触发标<EFBFBD><EFBFBD>
|
||||
// 全局按键扫描触发标志
|
||||
volatile bit key_scan_flag = 0;
|
||||
|
||||
/**
|
||||
* @brief 定时<EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (<EFBFBD><EFBFBD> 1ms 触发<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* @details 承担系统<EFBFBD><EFBFBD>时钟计算,并<EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>位主<EFBFBD><EFBFBD><EFBFBD><EFBFBD>按键<EFBFBD><EFBFBD>描标志,不直接在<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>进<EFBFBD> ADC 多<EFBFBD><EFBFBD>采样<EFBFBD>
|
||||
* @brief 定时器 1 中断服务程序 (每 1ms 触发一次)
|
||||
* @details 承担系统软时钟计算,并每 10ms 置位主循环按键扫描标志,不直接在中断中进行 ADC 多次采样。
|
||||
*/
|
||||
void Timer1_Isr(void) interrupt 3
|
||||
{
|
||||
// 1ms 定时更新<EFBFBD><EFBFBD>时钟
|
||||
// 1ms 定时更新软时钟
|
||||
Clock_IncMS();
|
||||
|
||||
// 报<EFBFBD><EFBFBD>屏幕红边<EFBFBD><EFBFBD>以 100ms 周期<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,进行<EFBFBD><EFBFBD>色爆闪指示
|
||||
// 报警屏幕红边框以 100ms 周期亮灭,进行颜色爆闪指示
|
||||
alarm_flash_flag = (ms_tick / 100) % 2;
|
||||
|
||||
/* 物理按键定时计数 (<EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>位一次标志位) */
|
||||
/* 物理按键定时计数 (每 10ms 置位一次标志位) */
|
||||
key_scan_timer++;
|
||||
if (key_scan_timer >= 10) {
|
||||
key_scan_timer = 0; // 重置<EFBFBD><EFBFBD>描分频<EFBFBD><EFBFBD>数<EFBFBD><EFBFBD>
|
||||
key_scan_flag = 1; // 仅在<EFBFBD><EFBFBD><EFBFBD><EFBFBD>里置起标志位,留待主<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>执<EFBFBD><EFBFBD>实际<EFBFBD><EFBFBD>取与消<EFBFBD><EFBFBD>
|
||||
key_scan_timer = 0; // 重置扫描分频计数器
|
||||
key_scan_flag = 1; // 仅在中断里置起标志位,留待主循环中执行实际读取与消抖
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 主循<EFBFBD><EFBFBD>按键<EFBFBD><EFBFBD>描与消抖处理函数
|
||||
* @details 由主<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>查并执<EFBFBD><EFBFBD>,完全在主线程<EFBFBD><EFBFBD>运<EFBFBD><EFBFBD>,绝无<EFBFBD><EFBFBD><EFBFBD><EFBFBD>重入冲突<EFBFBD><EFBFBD>
|
||||
* @brief 主循环按键扫描与消抖处理函数
|
||||
* @details 由主循环每 10ms 检查并执行,完全在主线程中运行,绝无中断重入冲突。
|
||||
*/
|
||||
void Event_KeyScan_Poll(void)
|
||||
{
|
||||
SystemEvent evt;
|
||||
// 读取按键的电平信<EFBFBD><EFBFBD> (KEY_UP, KEY_CONFIRM 为低电平有效)
|
||||
// 读取按键的电平信号 (KEY_UP, KEY_CONFIRM 为低电平有效)
|
||||
u8 raw_up = !KEY_UP;
|
||||
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通道判定 (常<EFBFBD> 2.0V, 按下 3.7V)
|
||||
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通道判定 (常态 2.0V, 按下 3.7V)
|
||||
u8 raw_confirm = !KEY_CONFIRM;
|
||||
u8 raw_sos = !KEY_SOS; // 恢<EFBFBD> SOS 物理按键电平<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
key_scan_timer = 0; // 重置<EFBFBD><EFBFBD>描分频<EFBFBD><EFBFBD>数<EFBFBD><EFBFBD>
|
||||
u8 raw_sos = !KEY_SOS; // 恢复 SOS 物理按键电平检测
|
||||
key_scan_timer = 0; // 重置扫描分频计数器
|
||||
|
||||
// 【SOS 按键电平实时诊断<EFBFBD><EFBFBD>
|
||||
// 【SOS 按键电平实时诊断】
|
||||
{
|
||||
static u8 last_raw_sos = 99;
|
||||
if (raw_sos != last_raw_sos) {
|
||||
@@ -210,7 +210,7 @@ void Event_KeyScan_Poll(void)
|
||||
}
|
||||
}
|
||||
|
||||
// 按键调试诊断:若按键 ADC 值有变化或<EFBFBD><EFBFBD>于高电平,串口输出真实 ADC <EFBFBD><EFBFBD>
|
||||
// 按键调试诊断:若按键 ADC 值有变化或处于高电平,串口输出真实 ADC 值
|
||||
{
|
||||
u16 down_val = ADC_ReadFiltered(ADC_CHANNEL_KEY_DOWN);
|
||||
if (down_val > 2800) {
|
||||
@@ -223,35 +223,35 @@ void Event_KeyScan_Poll(void)
|
||||
}
|
||||
}
|
||||
|
||||
// <EFBFBD><EFBFBD>测到有任意按<EFBFBD><EFBFBD>处于下压状<EFBFBD><EFBFBD>,立即将无操作闲置休眠计时器归<EFBFBD><EFBFBD>
|
||||
// 检测到有任意按键处于下压状态,立即将无操作闲置休眠计时器归零
|
||||
if (raw_up || raw_down || raw_confirm || raw_sos) {
|
||||
inactivity_timer = 0;
|
||||
} else {
|
||||
// 如果在常态下(非休眠、非报<EFBFBD><EFBFBD><EFBFBD><EFBFBD>非紧<EFBFBD><EFBFBD>求救),累加闲<EFBFBD><EFBFBD>时间
|
||||
// 如果在常态下(非休眠、非报警、非紧急求救),累加闲置时间
|
||||
if (current_state != STATE_SLEEP && current_state != STATE_ALARM && current_state != STATE_SOS_EMITTED) {
|
||||
inactivity_timer++;
|
||||
}
|
||||
}
|
||||
|
||||
// 默<EFBFBD><EFBFBD>将派发事件重置为空
|
||||
// 默认将派发事件重置为空
|
||||
evt.key_event = KEY_EVENT_NONE;
|
||||
evt.priority = EVENT_PRIORITY_NORMAL;
|
||||
evt.extra_data = 0;
|
||||
evt.extra_size = 0;
|
||||
|
||||
// 双键组合判定:▲ <EFBFBD><EFBFBD> and <EFBFBD><EFBFBD> <20><>同时按下的消抖与生成
|
||||
// 双键组合判定:▲ 键 and ▼ 键同时按下的消抖与生成
|
||||
if (raw_up && raw_down) {
|
||||
comb_hold++;
|
||||
if (comb_hold == 300) { // 持续按下<EFBFBD><EFBFBD> 3 <EFBFBD><EFBFBD> (300 * 10ms = 3s)
|
||||
if (comb_hold == 300) { // 持续按下达 3 秒 (300 * 10ms = 3s)
|
||||
evt.key_event = KEY_EVENT_UP_DOWN_COMB;
|
||||
EventQueue_Push(evt); // 压入队列
|
||||
}
|
||||
key_up_hold = 0; // 清零单个按键计数,防止双击事件干<EFBFBD><EFBFBD>
|
||||
key_up_hold = 0; // 清零单个按键计数,防止双击事件干扰
|
||||
key_down_hold = 0;
|
||||
} else {
|
||||
comb_hold = 0; // 组合<EFBFBD><EFBFBD>松开归零
|
||||
comb_hold = 0; // 组合键松开归零
|
||||
|
||||
// <EFBFBD><EFBFBD> (KEY_UP) 按键状<EFBFBD><EFBFBD>机
|
||||
// ▲ (KEY_UP) 按键状态机
|
||||
if (raw_up) {
|
||||
key_up_hold++;
|
||||
if (key_up_hold == 300) { // 达到 3 秒判定为长按
|
||||
@@ -259,7 +259,7 @@ void Event_KeyScan_Poll(void)
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
} else {
|
||||
// 如果松开时按下<EFBFBD><EFBFBD>数在消抖阈值(20ms)至长按阈<EFBFBD><EFBFBD>(3s)之间,则判定为<EFBFBD><EFBFBD>次短<EFBFBD><EFBFBD>
|
||||
// 如果松开时按下计数在消抖阈值(20ms)至长按阈值(3s)之间,则判定为一次短按
|
||||
if (key_up_hold >= 2 && key_up_hold < 300) {
|
||||
evt.key_event = KEY_EVENT_UP_CLICK;
|
||||
EventQueue_Push(evt);
|
||||
@@ -267,15 +267,15 @@ void Event_KeyScan_Poll(void)
|
||||
key_up_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// <EFBFBD><EFBFBD> (KEY_DOWN / <EFBFBD><EFBFBD>关机) 按键状<EFBFBD><EFBFBD>机
|
||||
// ▼ (KEY_DOWN / 开关机) 按键状态机
|
||||
if (raw_down) {
|
||||
key_down_hold++;
|
||||
if (key_down_hold == 100) { // 长按 1 <EFBFBD><EFBFBD> (100 * 10ms = 1000ms = 1s) 触发关机事件
|
||||
if (key_down_hold == 100) { // 长按 1 秒 (100 * 10ms = 1000ms = 1s) 触发关机事件
|
||||
evt.key_event = KEY_EVENT_POWER_OFF;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
} else {
|
||||
// 如果松开时按下时长在 20ms <EFBFBD><EFBFBD> 1s 之间,触发短按下<EFBFBD><EFBFBD>/选择事件
|
||||
// 如果松开时按下时长在 20ms 至 1s 之间,触发短按下翻/选择事件
|
||||
if (key_down_hold >= 2 && key_down_hold < 100) {
|
||||
evt.key_event = KEY_EVENT_DOWN_CLICK;
|
||||
EventQueue_Push(evt);
|
||||
@@ -283,10 +283,10 @@ void Event_KeyScan_Poll(void)
|
||||
key_down_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// <EFBFBD><EFBFBD> (KEY_CONFIRM) <EFBFBD><EFBFBD>认按<EFBFBD><EFBFBD>状<EFBFBD><EFBFBD>机
|
||||
// ■ (KEY_CONFIRM) 确认按键状态机
|
||||
if (raw_confirm) {
|
||||
key_confirm_hold++;
|
||||
if (key_confirm_hold == 300) { // 长按 3 秒打<EFBFBD><EFBFBD>主菜<EFBFBD><EFBFBD>
|
||||
if (key_confirm_hold == 300) { // 长按 3 秒打开主菜单
|
||||
evt.key_event = KEY_EVENT_CONFIRM_LONG;
|
||||
EventQueue_Push(evt);
|
||||
}
|
||||
@@ -298,23 +298,23 @@ void Event_KeyScan_Poll(void)
|
||||
key_confirm_hold = 0; // 释放归零
|
||||
}
|
||||
|
||||
// SOS <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȱ<EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD> (<28>ѽ<EFBFBD><D1BD><EFBFBD>)
|
||||
// SOS 物理求救按键状态机 (已解锁)
|
||||
if (raw_sos) {
|
||||
key_sos_hold++;
|
||||
if (key_sos_hold == 300) { // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 <20>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (key_sos_hold == 300) { // 长按 3 秒,发出求救,插入队首
|
||||
evt.key_event = KEY_EVENT_SOS_LONG;
|
||||
evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(evt);
|
||||
Uart_SendString("[KEY-DIAG] SOS Long Press Dispatched!\r\n");
|
||||
}
|
||||
} else {
|
||||
if (key_sos_hold >= 2 && key_sos_hold < 300) { // <EFBFBD>̰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (key_sos_hold >= 2 && key_sos_hold < 300) { // 短按即呼救,插入队首
|
||||
evt.key_event = KEY_EVENT_SOS_CLICK;
|
||||
evt.priority = EVENT_PRIORITY_URGENT;
|
||||
EventQueue_InsertFront(evt);
|
||||
Uart_SendString("[KEY-DIAG] SOS Click Dispatched!\r\n");
|
||||
}
|
||||
key_sos_hold = 0; // <EFBFBD>ͷŹ<EFBFBD><EFBFBD><EFBFBD>
|
||||
key_sos_hold = 0; // 释放归零
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
218
App/main.c
218
App/main.c
@@ -11,82 +11,82 @@
|
||||
/* =========================================================================
|
||||
* 系统全局变量定义
|
||||
* ========================================================================= */
|
||||
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默<EFBFBD><EFBFBD>为正常时钟待机<EFBFBD><EFBFBD>
|
||||
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默认为正常时钟待机页
|
||||
|
||||
|
||||
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 数组<EFBFBD><EFBFBD>的索引槽位号
|
||||
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 数组中的索引槽位号
|
||||
|
||||
// 传感器存储列表数<EFBFBD><EFBFBD>库,位于单片机<EFBFBD><EFBFBD>部 XDATA 存储空间,<EFBFBD><EFBFBD>共 16 <EFBFBD><EFBFBD>槽位
|
||||
// 传感器存储列表数据库,位于单片机外部 XDATA 存储空间,总共 16 个槽位
|
||||
Sensor_Slot xdata sensor_list[16];
|
||||
|
||||
// 全局滴答与定时中<EFBFBD><EFBFBD>计数变量,位<EFBFBD><EFBFBD> volatile 防<EFBFBD><EFBFBD><EFBFBD>编译器优<EFBFBD><EFBFBD>
|
||||
volatile u16 ms_tick = 0; // 定时<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 基准滴答<EFBFBD><EFBFBD>加器
|
||||
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> 组合<EFBFBD><EFBFBD>按下时长<EFBFBD><EFBFBD><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>
|
||||
* 串口调试指令解析与事件派发封装
|
||||
* ========================================================================= */
|
||||
/**
|
||||
* @brief 解析通过串口 1 发<EFBFBD><EFBFBD>来的键盘及测试模拟指令
|
||||
* @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 物理<EFBFBD><EFBFBD>(优先插入队首)<EFBFBD><EFBFBD>
|
||||
* - 'c'/'C': 模拟组合<EFBFBD><EFBFBD>触发<EFBFBD><EFBFBD>
|
||||
* - 'a'/'A': 模拟无线传感器入侵触发<EFBFBD><EFBFBD>报信号,地<EFBFBD><EFBFBD>固定<EFBFBD><EFBFBD> 0x123456,zone=1<EFBFBD><EFBFBD>
|
||||
* - 'p'/'P': 模拟对码期间捕获<EFBFBD><EFBFBD> 24 位无线<EFBFBD><EFBFBD>码信号,地<EFBFBD><EFBFBD>固定<EFBFBD><EFBFBD> 0x789ABC<EFBFBD><EFBFBD>
|
||||
* - '1'/'2'/'3': 模拟系统的<EFBFBD><EFBFBD>常、已布防、已撤防状<EFBFBD><EFBFBD>切<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000,触发自动深度休眠<EFBFBD>
|
||||
* - 't'/'T': 触发屏幕与无线控制引脚测试<EFBFBD>
|
||||
* @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 <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,7 +94,7 @@ 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;
|
||||
|
||||
@@ -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;
|
||||
@@ -136,22 +136,22 @@ void Debug_ProcessCommand(char cmd)
|
||||
} else if (cmd == 'a' || cmd == 'A') {
|
||||
u32 mock_addr = 0x123456; // 设定模拟的报警射频源地址
|
||||
u8 mock_slot;
|
||||
// 如果<EFBFBD><EFBFBD>地数<EFBFBD><EFBFBD>库中没有匹配该射频,则强制登记进 1 号防<EFBFBD><EFBFBD>
|
||||
// 如果本地数据库中没有匹配该射频,则强制登记进 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); // 高优先级插队
|
||||
Uart_SendString("[UART] Mock RF Alarm\r\n");
|
||||
} else if (cmd == 'p' || cmd == 'P') {
|
||||
// <EFBFBD><EFBFBD>有当手环切入 Pair 模式时,模拟对码信号才有<EFBFBD><EFBFBD>
|
||||
// 只有当手环切入 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,157 @@ void Debug_ProcessCommand(char cmd)
|
||||
Uart_SendString("[UART] Not in PAIR mode\r\n");
|
||||
}
|
||||
} else if (cmd == '1') {
|
||||
// 模拟切换<EFBFBD><EFBFBD> 正常撤防 (NORMAL) 状<EFBFBD><EFBFBD>并刷新时钟
|
||||
// 模拟切换至 正常撤防 (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> 已布<EFBFBD><EFBFBD> (ARMED) 状<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD>通门磁可触发警报
|
||||
// 模拟切换至 已布防 (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> 已撤<EFBFBD><EFBFBD> (DISARMED) 状<EFBFBD><EFBFBD>,忽略<EFBFBD><EFBFBD>通报<EFBFBD><EFBFBD>
|
||||
// 模拟切换至 已撤防 (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 秒超时,强制触发主循<EFBFBD><EFBFBD>深度休眠
|
||||
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 秒射频接收监<EFBFBD><EFBFBD>诊断
|
||||
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监听诊断
|
||||
} else if (cmd == 'l' || cmd == 'L') {
|
||||
Loopback_Test(); // 触发物理电气回环测试 (<EFBFBD><EFBFBD><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 (<EFBFBD><EFBFBD>高<EFBFBD><EFBFBD>运<EFBFBD><EFBFBD>)
|
||||
EAXFR = 1; // 允<EFBFBD><EFBFBD><EFBFBD><EFBFBD>问扩展特殊功能寄存<EFBFBD><EFBFBD> (XSFR)
|
||||
CKCON = 0; // 外部总线时钟设定为最<EFBFBD><EFBFBD>
|
||||
// ====== 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 码关<EFBFBD><EFBFBD><EFBFBD><EFBFBD>条,熄灭上电暂<EFBFBD><EFBFBD>引起的随机白光<EFBFBD><EFBFBD>
|
||||
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 波特<EFBFBD><EFBFBD> 115200 供调试日<EFBFBD><EFBFBD>
|
||||
// ====== 硬件各模块基础初始化 ======
|
||||
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(); // 执<><E689A7>上电硬件自<E4BBB6><E887AA> (PWR_HOLD锁存、P0.3 ADC按键常<E994AE><E5B8B8><EFBFBD><EFBFBD>P1.3 电池电量)
|
||||
Load_Database(); // <20><> IAP Flash <20><> 254 扇区读取<E8AFBB><E58F96>有已绑定的传感器数据<E695B0><E68DAE> RAM
|
||||
|
||||
/* 步<> 1: 初<><E5889D>化事件<E4BA8B><E4BBB6>形缓冲区队列 */
|
||||
Self_Test(); // 执行上电硬件自检 (PWR_HOLD锁存、P0.3 ADC按键常态、P1.3 电池电量)
|
||||
Load_Database(); // 从 IAP Flash 第 254 扇区读取所有已绑定的传感器数据至 RAM
|
||||
|
||||
/* 步骤 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>按键定时标志 (<EFBFBD><EFBFBD> 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>位,主循<EFBFBD><EFBFBD>响应清除并<EFBFBD><EFBFBD>理) */
|
||||
/* 0. 检查主循环按键定时标志 (由 1ms 中断置位,主循环响应清除并处理) */
|
||||
if (key_scan_flag) {
|
||||
key_scan_flag = 0;
|
||||
Event_KeyScan_Poll();
|
||||
}
|
||||
|
||||
/* 1. 串口非阻塞指令捕<EFBFBD><EFBFBD> -> 装配为事件方式入<EFBFBD><EFBFBD> */
|
||||
/* 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 运<EFBFBD><EFBFBD>时间超时挂起保护) */
|
||||
/* 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(); // 该函数是阻<EFBFBD><EFBFBD>的,MCU 将在此挂起<EFBFBD><EFBFBD>唤醒后将自动从其后继续执<EFBFBD>
|
||||
current_state = STATE_NORMAL; // 唤醒后重新置为<EFBFBD><EFBFBD>常待机状<EFBFBD>
|
||||
AppManager_StartApp(APP_ID_CLOCK); // 重新<EFBFBD><EFBFBD><EFBFBD><EFBFBD>时钟应用以刷新画面和背光
|
||||
current_state = STATE_SLEEP; // 系统置为休眠状态
|
||||
Enter_Low_Power_Sleep(); // 该函数是阻塞的,MCU 将在此挂起。唤醒后将自动从其后继续执行
|
||||
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 端口按键唤醒标志
|
||||
volatile u8 p2_wakeup_flag = 0; // P2 端口按键唤醒标志
|
||||
volatile u8 p3_wakeup_flag = 0; // P3 端口射频中断唤醒标志
|
||||
volatile u8 rf_wakeup_flag = 0; // 射频中断唤醒标志
|
||||
|
||||
/* =========================================================================
|
||||
* STC32G <EFBFBD><EFBFBD>口掉电<EFBFBD><EFBFBD>部<EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒<EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (ISR)
|
||||
* STC32G 端口掉电外部中断唤醒中断服务程序 (ISR)
|
||||
* ========================================================================= */
|
||||
|
||||
/**
|
||||
* @brief Port0 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> 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 端口掉电中断服务函数 (由 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 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存器<EFBFBD> (0x01作安全掩<EFBFBD><EFBFBD>)
|
||||
P0INTF = 0x00; // 清除 P0 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
|
||||
P0INTE = 0x00; // 【关<EFBFBD><EFBFBD>保护】:立即关闭 P0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>允<EFBFBD><EFBFBD>,防<EFBFBD><EFBFBD>按<EFBFBD><EFBFBD>处于低电平期间反复触<EFBFBD><EFBFBD> ISR 导致堆栈溢出
|
||||
EAXFR = 1; // 使能访问扩展寄存区
|
||||
p0_wakeup_flag = P0INTF | 0x01;// 读取并备份 P0 中断标志寄存器值 (0x01作安全掩码)
|
||||
P0INTF = 0x00; // 清除 P0 端口中断悬挂标志位
|
||||
P0INTE = 0x00; // 【关键保护】:立即关闭 P0 中断允许,防止按键处于低电平期间反复触发 ISR 导致堆栈溢出
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port2 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
|
||||
* @details 负责处理 P2.6 (SOS按键) <EFBFBD><EFBFBD> P2.1 (射<EFBFBD><EFBFBD>数<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<EFBFBD>
|
||||
* @brief Port2 端口掉电中断服务函数 (由 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 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存区的<EFBFBD><EFBFBD>
|
||||
P2INTF = 0x00; // 清除 P2 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
|
||||
P2INTE = 0x00; // 立即关闭 P2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>通道,防<EFBFBD><EFBFBD>低电平期间反复重<EFBFBD><EFBFBD>
|
||||
EAXFR = 1; // 使能扩展寄存区
|
||||
p2_wakeup_flag = P2INTF | 0x01;// 读取并备份 P2 中断标志寄存区的值
|
||||
P2INTF = 0x00; // 清除 P2 端口中断悬挂标志位
|
||||
P2INTE = 0x00; // 立即关闭 P2 中断通道,防止低电平期间反复重入
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port3 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
|
||||
* @details 负责处理 P3.6 (新射频数<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<EFBFBD>
|
||||
* @brief Port3 端口掉电中断服务函数 (由 isr_jump.asm 引导定位至此)
|
||||
* @details 负责处理 P3.6 (新射频数据脚) 在休眠模式下的物理跳变唤醒。
|
||||
*/
|
||||
void Port3_Isr(void) interrupt 16
|
||||
{
|
||||
EAXFR = 1; // 使能访问扩展寄存<EFBFBD><EFBFBD>
|
||||
p3_wakeup_flag = P3INTF | 0x01;// 读取并<EFBFBD><EFBFBD>份 P3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>标志寄存器<EFBFBD> (0x01作安全掩<EFBFBD><EFBFBD>)
|
||||
P3INTF = 0x00; // 清除 P3 <EFBFBD><EFBFBD>口中<EFBFBD><EFBFBD><EFBFBD><EFBFBD>挂标志位
|
||||
P3INTE = 0x00; // 立即关闭 P3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>通道,防止反复重<EFBFBD><EFBFBD>
|
||||
EAXFR = 1; // 使能访问扩展寄存器
|
||||
p3_wakeup_flag = P3INTF | 0x01;// 读取并备份 P3 中断标志寄存器值 (0x01作安全掩码)
|
||||
P3INTF = 0x00; // 清除 P3 端口中断悬挂标志位
|
||||
P3INTE = 0x00; // 立即关闭 P3 中断通道,防止反复重入
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user