Compare commits

...

3 Commits

8 changed files with 229 additions and 67 deletions

View File

@@ -205,7 +205,7 @@ void ClockApp_OnStart(void)
{ {
time_edit_active = 0; time_edit_active = 0;
current_state = STATE_NORMAL; current_state = STATE_NORMAL;
RF_SetMode(1); RF_SetMode(0);
UI_ShowClockPage(current_state, current_hour, current_min); UI_ShowClockPage(current_state, current_hour, current_min);
// 启动时熄灭灯条 // 启动时熄灭灯条
@@ -377,7 +377,7 @@ void MenuApp_onClose(void)
{ {
menu_level = 0; menu_level = 0;
RGB_Send(0, 0, 0, 0, 0, 0); RGB_Send(0, 0, 0, 0, 0, 0);
RF_SetMode(1); RF_SetMode(0);
Uart_SendString("[MenuApp] Closed\r\n"); Uart_SendString("[MenuApp] Closed\r\n");
} }
@@ -577,7 +577,7 @@ void PairApp_onClose(void)
{ {
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯光 RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯光
MOTOR = 0; MOTOR = 0;
RF_SetMode(1); RF_SetMode(0);
Uart_SendString("[PairApp] Closed\r\n"); Uart_SendString("[PairApp] Closed\r\n");
} }

View File

@@ -2,6 +2,9 @@
#include "rgb.h" #include "rgb.h"
#include "ui.h" #include "ui.h"
#include "../Drivers/lcd.h" #include "../Drivers/lcd.h"
#include "../Drivers/rf.h"
#include "app_manager.h"
#include "database.h"
void GPIO_Init(void) void GPIO_Init(void)
{ {
@@ -219,8 +222,8 @@ void Enter_Low_Power_Sleep(void)
LCD_SCL = 0; LCD_SCL = 0;
LCD_SDI = 0; LCD_SDI = 0;
// 6. 休眠状态下不能关闭接收芯片,保持 SHUT 为高电平 (1) 工作状态 // 6. 休眠状态下开启接收芯片并接通天线 (SHUT=0, RF_RX=1),此时屏幕关闭没有 SGM3833 噪底干扰
SHUT = 1; RF_SetMode(1);
// 确保开启扩展寄存器访问 (EAXFR = 1),以便能正确配置端口唤醒使能扩展寄存器 // 确保开启扩展寄存器访问 (EAXFR = 1),以便能正确配置端口唤醒使能扩展寄存器
P_SW2 |= 0x80; P_SW2 |= 0x80;
@@ -239,33 +242,57 @@ void Enter_Low_Power_Sleep(void)
P0WKUE |= 0x0E; // 使使能 P0.1/P0.2/P0.3 掉电唤醒 P0WKUE |= 0x0E; // 使使能 P0.1/P0.2/P0.3 掉电唤醒
P2WKUE |= 0x40; // 使使能 P2.6 掉电唤醒 P2WKUE |= 0x40; // 使使能 P2.6 掉电唤醒
// 9. 不允许外部中断 2 (RF_RX_DATA) 沿触发唤醒源 // 9. 开启外部中断 2 (RF_RX_DATA) 沿触发唤醒源
EX2 = 0; EX2 = 1;
// 10. 清除端口中断的悬挂/标志位,防误触 // 10. 清除端口中断的悬挂/标志位,防误触
P0INTF = 0x00; P0INTF = 0x00;
P2INTF = 0x00; P2INTF = 0x00;
// 11. 关闭 Timer1 中断,保持 EA=1 让端口中断能唤醒 // 11. 关闭 Timer1 中断,保持 EA=1 让端口/射频中断能唤醒
ET1 = 0; ET1 = 0;
EA = 1; EA = 1;
// 12. 写入 PCON 掉电模式位,使 MCU 进入深度 Power-Down 挂起状态 // 12. 写入 PCON 掉电模式位,使 MCU 进入深度 Power-Down 挂起状态
Uart_SendString("[SYS] Entering Power-Down mode...\r\n"); // 如果由于杂波伪唤醒,我们在循环中检测并重新进入休眠
PCON |= 0x02; // PD = 1 while (1)
_nop_(); {
_nop_(); Uart_SendString("[SYS] Entering Power-Down mode...\r\n");
_nop_(); PCON |= 0x02; // PD = 1
_nop_(); _nop_();
_nop_();
_nop_();
_nop_();
// 13. 唤醒并执行完 ISR 后CPU 从这里继续执行 // 13. 唤醒并执行完 ISR 后CPU 从这里继续执行
Wakeup_Restore(); if (Wakeup_Restore())
{
break; // 真实唤醒(按键或合法射频报警),退出休眠循环
}
// 14. 伪唤醒,重新配置唤醒源寄存器,准备下一次 Power-Down
EAXFR = 1;
RF_SetMode(1); // 重新开启接收芯片并接通天线
EX2 = 1; // 重新使能外部中断 2
P0INTF = 0x00;
P2INTF = 0x00;
P0INTE = 0x0E;
P2INTE = 0x40;
P0WKUE = 0x0E;
P2WKUE = 0x40;
ET1 = 0; // 关闭定时器 1
EA = 1;
}
} }
void Wakeup_Restore(void) bit Wakeup_Restore(void)
{ {
u8 p0_flag; u8 p0_flag;
u8 p2_flag; u8 p2_flag;
u16 rf_check_ms = 0;
bit rf_valid = 0;
u32 rx_addr;
u8 rx_data;
// 确保 EAXFR=1 才能访问扩展 SFR (P0INTF/P2INTF/P0INTE/P2INTE) // 确保 EAXFR=1 才能访问扩展 SFR (P0INTF/P2INTF/P0INTE/P2INTE)
EAXFR = 1; EAXFR = 1;
@@ -281,47 +308,118 @@ void Wakeup_Restore(void)
P2WKUE = 0x00; // 清除 P2 唤醒允许 P2WKUE = 0x00; // 清除 P2 唤醒允许
P0INTF = 0x00; P0INTF = 0x00;
P2INTF = 0x00; P2INTF = 0x00;
EX2 = 0; EX2 = 0; // 唤醒后禁用射频中断,运行模式下不受噪底杂波干扰
// 1b. 关闭掉电唤醒定时器 // 1b. 关闭掉电唤醒定时器
WKTCH = 0x00; WKTCH = 0x00;
WKTCL = 0x00; WKTCL = 0x00;
// 2. 重新开启全局中断 Timer1 中断 // 2. 开启全局中断,但暂时保持 Timer1 关闭以防中断影响射频比值软件解码
EA = 1; EA = 1;
ET1 = 1; ET1 = 0;
// [诊断] 打印唤醒来源 // 3. 判断是否为按键唤醒
if (p0_flag & 0x0E) { if ((p0_flag & 0x0E) || (p2_flag & 0x40))
Uart_SendString("[WR] Woken by KEY P0 (P0INTF=0x"); {
Uart_SendHex8(p0_flag); if (p0_flag & 0x0E) {
Uart_SendString(")\r\n"); Uart_SendString("[WR] Woken by KEY P0 (P0INTF=0x");
} else if (p2_flag & 0x40) { Uart_SendHex8(p0_flag);
Uart_SendString("[WR] Woken by KEY P2 (P2INTF=0x"); Uart_SendString(")\r\n");
Uart_SendHex8(p2_flag); } else {
Uart_SendString(")\r\n"); Uart_SendString("[WR] Woken by KEY P2 (P2INTF=0x");
} else { Uart_SendHex8(p2_flag);
Uart_SendString("[WR] Woken by TIMER (no key flag)\r\n"); Uart_SendString(")\r\n");
}
// 运行模式屏幕开启有噪底干扰,关闭射频接收,防止无信号时在后台乱输出电平
RF_SetMode(0);
// 启动 SGM3833 PMIC 并发送脉冲使能升压
SGM_CTRL = 1;
SGM_SendPulse(27);
// 等待负压电轨充分稳定
Delay_ms(200);
// 重做屏控制器 RM69310 寄存器组 of 初始化
LCD_Init();
// 重新开启 Timer1
ET1 = 1;
inactivity_timer = 0;
// 绘制时钟主界面
current_state = STATE_NORMAL;
UI_ShowClockPage(current_state, current_hour, current_min);
Uart_SendString("[SYS] Wakeup restored by Key!\r\n");
return 1; // 真实唤醒
} }
else
{
// 射频外部中断或者 WKT 唤醒,保持屏幕 SGM_CTRL=0 关闭状态,避免升压干扰射频
Uart_SendString("[WR] Woken by RF/WKT, decoding...\r\n");
SGM_CTRL = 0;
// 3. 保持 SHUT 开启射频接收芯片工作 // 尝试解码 150ms 射频包
SHUT = 1; for (rf_check_ms = 0; rf_check_ms < 150; rf_check_ms++)
{
if (EV1527_Decode(&rx_addr, &rx_data))
{
u8 slot;
if (Check_Sensor_ID(rx_addr, &slot))
{
// 找到了匹配的已配对传感器
if (sensor_list[slot].zone == 0 || current_state == STATE_ARMED)
{
rf_valid = 1;
captured_addr = rx_addr;
alarm_sensor_slot = slot;
break;
}
}
}
Delay_ms(1);
}
// 4. 拉高 SGM_CTRL 并发送脉冲使能 SGM3833 升压 // 采集完/超时后,立即关闭射频接收芯片,杜绝乱输出的噪底电平
SGM_CTRL = 1; RF_SetMode(0);
SGM_SendPulse(27);
// 5. 等待负压电轨充分稳定 if (rf_valid)
Delay_ms(200); {
// 真实报警信号唤醒:开启屏幕,显示报警画面
Uart_SendString("[WR] Valid Alarm RF Decoded! Address=0x");
Uart_SendHex32(captured_addr);
Uart_SendString("\r\n");
// 6. 重做屏控制器 RM69310 寄存器组的初始化 // 启动 SGM3833 并使能升压
LCD_Init(); SGM_CTRL = 1;
SGM_SendPulse(27);
Delay_ms(200);
LCD_Init();
// 7. 重置闲置倒计时 // 重新开启 Timer1
inactivity_timer = 0; ET1 = 1;
inactivity_timer = 0;
// 8. 直接绘制时钟界面(绕过 AppManager 早期返回保护) // 进入报警 App
current_state = STATE_NORMAL; AppManager_StartApp(APP_ID_ALARM);
UI_ShowClockPage(current_state, current_hour, current_min); return 1; // 真实唤醒
Uart_SendString("[SYS] Wakeup restored!\r\n"); }
else
{
// 伪唤醒(杂波引起的误触发,或未注册传感器):不开启屏幕,返回 0 以便主循环重新进入休眠
Uart_SendString("[WR] RF Noise or Unregistered signal, back to sleep...\r\n");
// 重新开启 Timer1
ET1 = 1;
return 0; // 假唤醒,重新进入 Power-Down
}
}
}
// STC32G INT2 外部中断服务子程序 (向量 10)
// 用于从 Power-Down 模式中由射频数据脚下降沿唤醒 CPU
void INT2_Isr(void) interrupt 10
{
EX2 = 0; // 唤醒后立即关闭外部中断,避免噪底电平在唤醒后反复触发中断
} }

View File

@@ -26,6 +26,6 @@ void FormatHex(u32 val, char *buf);
// 电源管理与休眠唤醒 // 电源管理与休眠唤醒
void Enter_Low_Power_Sleep(void); void Enter_Low_Power_Sleep(void);
void Wakeup_Restore(void); bit Wakeup_Restore(void);
#endif #endif

View File

@@ -9,19 +9,8 @@
## 2. 关键代码片段与逻辑实现 ## 2. 关键代码片段与逻辑实现
### 2.1 供电引脚初始化 ### 2.1 供电引脚初始化
系统初始化时,配置 `SHUT`(控制 SGM3833 供电的引脚 `P2.2`)为推挽输出,并拉高以开启屏幕供电:
```c
sbit SHUT = P2^2; // Pin 23
void Power_Init(void) {
// P2.2 (SHUT) 配置为推挽输出
P2M1 &= ~(1 << 2);
P2M0 |= (1 << 2);
// 拉高引脚,开启 SGM3833 负压供电
SHUT = 1;
}
```
### 2.2 进入低功耗睡眠 (Enter_Low_Power_Sleep) ### 2.2 进入低功耗睡眠 (Enter_Low_Power_Sleep)
在 10 秒无按键操作发生后,关闭屏幕显示,断电,配置中断,并进入 Power-Down 挂起状态: 在 10 秒无按键操作发生后,关闭屏幕显示,断电,配置中断,并进入 Power-Down 挂起状态:
@@ -31,7 +20,7 @@ void Enter_Low_Power_Sleep(void) {
LCD_WriteCmd(0x10); LCD_WriteCmd(0x10);
// 2. 切断 SGM3833 电源,停止输出负压 // 2. 切断 SGM3833 电源,停止输出负压
SHUT = 0;
// 3. 配置引脚中断 (P0.1, P0.2, P0.3, P2.6) 允许唤醒 // 3. 配置引脚中断 (P0.1, P0.2, P0.3, P2.6) 允许唤醒
// 允许 P0 / P2 端口中断以供按键唤醒 // 允许 P0 / P2 端口中断以供按键唤醒
@@ -56,12 +45,12 @@ void Port0_Isr(void) interrupt 37 {
P0INTF = 0x00; // 清除 P0 中断标志 P0INTF = 0x00; // 清除 P0 中断标志
Wakeup_Restore(); Wakeup_Restore();
} }
//周期嗅探模式来接收信号源
void Wakeup_Restore(void) { void Wakeup_Restore(void) {
if (SHUT == 1) return; // 已经在工作状态,直接返回 if // 已经在工作状态,直接返回
// 重新使能 SGM3833 供电
// 1. 拉高 SHUT 重新使能 SGM3833 供电
SHUT = 1;
// 2. 延时约 50ms 等待升压/负压输出稳定 // 2. 延时约 50ms 等待升压/负压输出稳定
Delay50ms(); Delay50ms();

View File

@@ -0,0 +1 @@
{"hostname":"DESKTOP-0S8JI7H","username":"xtell"}

View File

@@ -0,0 +1 @@
{"hostname":"DESKTOP-0S8JI7H","username":"xtell"}

View File

@@ -0,0 +1 @@
{"hostname":"DESKTOP-0S8JI7H","username":"xtell"}

View File

@@ -171,7 +171,7 @@
<Group> <Group>
<GroupName>App</GroupName> <GroupName>App</GroupName>
<tvExp>0</tvExp> <tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel> <cbSel>0</cbSel>
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
@@ -187,6 +187,78 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<bShared>0</bShared> <bShared>0</bShared>
</File> </File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>2</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\rgb.c</PathWithFileName>
<FilenameWithoutPath>rgb.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\event.c</PathWithFileName>
<FilenameWithoutPath>event.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>4</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\app_manager.c</PathWithFileName>
<FilenameWithoutPath>app_manager.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\database.c</PathWithFileName>
<FilenameWithoutPath>database.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>6</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\ui.c</PathWithFileName>
<FilenameWithoutPath>ui.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>7</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\App\system.c</PathWithFileName>
<FilenameWithoutPath>system.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group> </Group>
<Group> <Group>
@@ -197,7 +269,7 @@
<RteFlg>0</RteFlg> <RteFlg>0</RteFlg>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>2</FileNumber> <FileNumber>8</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>
@@ -209,7 +281,7 @@
</File> </File>
<File> <File>
<GroupNumber>2</GroupNumber> <GroupNumber>2</GroupNumber>
<FileNumber>3</FileNumber> <FileNumber>9</FileNumber>
<FileType>1</FileType> <FileType>1</FileType>
<tvExp>0</tvExp> <tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg> <tvExpOptDlg>0</tvExpOptDlg>