Compare commits

..

7 Commits

5 changed files with 406 additions and 270 deletions

View File

@@ -6,17 +6,17 @@
#include "xtell.h"
#include "../Drivers/adc.h"
// 定义事件形队列的大深度为 8
// 定义事件<EFBFBD><EFBFBD>形队列的<EFBFBD><EFBFBD>大深度为 8
#define EVENT_QUEUE_DEPTH 8
// 形队列存储数 (存放在单片机 xdata 拓展 RAM区中)
// <EFBFBD><EFBFBD>形队列存储数<EFBFBD><EFBFBD> (存放在单片机 xdata 拓展 RAM区中)
static SystemEvent xdata event_queue[EVENT_QUEUE_DEPTH];
static u8 queue_head = 0; // 队首读指针
static u8 queue_tail = 0; // 队尾写指
static u8 queue_count = 0; // 当前队列内有效事件
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>
/**
* @brief 初化/清空事件队列
* @brief 初<EFBFBD><EFBFBD>化/清空事件队列
*/
void EventQueue_Init(void)
{
@@ -26,62 +26,63 @@ void EventQueue_Init(void)
}
/**
* @brief 将普通事件压入队
* @param evt 输入的系统事
* @return bit 1-成功0-失败
* @brief 将普通事件压入队<EFBFBD><EFBFBD>
* @param evt 输入的系统事<EFBFBD><EFBFBD>
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
*/
bit EventQueue_Push(SystemEvent evt)
{
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,丢弃事件
EA = 0; // 关闭全局中断,保护临界区操作的原子
EA = 0; // 关闭全局<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,保护临界区操作的原子<EFBFBD>
event_queue[queue_tail] = evt; // 存入队尾
queue_tail = (queue_tail + 1) % EVENT_QUEUE_DEPTH; // 尾指针向后移动,回环
queue_count++; // 有效计数 1
EA = 1; // 恢复全局中断
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>
return 1;
}
/**
* @brief 将高优先级/紧急事件强行插到队
* @param evt 输入的系统事
* @return bit 1-成功0-失败
* @brief 将高优先<EFBFBD><EFBFBD>/紧<><E7B4A7>事件强行插到队<EFBFBD><EFBFBD>
* @param evt 输入的系统事<EFBFBD><EFBFBD>
* @return bit 1-成功<EFBFBD><EFBFBD>0-失败
*/
bit EventQueue_InsertFront(SystemEvent evt)
{
if (queue_count >= EVENT_QUEUE_DEPTH) return 0; // 队列满,插队失败
EA = 0; // 屏蔽中断
// 头指针向前移动一位(带回防溢出)
EA = 0; // 屏蔽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 头指针向前移动一位(带回<EFBFBD><EFBFBD>防溢出)
queue_head = (queue_head - 1 + EVENT_QUEUE_DEPTH) % EVENT_QUEUE_DEPTH;
event_queue[queue_head] = evt; // 存入腾出的队首位
queue_count++; // 计数 1
EA = 1; // 恢复中断
event_queue[queue_head] = evt; // 存入腾出的队首位<EFBFBD><EFBFBD>
queue_count++; // 计数<EFBFBD><EFBFBD> 1
EA = 1; // 恢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return 1;
}
/**
* @brief 从队首弹出一缓冲事件
* @return SystemEvent 返回弹出的事件若空返回空闲事
* @brief 从队首弹出一<EFBFBD><EFBFBD>缓冲事件
* @return SystemEvent 返回弹出的事件<EFBFBD><EFBFBD>若空返回空闲事<EFBFBD><EFBFBD>
*/
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; // 队空,直接返回空闲事
if (queue_count == 0) return evt; // 队空,直接返回空闲事<EFBFBD><EFBFBD>
EA = 0; // 屏蔽中断
evt = event_queue[queue_head]; // 读取队首数据
queue_head = (queue_head + 1) % EVENT_QUEUE_DEPTH; // 头指针向后移动,回环
queue_count--; // 有效计数 1
EA = 1; // 恢复中断
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>
return evt;
}
/**
* @brief 判断队列是否为空
* @brief 判断队列<EFBFBD><EFBFBD>否为<EFBFBD><EFBFBD>
*/
bit EventQueue_IsEmpty(void)
{
@@ -89,7 +90,7 @@ bit EventQueue_IsEmpty(void)
}
/**
* @brief 判断队列是否已满
* @brief 判断队列<EFBFBD><EFBFBD>否已<EFBFBD><EFBFBD>
*/
bit EventQueue_IsFull(void)
{
@@ -97,7 +98,7 @@ bit EventQueue_IsFull(void)
}
/**
* @brief 获取当前队列的事件
* @brief 获取当前队列<EFBFBD><EFBFBD>的事件<EFBFBD><EFBFBD>
*/
u8 EventQueue_GetCount(void)
{
@@ -105,98 +106,111 @@ u8 EventQueue_GetCount(void)
}
/**
* @brief 事件分发器核心轮询
* @details 逐一处理队列的事件,并根系统当前的运行模式进行拦截、跳转或下发派发
* @brief 事件分发器核心轮询<EFBFBD><EFBFBD>
* @details 逐一处理队列<EFBFBD><EFBFBD>的事件,并根<EFBFBD><EFBFBD>系统当前的运行模式进行拦<EFBFBD><EFBFBD>、跳<EFBFBD><EFBFBD>或下发派发<EFBFBD>
*/
void Event_Dispatcher_Loop(void)
{
SystemEvent evt = EventQueue_Pop(); // 弹出一个事件
SystemEvent evt = EventQueue_Pop(); // 弹出<EFBFBD><EFBFBD><EFBFBD><EFBFBD>事件
// 如果无事发生的空事件,直接退出
// 如果<EFBFBD><EFBFBD>无事发生的空事件,直接<EFBFBD><EFBFBD><EFBFBD>
if (evt.key_event == KEY_EVENT_NONE && evt.extra_size == 0) {
return;
}
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时器,重置闲置超时
inactivity_timer = 0; // 捕获到有效事件,清零休眠计时<EFBFBD><EFBFBD><EFBFBD><EFBFBD>闲置超时
// 串口打印调试信息
XTELL_LOG("[EVENT] key=");
XTELL_LOG_HEX8((u8)evt.key_event);
XTELL_LOG("\r\n");
// SOS 按键紧急处理:若当前前台不为 SOS 应用,接收到 SOS 动作,立即强行切入到 SOS_APP 并执行求
// SOS 按键紧<EFBFBD><EFBFBD><EFBFBD><EFBFBD>理:若当前前台不为 SOS 应用,接收到 SOS <EFBFBD><EFBFBD>动作,立即强行切入到 SOS_APP 并执行求<EFBFBD><EFBFBD>
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;
}
// 关机事件处理:捕获到长按关机指令,直接调 Power_Off 关断电源
// 关机事件处理:捕获到长按关机指令,直接调<EFBFBD><EFBFBD> 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 定时 1 初始化,设定 1ms 中断周期
* @brief 定时<EFBFBD><EFBFBD> 1 初<EFBFBD><EFBFBD><EFBFBD><EFBFBD>定 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD>周期
*/
void Timer1_Init(void)
{
AUXR |= 0x40; // 设定定时 1 1T 模式 (无分频,主直接输)
TMOD &= 0x0F; // 设置定时 1 模式寄存,保留低四位 (定时0配置)
AUXR |= 0x40; // 设定定时<EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD> 1T 模式 (无分频,主<EFBFBD><EFBFBD>直接输<EFBFBD><EFBFBD>)
TMOD &= 0x0F; // 设置定时<EFBFBD><EFBFBD> 1 模式寄存<EFBFBD><EFBFBD>,保留低四位 (定时<EFBFBD><EFBFBD>0配置)
{
// 按照系统主 (MAIN_Fosc) 计算 1ms 对应的重装载
// 按照系统主<EFBFBD> (MAIN_Fosc) 计算 1ms 对应的重装载<EFBFBD><EFBFBD>
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
TL1 = (u8)reload; // 载入 8
TH1 = (u8)(reload >> 8);// 载入 8
TL1 = (u8)reload; // 载入<EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD>
TH1 = (u8)(reload >> 8);// 载入<EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD>
}
ET1 = 1; // 开启定时器 1 中断允许
TR1 = 1; // 动定时器 1 计数
EA = 1; // 开启全局中断允许
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>
}
// 全局按键描触发标
// 全局按键<EFBFBD><EFBFBD>描触发标<EFBFBD><EFBFBD>
volatile bit key_scan_flag = 0;
/**
* @brief 定时 1 中断服务程序 ( 1ms 触发一次)
* @details 承担系统时钟计算,并 10ms 置位主循环按键扫描标志,不直接在中断中进行 ADC 多采样
* @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>
*/
void Timer1_Isr(void) interrupt 3
{
// 1ms 定时更新时钟
// 1ms 定时更新<EFBFBD><EFBFBD>时钟
Clock_IncMS();
// 报屏幕红边以 100ms 周期亮灭,进行色爆闪指示
// 报<EFBFBD><EFBFBD>屏幕红边<EFBFBD><EFBFBD>以 100ms 周期<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,进行<EFBFBD><EFBFBD>色爆闪指示
alarm_flash_flag = (ms_tick / 100) % 2;
/* 物理按键定时计数 ( 10ms 位一次标志位) */
/* 物理按键定时计数 (<EFBFBD><EFBFBD> 10ms <EFBFBD><EFBFBD>位一次标志位) */
key_scan_timer++;
if (key_scan_timer >= 10) {
key_scan_timer = 0; // 重置描分频计数器
key_scan_flag = 1; // 仅在中断里置起标志位,留待主循环中执行实际读取与消
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>
}
}
/**
* @brief 主循环按键扫描与消抖处理函数
* @details 由主循环每 10ms 查并执,完全在主线程中运行,绝无中断重入冲突
* @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>
*/
void Event_KeyScan_Poll(void)
{
SystemEvent evt;
// 读取按键的电平信 (KEY_UP, KEY_CONFIRM 为低电平有效)
// 读取按键的电平信<EFBFBD><EFBFBD> (KEY_UP, KEY_CONFIRM 为低电平有效)
u8 raw_up = !KEY_UP;
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通道判定 (常 2.0V, 按下 3.7V)
u8 raw_down = ADC_IsKeyDown(); // KEY_DOWN 通过 P0.3 ADC 通道判定 (常<EFBFBD> 2.0V, 按下 3.7V)
u8 raw_confirm = !KEY_CONFIRM;
u8 raw_sos = 0; // 临时注释关闭 SOS 物理按键电平检测,防浮空干扰
key_scan_timer = 0; // 重置描分频计数器
u8 raw_sos = !KEY_SOS; // <EFBFBD> SOS 物理按键电平<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
key_scan_timer = 0; // 重置<EFBFBD><EFBFBD>描分频<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 按键调试诊断:若按键 ADC 值有变化或处于高电平,串口输出真实 ADC 值
// 【SOS 按键电平实时诊断<E8AF8A><E696AD>
{
static u8 last_raw_sos = 99;
if (raw_sos != last_raw_sos) {
last_raw_sos = raw_sos;
Uart_SendString("[KEY-DIAG] KEY_SOS (P2.6) logic raw: ");
Uart_SendByte(raw_sos ? '1' : '0');
Uart_SendString(", Physical GPIO Pin: ");
Uart_SendByte(KEY_SOS ? '1' : '0');
Uart_SendString("\r\n");
}
}
// 按键调试诊断:若按键 ADC 值有变化或<E58C96><E68896>于高电平串口输出真实 ADC <20><>
{
u16 down_val = ADC_ReadFiltered(ADC_CHANNEL_KEY_DOWN);
if (down_val > 2800) {
@@ -209,34 +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;
// 双键组合判定:▲ and ▼ 键同时按下的消抖与生成
// 双键组合判定:▲ <EFBFBD><EFBFBD> and <EFBFBD><EFBFBD> <20><>同时按下的消抖与生成
if (raw_up && raw_down) {
comb_hold++;
if (comb_hold == 300) { // 持续按下 3 (300 * 10ms = 3s)
if (comb_hold == 300) { // 持续按下<EFBFBD><EFBFBD> 3 <EFBFBD><EFBFBD> (300 * 10ms = 3s)
evt.key_event = KEY_EVENT_UP_DOWN_COMB;
EventQueue_Push(evt); // 压入队列
}
key_up_hold = 0; // 清零单个按键计数,防止双击事件干
key_up_hold = 0; // 清零单个按键计数,防止双击事件干<EFBFBD><EFBFBD>
key_down_hold = 0;
} else {
comb_hold = 0; // 组合松开归零
comb_hold = 0; // 组合<EFBFBD><EFBFBD>松开归零
// (KEY_UP) 按键状
// <EFBFBD><EFBFBD> (KEY_UP) 按键状<EFBFBD><EFBFBD>
if (raw_up) {
key_up_hold++;
if (key_up_hold == 300) { // 达到 3 秒判定为长按
@@ -244,7 +259,7 @@ void Event_KeyScan_Poll(void)
EventQueue_Push(evt);
}
} else {
// 如果松开时按下数在消抖阈值20ms至长按阈3s之间则判定为一次短按
// 如果松开时按下<EFBFBD><EFBFBD>数在消抖阈值20ms至长按阈<EFBFBD><EFBFBD>3s之间则判定为<EFBFBD><EFBFBD>次短<EFBFBD><EFBFBD>
if (key_up_hold >= 2 && key_up_hold < 300) {
evt.key_event = KEY_EVENT_UP_CLICK;
EventQueue_Push(evt);
@@ -252,15 +267,15 @@ void Event_KeyScan_Poll(void)
key_up_hold = 0; // 释放归零
}
// (KEY_DOWN / 关机) 按键状
// <EFBFBD><EFBFBD> (KEY_DOWN / <EFBFBD><EFBFBD>关机) 按键状<EFBFBD><EFBFBD>
if (raw_down) {
key_down_hold++;
if (key_down_hold == 100) { // 长按 1 (100 * 10ms = 1000ms = 1s) 触发关机事件
if (key_down_hold == 100) { // 长按 1 <EFBFBD><EFBFBD> (100 * 10ms = 1000ms = 1s) 触发关机事件
evt.key_event = KEY_EVENT_POWER_OFF;
EventQueue_Push(evt);
}
} else {
// 如果松开时按下时长在 20ms 1s 之间,触发短按下/选择事件
// 如果松开时按下时长在 20ms <EFBFBD><EFBFBD> 1s 之间,触发短按下<EFBFBD><EFBFBD>/选择事件
if (key_down_hold >= 2 && key_down_hold < 100) {
evt.key_event = KEY_EVENT_DOWN_CLICK;
EventQueue_Push(evt);
@@ -268,10 +283,10 @@ void Event_KeyScan_Poll(void)
key_down_hold = 0; // 释放归零
}
// (KEY_CONFIRM) 确认按键状态
// <EFBFBD><EFBFBD> (KEY_CONFIRM) <EFBFBD><EFBFBD>认按<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (raw_confirm) {
key_confirm_hold++;
if (key_confirm_hold == 300) { // 长按 3 秒打开主菜单
if (key_confirm_hold == 300) { // 长按 3 秒打<EFBFBD><EFBFBD>主菜<EFBFBD><EFBFBD>
evt.key_event = KEY_EVENT_CONFIRM_LONG;
EventQueue_Push(evt);
}
@@ -283,21 +298,23 @@ void Event_KeyScan_Poll(void)
key_confirm_hold = 0; // 释放归零
}
/*
// SOS 物理求救按键状态机
// SOS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȱ<EFBFBD><C8B0><EFBFBD>״̬<D7B4><CCAC> (<28>ѽ<EFBFBD><D1BD><EFBFBD>)
if (raw_sos) {
key_sos_hold++;
if (key_sos_hold == 300) { // 长按 3 秒,发出求救,插入队首
if (key_sos_hold == 300) { // <20><><EFBFBD><EFBFBD> 3 <20><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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) { // 短按即呼救,插入队首
if (key_sos_hold >= 2 && key_sos_hold < 300) { // <20>̰<EFBFBD><CCB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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; // 释放归零
key_sos_hold = 0; // <20>ͷŹ<CDB7><C5B9><EFBFBD>
}
*/
}
}

View File

@@ -11,54 +11,90 @@
/* =========================================================================
* 系统全局变量定义
* ========================================================================= */
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默为正常时钟待机
SystemState current_state = STATE_NORMAL; // 系统整体的当前运行状态,默<EFBFBD><EFBFBD>为正常时钟待机<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 数组的索引槽位号
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>的索引槽位号
// 传感器存储列表数库,位于单片机部 XDATA 存储空间,共 16 槽位
// 传感器存储列表数<EFBFBD><EFBFBD>库,位于单片机<EFBFBD><EFBFBD>部 XDATA 存储空间,<EFBFBD><EFBFBD>共 16 <EFBFBD><EFBFBD>槽位
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; // 报警时红框周期性闪烁亮灭标志位
// 全局滴答与定时中<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>
// 物理按键描与消抖长按计数 (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>描与消抖长按计数<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>
/* =========================================================================
* 串口调试指令解析与事件派发封
* 串口调试指令解析与事件派发封<EFBFBD><EFBFBD>
* ========================================================================= */
/**
* @brief 解析通过串口 1 发来的键盘及测试模拟指令
* @param cmd 接收到的 ASCII 字符命令
* @details 负责将字符指令转化应的系统按或射频事件,并推入事件队列以测试件架构:
* - 'u'/'U': 模拟短按/长按 ▲ 键。
* - 'd'/'D': 模拟短按/长按 ▼ 键。
* - 's'/'S': 模拟短按/长按 SOS 物理(优先插入队首)
* - 'c'/'C': 模拟组合键触发。
* - 'a'/'A': 模拟无线传感器入侵触发报信号,地址固定为 0x123456zone=1
* - 'p'/'P': 模拟对码期间捕获 24 位无线码信号,地址固定为 0x789ABC
* - '1'/'2'/'3': 模拟系统的常、已布防、已撤防状态切换。
* - 'z'/'Z': 模拟超时,强行使闲置计数器置 6000触发自动深度休眠
* - 't'/'T': 触发屏幕与无线控制引脚测试
* @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> 0x123456zone=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 <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ר<EFBFBD><D7A8><EFBFBD><EFBFBD>RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<C9AB><CDA8><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>
* @details <20><><EFBFBD>η<EFBFBD><CEB7>ʹ<EFBFBD><CDB4><EFBFBD><ECA1A2><EFBFBD>̡<EFBFBD><CCA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><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>ϵ
*/
void RGB_Diagnostic_Test(void)
{
Uart_SendString("\r\n=== RGB LED Color Channel Test Starting ===\r\n");
// 1. <20><><EFBFBD>Է<EFBFBD><D4B7>ͺ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (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);
// Ϩ<><CFA8>
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 2. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (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);
// Ϩ<><CFA8>
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(300);
// 3. <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (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);
// <20><><EFBFBD><EFBFBD>Ϩ<EFBFBD><CFA8>
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; // 收到指令,立即重<EFBFBD><EFBFBD>用户的无操作闲置计时<EFBFBD><EFBFBD>
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); // 紧<EFBFBD><EFBFBD>事件插入队<EFBFBD><EFBFBD>
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 号防
// 如果<EFBFBD><EFBFBD>地数<EFBFBD><EFBFBD>库中没有匹配该射频,则强制登记进 1 号防<EFBFBD><EFBFBD>
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; // 入侵报<EFBFBD><EFBFBD><EFBFBD><EFBFBD>为 HIGH 优先<EFBFBD><EFBFBD>
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 模式时,模拟对码信号才有
// <EFBFBD><EFBFBD>有当手环切入 Pair 模式时,模拟对码信号才有<EFBFBD><EFBFBD>
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; // 设定模拟对码<EFBFBD><EFBFBD>件地<EFBFBD><EFBFBD>
debug_evt.extra_size = 4;
EventQueue_Push(debug_evt);
Uart_SendString("[UART] Mock RF Pair Signal\r\n");
@@ -123,153 +159,157 @@ void Debug_ProcessCommand(char cmd)
Uart_SendString("[UART] Not in PAIR mode\r\n");
}
} else if (cmd == '1') {
// 模拟切换 正常撤防 (NORMAL) 状并刷新时钟
// 模拟切换<EFBFBD><EFBFBD> 正常撤防 (NORMAL) 状<EFBFBD><EFBFBD>并刷新时钟
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) 状态,普通门磁可触发警报
// 模拟切换<EFBFBD><EFBFBD> 已布<EFBFBD><EFBFBD> (ARMED) 状<EFBFBD><EFBFBD><EFBFBD><EFBFBD>通门磁可触发警报
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) 状,忽略普通报警
// 模拟切换<EFBFBD><EFBFBD> 已撤<EFBFBD><EFBFBD> (DISARMED) 状<EFBFBD><EFBFBD>,忽略<EFBFBD><EFBFBD>通报<EFBFBD><EFBFBD>
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 秒超时,强制触发主循<EFBFBD><EFBFBD>深度休眠
Uart_SendString("[UART] Force Entering Sleep mode!\r\n");
} else if (cmd == 'q' || cmd == 'Q') {
RGB_Diagnostic_Test(); // <20><><EFBFBD><EFBFBD> RGB <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫͨ<C9AB><CDA8><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>
} else if (cmd == 't' || cmd == 'T') {
RF_DiagnosticMode('t'); // 触发射频连续发射诊断 (绿色爆闪)
RF_DiagnosticMode('t'); // 触发射<EFBFBD><EFBFBD><EFBFBD><EFBFBD>发射诊断 (绿色爆闪)
} else if (cmd == 'r' || cmd == 'R') {
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监诊断
RF_DiagnosticMode('r'); // 触发 5 秒射频接收监<EFBFBD><EFBFBD>诊断
} else if (cmd == 'l' || cmd == 'L') {
Loopback_Test(); // 触发物理电气回环测试 (<28><><EFBFBD><EFBFBD> P2.1 <20><> P3.6 <20><><EFBFBD><EFBFBD>)
}
}
/* =========================================================================
* 主函 (入口)
* 主函<EFBFBD><EFBFBD> (入口)
* ========================================================================= */
void main(void)
{
char cmd;
// ====== STC32G 特殊功能寄存器内核基础初始化 ======
WTST = 0; // 设置程序 Flash 访问等待时间 0 (最高速运行)
EAXFR = 1; // 允许访问扩展特殊功能寄存 (XSFR)
CKCON = 0; // 外部总线时钟设定为最
// ====== 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>
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 供调试日
// ====== <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>
Uart_SendString("Wristband System Initialized!\r\n");
Self_Test(); // 执上电硬件自 (PWR_HOLD锁存、P0.3 ADC按键常态、P1.3 电池电量)
Load_Database(); // IAP Flash 254 扇区读取有已绑定的传感器数据 RAM
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
/* 步 1: 初化事件形缓冲区队列 */
/* 步<EFBFBD> 1: 初<EFBFBD><EFBFBD>化事件<EFBFBD><EFBFBD>形缓冲区队列 */
EventQueue_Init();
/* 步 2+5: 初化应用管理器并登所有前台应,默认加 ClockApp */
/* 步<EFBFBD> 2+5: 初<EFBFBD><EFBFBD>化应用管理器并登<EFBFBD><EFBFBD>所有前台应<EFBFBD><EFBFBD>,默认加<EFBFBD><EFBFBD> ClockApp */
AppManager_Init();
/* 动并挂载后台射监控应,开始侦无线传感器信 */
/* <EFBFBD><EFBFBD>动并挂载后台射<EFBFBD><EFBFBD>监控应<EFBFBD><EFBFBD>,开始侦<EFBFBD><EFBFBD>无线传感器信<EFBFBD><EFBFBD> */
AppManager_AttachToBackground(&rf_monitor_app);
/* 启动 1ms 系统基准定时 Timer1 */
/* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1ms 系统基准定时<EFBFBD><EFBFBD> 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. 检查主循环按键定时标志 ( 1ms 中断置位,主循响应清除并理) */
/* 0. <EFBFBD><EFBFBD>查主<EFBFBD><EFBFBD><EFBFBD><EFBFBD>按键定时标志 (<EFBFBD><EFBFBD> 1ms <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>位,主循<EFBFBD><EFBFBD>响应清除并<EFBFBD><EFBFBD>理) */
if (key_scan_flag) {
key_scan_flag = 0;
Event_KeyScan_Poll();
}
/* 1. 串口非阻塞指令捕 -> 装配为事件方式入 */
/* 1. 串口非阻塞指令捕<EFBFBD><EFBFBD> -> 装配为事件方式入<EFBFBD><EFBFBD> */
cmd = Uart_RxChar();
if (cmd != '\0') {
Debug_ProcessCommand(cmd);
}
/* 2. 事件分发总线:循环轮询并处理队列的所有有效事 */
/* 2. 事件分发总线:循<EFBFBD><EFBFBD><EFBFBD><EFBFBD>询并处理队列<EFBFBD><EFBFBD>的所有有效事<EFBFBD><EFBFBD> */
while (!EventQueue_IsEmpty()) {
Event_Dispatcher_Loop();
}
/* 3. 应用调度心:运行当前处于前台活跃状的应用(集成了 CPU 运时间超时挂起保护) */
/* 3. 应用调度<EFBFBD><EFBFBD>心:运<EFBFBD><EFBFBD>当前<EFBFBD><EFBFBD>于前台活跃状<EFBFBD><EFBFBD>的应用(集成了 CPU 运<EFBFBD><EFBFBD>时间超时挂起保护) */
AppManager_RunActiveApp();
/* 4. 动休眠判定:常无操作闲置达到 60 (6000 * 10ms = 60s) 时,切入低功耗停机休 */
/* 4. <EFBFBD><EFBFBD>动休眠判定:常<EFBFBD><EFBFBD>无操作闲置达到 60 <EFBFBD><EFBFBD> (6000 * 10ms = 60s) 时,切入低功耗停机休<EFBFBD><EFBFBD> */
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; // 系统<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>时钟应用以刷新画面和背光
}
}
}
// 唤醒源事件标志,由对应的外部中断 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; // 射频中断唤醒标志
// 唤醒源事件标志,由<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>唤醒标志
/* =========================================================================
* STC32G 口掉电外部中断唤醒中断服务程序 (ISR)
* STC32G <EFBFBD><EFBFBD>口掉电<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>唤醒<EFBFBD><EFBFBD><EFBFBD><EFBFBD>服务程序 (ISR)
* ========================================================================= */
/**
* @brief Port0 口掉电中服务函数 ( isr_jump.asm 引定位至)
* @details 负责处理 P0.1, P0.2, P0.3 按键在休眠模式下的物理触发,并立刻禁用中断防止反复执行
* @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>
*/
void Port0_Isr(void) interrupt 13
{
EAXFR = 1; // 使能访问扩展寄存
p0_wakeup_flag = P0INTF | 0x01;// 读取并份 P0 中断标志寄存器 (0x01作安全掩)
P0INTF = 0x00; // 清除 P0 端口中断悬挂标志位
P0INTE = 0x00; // 【关保护】:立即关闭 P0 中断允许,防止按键处于低电平期间反复触 ISR 导致堆栈溢出
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 导致堆栈溢出
}
/**
* @brief Port2 口掉电中服务函数 ( isr_jump.asm 引定位至)
* @details 负责处理 P2.6 (SOS按键) P2.1 (射频数据脚) 在休眠模式下的物理跳变唤醒
* @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>
*/
void Port2_Isr(void) interrupt 15
{
EAXFR = 1; // 使能扩展寄存
p2_wakeup_flag = P2INTF | 0x01;// 读取并份 P2 中断标志寄存区的
P2INTF = 0x00; // 清除 P2 端口中断悬挂标志位
P2INTE = 0x00; // 立即关闭 P2 中断通道,防低电平期间反复重
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>
}
/**
* @brief Port3 口掉电中服务函数 ( isr_jump.asm 引定位至)
* @details 负责处理 P3.6 (新射频数据脚) 在休眠模式下的物理跳变唤醒
* @brief Port3 <EFBFBD><EFBFBD>口掉电中<EFBFBD><EFBFBD>服务函数 (<EFBFBD><EFBFBD> isr_jump.asm 引<EFBFBD><EFBFBD>定位至<EFBFBD><EFBFBD>)
* @details 负责处理 P3.6 (新射频数<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) 在休眠模式下的物理跳变唤醒<EFBFBD>
*/
void Port3_Isr(void) interrupt 16
{
EAXFR = 1; // 使能访问扩展寄存
p3_wakeup_flag = P3INTF | 0x01;// 读取并份 P3 中断标志寄存器 (0x01作安全掩)
P3INTF = 0x00; // 清除 P3 端口中断悬挂标志位
P3INTE = 0x00; // 立即关闭 P3 中断通道,防止反复重
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>
}

View File

@@ -51,6 +51,12 @@ void GPIO_Init(void)
MOTOR = 0;
RGB_DIN = 0; // P2.3 初始拉低,防止上电期间 WS2812B 误触发
// 配置 KEY_SOS (P2.6) 为带上拉准双向口模式以确保输入稳定
P2M1 &= ~(1 << 6);
P2M0 &= ~(1 << 6);
KEY_SOS = 1;
(*(unsigned char volatile xdata *)0xFE12) |= (1 << 6); // 使能 P2.6 的强内部上拉电阻 (P2PU = 0xFE12)
// SGM_CTRL (P1.7), LCD 控制管脚 (P1.0, P1.1, P1.4, P1.5, P1.6) 置为推挽输出
P1M1 &= ~((1 << 7) | (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6));
P1M0 |= ((1 << 7) | (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6));
@@ -206,6 +212,11 @@ void Self_Test(void)
Uart_SendByte((u8)('0' + (key_down_adc % 10)));
Uart_SendString(" [OK]\r\n");
// 2.2 检测 KEY_SOS (P2.6) 物理电平常态
Uart_SendString("[SELF-TEST] KEY_SOS (P2.6) Pin Level: ");
Uart_SendByte((u8)(KEY_SOS ? '1' : '0'));
Uart_SendString("\r\n");
// 3. 检查 P1.3 电池电压检测与百分比
vbat_mv = ADC_GetBatteryVoltage_mV();
percent = ADC_GetBatteryPercent();

View File

@@ -3,15 +3,15 @@
#include "../App/rgb.h"
#include "intrins.h"
// ATR5179 <EFBFBD><EFBFBD>Ƶǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD>ؿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŷ<EFBFBD><EFBFBD><EFBFBD>
sbit RF_TX = P2^0; // V1 <EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD> (1: ѡͨ<D1A1><CDA8><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD> TX ·<EFBFBD><EFBFBD>)
sbit RF_RX = P3^7; // V2 <EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD> (1: ѡͨ<D1A1><CDA8><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD> RX ·<EFBFBD><EFBFBD>)
// ATR5179 射频前端天线开关控制引脚定义
sbit RF_TX = P2^0; // V1 控制端 (1: 选通天线到发射 TX 路径)
sbit RF_RX = P3^7; // V2 控制端 (1: 选通天线到接收 RX 路径)
// <EFBFBD><EFBFBD>ƵоƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŷ<EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD>°<EFBFBD> PCB <20><><EFBFBD>ŶԵ<C5B6><D4B5><EFBFBD><EFBFBD><EFBFBD>)
sbit RF_TX_DAT = P2^1; // LR690L <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (DIN) - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pin 22 (P2.1)
sbit RF_RX_DATA = P3^6; // LR690L <EFBFBD><EFBFBD><EFBFBD>ս<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (DATA) - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pin 19 (P3.6)
// 射频芯片数据与电源控制引脚定义 (根据新版 PCB 引脚对调修正)
sbit RF_TX_DAT = P2^1; // LR690L 发射调制数据输入引脚 (DIN) - 物理连接 Pin 22 (P2.1)
sbit RF_RX_DATA = P3^6; // LR690L 接收解调数据输出引脚 (DATA) - 物理连接 Pin 19 (P3.6)
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><> system.c <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>)
// 声明外部延时及串口打印函数 (在 system.c 中定义)
extern void Delay_us(u16 us);
extern void Delay_ms(u16 ms);
extern u16 GetTimer0_Safe(void);
@@ -24,156 +24,176 @@ extern void Uart_SendHex32(u32 val);
extern void Uart_SendByte(u8 dat);
/**
* @brief <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƵоƬ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD> GPIO <20><><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD><EFBFBD><EFBFBD>״̬
* @brief 初始化无线射频芯片相关的 GPIO 引脚方向与状态
*/
void RF_Init(void)
{
// EAXFR = 1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܼĴ<EFBFBD><EFBFBD><EFBFBD> (XSFR)
// EAXFR = 1 允许访问扩展特殊功能寄存器 (XSFR)
EAXFR = 1;
// 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD> P2.0 (RF_TX) <EFBFBD><EFBFBD> P2.1 (RF_TX_DAT) Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ (M1=0, M0=1)
// 1. 配置 P2.0 (RF_TX) P2.1 (RF_TX_DAT) 为推挽输出模式 (M1=0, M0=1)
P2M1 &= ~((1 << 0) | (1 << 1));
P2M0 |= ((1 << 0) | (1 << 1));
// 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD> P3.7 (RF_RX) <EFBFBD><EFBFBD> P3.5 (SHUT) Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ (M1=0, M0=1)
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> P3.6 (RF_RX_DATA) Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ (M1=1, M0=0)<EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ս<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 2. 配置 P3.7 (RF_RX) P3.5 (SHUT) 为推挽输出模式 (M1=0, M0=1)
// 配置 P3.6 (RF_RX_DATA) 为高阻输入模式 (M1=1, M0=0)以匹配接收解调输入
P3M1 &= ~((1 << 5) | (1 << 7));
P3M1 |= (1 << 6);
P3M0 &= ~(1 << 6);
P3M0 |= ((1 << 5) | (1 << 7));
// 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳĬ<EFBFBD>ϵij<EFBFBD>ʼ<EFBFBD><EFBFBD>ƽ
RF_TX = 0; // <EFBFBD>Ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ·
SHUT = 1; // Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SHUT<EFBFBD><EFBFBD>ʹ LR690L <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߹ر<EFBFBD>״̬
RF_RX = 0; // <EFBFBD>Ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ·
RF_TX_DAT = 0; // <EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>
// 3. 设置系统默认的初始电平
RF_TX = 0; // 断开发射天线通路
SHUT = 1; // 默认拉高 SHUT,使 LR690L 处于休眠关闭状态
RF_RX = 0; // 断开接收天线通路
RF_TX_DAT = 0; // 调制发送数据线置低
}
/**
* @brief <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>
* @param mode <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ (0-<2D><><EFBFBD>߸<EFBFBD><DFB8><EFBFBD>, 1-<2D><><EFBFBD>չ<EFBFBD><D5B9><EFBFBD>, 2-<2D><><EFBFBD><EFBFBD><E4B9A4>)
* @brief 配置无线射频收发系统的运行模式与天线切换
* @param mode 运行模式 (0-休眠隔离, 1-接收工作, 2-发射工作)
*/
void RF_SetMode(u8 mode)
{
if (mode == 0) // ====== ģʽ 0: <EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><EFBFBD><EFBFBD>ģʽ (Sleep/Idle) ======
if (mode == 0) // ====== 模式 0: 休眠隔离模式 (Sleep/Idle) ======
{
SHUT = 1; // ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SHUT <20><><EFBFBD>ţ<EFBFBD>ʹ LR690L <20><><EFBFBD>׽<EFBFBD><D7BD><EFBFBD><EFBFBD>͹<EFBFBD><CDB9>Ĵ<EFBFBD><C4B4><EFBFBD>
RF_RX = 0; // <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>·
RF_TX = 0; // <EFBFBD>رշ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD>
SHUT = 1; // 强制拉高 SHUT 引脚,使 LR690L 彻底进入低功耗待机
RF_RX = 0; // 关闭接收天线开关,防止外界电磁杂波串入接收电路
RF_TX = 0; // 关闭发射天线开关
}
else if (mode == 1) // ====== ģʽ 1: <EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD>ģʽ (RX Mode) ======
else if (mode == 1) // ====== 模式 1: 接收工作模式 (RX Mode) ======
{
SHUT = 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> SHUT ʹ<EFBFBD><EFBFBD> LR690L оƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RF_TX = 0; // <EFBFBD>رշ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RF_RX = 1; // ѡͨ<EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD> RX <20><><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>ʹ<EFBFBD>ܽ<EFBFBD><DCBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>Ƶ<EFBFBD>Ŵ<EFBFBD>
SHUT = 0; // 拉低 SHUT 使能 LR690L 芯片,开始解调接收
RF_TX = 0; // 关闭发射开关
RF_RX = 1; // 选通天线到 RX 接收路径,使能接收链路高频放大
}
else if (mode == 2) // ====== ģʽ 2: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ (TX Mode) ======
else if (mode == 2) // ====== 模式 2: 发发射工作模式 (TX Mode) ======
{
SHUT = 1; // <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>źŶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>
RF_RX = 0; // <EFBFBD>رս<EFBFBD><EFBFBD>տ<EFBFBD><EFBFBD><EFBFBD>
RF_TX = 1; // ѡͨ<EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD> TX <20><><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>߷<EFBFBD><DFB7><EFBFBD>
SHUT = 1; // 接收机停机,防止发射强信号顶坏接收前端
RF_RX = 0; // 关闭接收开关
RF_TX = 1; // 选通天线到 TX 发射路径,使能天线发射
}
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD> EV1527 Э<><EFBFBD>ε<EFBFBD><CEB5>Ʒ<EFBFBD><C6B7><EFBFBD>һ֡ 24 λ<><CEBB>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD> (Sync + 24bit Data)
* @brief 使用单片机硬件 Timer0 实现高精度发射电平时延控制
* @param us 延时微秒数
* @note STC32G 在 24MHz 晶振 12T 模式下Timer0 的 1 tick 正好等于 0.5us (2MHz)
*/
void RF_Delay_us(u16 us)
{
u16 ticks = us * 2;
TL0 = 0;
TH0 = 0;
TR0 = 1; // 启动定时器 0
while (GetTimer0_Safe() < ticks);
TR0 = 0; // 停止定时器 0
}
/**
* @brief 按照 EV1527 协议单次调制发送一帧 24 位射频数据 (Sync + 24bit Data)
*/
void EV1527_TxFrame(u32 addr, u8 dat)
{
u8 i;
u32 tx_val;
// <EFBFBD>ϲ<EFBFBD> 20 λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD> 4 λ<><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 24 λ<>ز<EFBFBD><D8B2><EFBFBD>
// 合并 20 位地址与 4 位数据,成为 24 位完整 EV1527 帧
tx_val = (addr << 4) | (dat & 0x0F);
// 1. ͬ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1T (Լ 350us)<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 31T (Լ 10850us)
// 1. 同步头脉冲: 高电平 1T (350us) + 低电平 31T (10850us)
RF_TX_DAT = 1;
Delay_us(350);
RF_Delay_us(350);
RF_TX_DAT = 0;
Delay_us(10850);
RF_Delay_us(10850);
// 2. <EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD> 24 λ<><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ
// 2. 依次发送 24 个数据位 (MSB First)
for (i = 0; i < 24; i++)
{
if (tx_val & (0x800000UL >> i))
{
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> "1"<22><><EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD> 3T (1050us)<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1T (350us)
// 逻辑 "1": 高电平 3T (1050us) + 低电平 1T (350us)
RF_TX_DAT = 1;
Delay_us(1050);
RF_Delay_us(1050);
RF_TX_DAT = 0;
Delay_us(350);
RF_Delay_us(350);
}
else
{
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> "0"<22><><EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD> 1T (350us)<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3T (1050us)
// 逻辑 "0": 高电平 1T (350us) + 低电平 3T (1050us)
RF_TX_DAT = 1;
Delay_us(350);
RF_Delay_us(350);
RF_TX_DAT = 0;
Delay_us(1050);
RF_Delay_us(1050);
}
}
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>η<EFBFBD><EFBFBD><EFBFBD> EV1527 <20><>Ƶ֡<C6B5><D6A1><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9>֡<EFBFBD><D6A1>ʧ
* @brief 调制发射 25 帧 EV1527 射频同步电平信号以确保接收侧可靠触发
*/
void EV1527_Transmit(u32 addr, u8 dat)
{
u8 i;
RF_SetMode(2); // <EFBFBD>л<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD>
Delay_ms(5); // <20>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶͨ·
u8 r;
bit ea_bak = EA; // 备份并屏蔽全局中断,确保发射高低电平周期的绝对纯净与防抖
EA = 0;
// ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 10 ֡<><D6A1>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD><D5B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 ֡<><D6A1><EFBFBD>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (i = 0; i < 10; i++)
RF_SetMode(2); // 切换为发射状态,接通天线与射频模块通道
Delay_ms(5); // 稍作延时使射频通路稳定
// 连续发射 25 帧以保证接收设备顺利锁定并解码
for (r = 0; r < 25; r++)
{
EV1527_TxFrame(addr, dat);
Delay_ms(10); // ֡<><EFBFBD><E4B1A3><EFBFBD><EFBFBD>ʱ
// 去除帧与帧之间可能导致波形不连续的 Delay_ms
}
RF_TX_DAT = 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RF_SetMode(1); // <EFBFBD><EFBFBD><EFBFBD>»ָ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RF_TX_DAT = 0; // 结束发射,拉低数据脚
RF_SetMode(1); // 恢复为常态后台接收模式
EA = ea_bak; // 还原全局中断开关状态
}
/**
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD>΢<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> Timer0 Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
* @brief 获取特定电平引脚状态的持续微秒时间 (利用 Timer0 硬件测量)
*/
u16 GetPulseDuration(u8 state, u16 timeout_us)
{
u16 timeout_ticks;
// ǿ<EFBFBD>ƹر<EFBFBD> Timer0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>㸴λ
// 强制关闭 Timer0 计数器,并将其计数值清零复位
TR0 = 0;
TMOD &= 0xF0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Timer0 <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD>Ϊģʽ 0 (16λ<36>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>)
TMOD &= 0xF0; // 设置 Timer0 寄存器为模式 0 (16位自动重载)
TL0 = 0x00;
TH0 = 0x00;
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 16 λ<><CEBB>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ticks <20><>ʱֵ (<28><> 1T ģʽ 24MHz <EFBFBD>£<EFBFBD>1 Tick = 1 / 24M = 0.0416us)
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ Timer0 Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 12T ģʽ (1 Tick = 12 / 24MHz = 0.5us)
// 换算 16 位定时器所需的最大 ticks 超时值 (在 1T 模式 24MHz 下,1 Tick = 1 / 24M = 0.0416us)
// 但此系统 Timer0 默认配置为 12T 模式 (1 Tick = 12 / 24MHz = 0.5us)
timeout_ticks = (u16)((u32)timeout_us * (MAIN_Fosc / 1000000UL) / 12UL);
TR0 = 1; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Timer0 Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TR0 = 1; // 启动 Timer0 硬件计数器
// <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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
// 根据要捕获的电平状态进行阻塞判断,直到电平发生翻转或计数超时
while (RF_RX_DATA == state)
{
if (GetTimer0_Safe() > timeout_ticks)
{
TR0 = 0;
return 0; // <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0
return 0; // 判定超时,返回 0
}
}
TR0 = 0; // <EFBFBD>ض϶<EFBFBD>ʱ<EFBFBD><EFBFBD>
TR0 = 0; // 关断定时器
return (u16)((u32)GetTimer0_Safe() * 12UL / (MAIN_Fosc / 1000000UL));
}
// ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ź<EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 模拟射频信号全局变量定义
volatile u32 mock_rx_addr = 0;
volatile u8 mock_rx_data = 0;
volatile bit mock_rf_ready = 0;
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD> EV1527 <20><>Ƶ<EFBFBD>ź<EFBFBD><C5BA><EFBFBD><EFBFBD><EFBFBD>֡
* @brief 阻塞式检测并解码一个合法的 EV1527 射频信号数据帧
*/
bit EV1527_Decode(u32 *out_addr, u8 *out_data)
{
@@ -185,7 +205,7 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
u16 idata raw_h[24];
u16 idata raw_l[24];
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 检查模拟射频触发
if (mock_rf_ready) {
mock_rf_ready = 0;
*out_addr = mock_rx_addr;
@@ -193,14 +213,14 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
return 1;
}
// ====== 1. ͬ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ======
// ====== 1. 同步头引导脉冲捕获 ======
{
u16 wait_cnt = 0;
while (RF_RX_DATA == 1)
{
Delay_us(5);
wait_cnt++;
if (wait_cnt > 2000) // 10 <EFBFBD><EFBFBD><EFBFBD>볬ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (wait_cnt > 2000) // 10 毫秒超时保护
return 0;
}
@@ -209,28 +229,28 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
{
Delay_us(5);
wait_cnt++;
if (wait_cnt > 4000) // 20 <EFBFBD><EFBFBD><EFBFBD>볬ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (wait_cnt > 4000) // 20 毫秒超时保护
return 0;
}
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>ߵ<EFBFBD>ƽʱ<EFBFBD><EFBFBD>
// 捕获引导头高电平时间
high_time = GetPulseDuration(1, 2500);
if (high_time < 50 || high_time > 2500) {
return 0;
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 31T <20>͵<EFBFBD>ƽʱ<C6BD><CAB1>
// 捕获引导头后续的 31T 低电平时间
low_time = GetPulseDuration(0, 60000);
if (low_time < 1500 || low_time > 60000) {
return 0;
}
// ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD>׼ʱ<EFBFBD><EFBFBD> T <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD>ȼ<EFBFBD>Ϊ 1T)
// 同步引导脉冲的基准时间 T 计算 (引导脉冲高电平宽度即为 1T)
T = high_time;
if (T < 100 || T > 800) return 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>Χ<EFBFBD>޷<EFBFBD>: 100us ~ 800us
if (T < 100 || T > 800) return 0; // 自适应范围限幅: 100us ~ 800us
// ====== 2. <EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><EFBFBD><EFBFBD> 24 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD> ======
// ====== 2. 依次解析 24 个数据位脉宽 ======
for (i = 0; i < 24; i++)
{
raw_h[i] = GetPulseDuration(1, 2000);
@@ -240,15 +260,15 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
if (raw_l[i] == 0) return 0;
}
// ====== 3. ˫<EFBFBD>˱<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ======
// ====== 3. 双端比值解调判定数据内容 ======
for (i = 0; i < 24; i++)
{
u16 total = raw_h[i] + raw_l[i];
if (total < T * 3 || total > T * 6) return 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3T~6T ֮<EFBFBD><EFBFBD>
if (total < T * 3 || total > T * 6) return 0; // 单个数据位周期必须在 3T~6T 之间
if (raw_h[i] > raw_l[i] * 2)
{
// <EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>Գ<EFBFBD><EFBFBD>ڵ͵<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD> "1"
// 高电平明显长于低电平,代表逻辑 "1"
if (i < 20)
addr = (addr << 1) | 1;
else
@@ -256,7 +276,7 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
}
else if (raw_l[i] > raw_h[i] * 2)
{
// <EFBFBD>͵<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>Գ<EFBFBD><EFBFBD>ڸߵ<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD> "0"
// 低电平明显长于高电平,代表逻辑 "0"
if (i < 20)
addr = (addr << 1);
else
@@ -264,18 +284,18 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data)
}
else
{
return 0; // <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>
return 0; // 电平脉冲比值不合规,判定数据帧畸变,解码作废
}
}
// У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 校验无误,输出解调数据
*out_addr = addr;
*out_data = dat;
return 1;
}
/**
* @brief RF <EFBFBD>շ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD><>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ӡ)
* @brief RF 收发诊断测试功能 (支持发送与接收监听打印)
*/
void RF_DiagnosticMode(char choice)
{
@@ -283,23 +303,23 @@ void RF_DiagnosticMode(char choice)
{
u8 i;
Uart_SendString("=== RF TX Test: Transmitting 20 test frames... ===\r\n");
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD>
// 开启发射模式并配置天线开关
RF_SetMode(2);
Delay_ms(5);
for (i = 0; i < 20; i++)
{
// <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>˸
// 连续发送测试包,每次发送伴随马达短震及指示灯闪烁
MOTOR = 1;
RGB_Send(0, 150, 0, 0, 150, 0); // <EFBFBD>̹<EFBFBD><EFBFBD><EFBFBD>˸
RGB_Send(0, 150, 0, 0, 150, 0); // 绿光闪烁
EV1527_TxFrame(0x37A86UL, 0x01);
MOTOR = 0;
RGB_Send(0, 0, 0, 0, 0, 0);
Delay_ms(150); // ֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Delay_ms(150); // 帧间隔
}
RF_TX_DAT = 0;
RF_SetMode(1); // <EFBFBD><EFBFBD><EFBFBD>»ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
RF_SetMode(1); // 重新恢复接收模式
Uart_SendString("[RF] Transmit Done!\r\n");
}
else if (choice == 'r')
@@ -309,10 +329,10 @@ void RF_DiagnosticMode(char choice)
u8 rx_data;
Uart_SendString("=== RF RX Test: Listening for 5 seconds... ===\r\n");
RF_SetMode(1); // <EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RF_SetMode(1); // 配置进入接收模式并使能天线
Delay_ms(10);
// 5<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 5秒的非阻塞监听
for (wait_ms = 0; wait_ms < 5000; wait_ms++)
{
if (EV1527_Decode(&rx_addr, &rx_data))
@@ -323,7 +343,7 @@ void RF_DiagnosticMode(char choice)
Uart_SendHex8(rx_data);
Uart_SendString("\r\n");
// <EFBFBD>յ<EFBFBD><EFBFBD>źź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𶯲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 收到信号后马达震动并亮青色灯提醒
MOTOR = 1;
RGB_Send(0, 150, 150, 0, 150, 150);
Delay_ms(100);
@@ -335,3 +355,46 @@ void RF_DiagnosticMode(char choice)
Uart_SendString("=== RF RX Test End ===\r\n");
}
}
/**
* @brief 电气回环自检测试 (物理短路 P2.1 与 P3.6 自检)
* @details 用户通过短路 P2.1 和 P3.6 来实现 GPIO 的物理连通性自检
*/
void Loopback_Test(void)
{
u16 match_count = 0;
u16 i;
EAXFR = 1;
RF_SetMode(1); // 开启接收芯片
Delay_ms(100);
Uart_SendString("Starting RF Hardware Loopback Test (P2.1 -> P3.6)...\r\n");
Uart_SendString("Please use a metal tweezers to short-circuit P2.1 (Pin 22) and P3.6 (Pin 19)!\r\n");
for (i = 0; i < 100; i++)
{
RF_TX_DAT = 1;
Delay_us(500);
if (RF_RX_DATA == 1) match_count++;
RF_TX_DAT = 0;
Delay_us(500);
if (RF_RX_DATA == 0) match_count++;
}
Uart_SendString("Loopback Match Count: ");
Uart_SendHex16(match_count);
Uart_SendString("/200\r\n");
if (match_count > 150)
{
Uart_SendString("Result: PASS! Pin P2.1 and P3.6 are electrical connected successfully!\r\n");
}
else
{
Uart_SendString("Result: FAIL! GPIO coupling check failed. Short-circuit the pins and test again.\r\n");
}
RF_SetMode(0); // 关断射频
}

View File

@@ -61,4 +61,9 @@ bit EV1527_Decode(u32 *out_addr, u8 *out_data);
*/
void RF_DiagnosticMode(char choice);
/**
* @brief 电气回环自检测试 (物理短路 P2.1 与 P3.6 自检)
*/
void Loopback_Test(void);
#endif // __RF_H__