fix(sleep): pin P3.6 to a fixed rising-edge trigger before Power Down

RF_HandleEdgeInterrupt()'s software ping-pong toggle can leave P3IM0
parked in either edge direction while awake; Enter_Low_Power_Sleep()
never reset it, so sleep entry could randomly land on a direction that
misses the wake edge. Per the datasheet truth table (WO-04 2.9), only
edge modes support power-down wake, not level modes, so this forces a
known rising-edge state (matching RF_Init()'s own boot default) instead
of switching to level-triggered as originally requested. wo-05 updated
to record the deviation and rationale.
This commit is contained in:
edisondeng
2026-07-31 18:14:22 +08:00
parent ae235d3c51
commit 79d604a387
2 changed files with 14 additions and 6 deletions

View File

@@ -346,8 +346,16 @@ void Enter_Low_Power_Sleep(void)
P2WKUE |= 0x40; // 使能 P2.6 掉电唤醒 P2WKUE |= 0x40; // 使能 P2.6 掉电唤醒
// 9. 配置 Port3 掉电唤醒源 (RF_RX_DATA=P3.6) // 9. 配置 Port3 掉电唤醒源 (RF_RX_DATA=P3.6)
// 双边沿触发与 P3INTE 中断允许现已在 RF_Init() 中常态开启 (供正常运行期间的边沿解码使用) // RF_HandleEdgeInterrupt() 用软件乒乓单边沿切换模拟双边沿触发,运行期间 P3IM0 会在
// 此处只需重新武装 P3WKUE (掉电唤醒使能,会被 Wakeup_Restore() 清零) 与清除挂起标志 // 上升沿/下降沿之间动态翻转;如果休眠前不重新固定它,进入 Power Down 那一刻 P3IM0
// 具体停在哪个方向是不确定的可能导致唤醒不了或唤醒延迟。根据《STC32G 技术手册》
// 15.1.3 节真值表PxIM1/PxIM0 的四种模式里只有下降沿(0,0)和上升沿(0,1)两种边沿模式
// 标注支持掉电唤醒,高/低电平两种模式都不支持——所以这里没有改成电平触发,而是强制
// 固定为上升沿 (与 RF_Init() 开机时的初始配置一致),确保休眠那一刻处于一个明确的、
// 手册标注支持唤醒的状态;唤醒后 P3IM0 就停在上升沿,与开机状态相同,解码状态机从
// 一个已知状态重新开始,不需要额外恢复。
P3IM1 &= ~0x40;
P3IM0 |= 0x40; // (0,1) 上升沿触发
P3INTF = 0x00; // 清除挂起标志 P3INTF = 0x00; // 清除挂起标志
P3WKUE |= 0x40; // 使能 P3.6 掉电唤醒 P3WKUE |= 0x40; // 使能 P3.6 掉电唤醒

View File

@@ -75,8 +75,8 @@
- 传感器类型选择(现在是 `app_menu.c` 的 `menu_level==1`,第 158-172 行;重构后是 `pair_app` 的 `PAIR_STATE_SELECT_TYPE`5 项,索引 0~4) - 传感器类型选择(现在是 `app_menu.c` 的 `menu_level==1`,第 158-172 行;重构后是 `pair_app` 的 `PAIR_STATE_SELECT_TYPE`5 项,索引 0~4)
- 现在是 `if (menu_select > 0) menu_select--;` / `if (menu_select < MAX) menu_select++;`,到边界就不动;改成到边界时绕到另一端,例如 UP 在 `menu_select==0` 时跳到 `MAX`DOWN 在 `menu_select==MAX` 时跳回 `0`。 - 现在是 `if (menu_select > 0) menu_select--;` / `if (menu_select < MAX) menu_select++;`,到边界就不动;改成到边界时绕到另一端,例如 UP 在 `menu_select==0` 时跳到 `MAX`DOWN 在 `menu_select==MAX` 时跳回 `0`。
### 6. P3.6 休眠前改电平触发唤醒 ### 6. P3.6 休眠前唤醒触发方式修复
- 现状`RF_HandleEdgeInterrupt()` 用软件乒乓单边沿切换模拟双边沿触发,`P3IM0` 会在上升沿/下降沿之间动态翻转;`Enter_Low_Power_Sleep()` 进入休眠前完全没有重新设置 `P3IM0`/`P3IM1`,导致进入 Power Down 那一刻 `P3IM0` 具体停在哪个方向是不确定的,如果停在"等下降沿"而实际先来的是上升沿,就可能唤醒不了或唤醒延迟。 - 原因`RF_HandleEdgeInterrupt()` 用软件乒乓单边沿切换模拟双边沿触发,`P3IM0` 会在上升沿/下降沿之间动态翻转;`Enter_Low_Power_Sleep()` 进入休眠前完全没有重新设置 `P3IM0`/`P3IM1`,导致进入 Power Down 那一刻 `P3IM0` 具体停在哪个方向是不确定的,如果停在"等下降沿"而实际先来的是上升沿,就可能唤醒不了或唤醒延迟。
- **需要注意**:根据 WO-04 §2.9 查到的《STC32G 技术手册》15.1.3 节真值表,`PxIM1/PxIM0` 的"高电平中断"和"低电平中断"两种模式**都标注为不支持掉电唤醒**,只有下降沿/上升沿两种边沿模式支持。这与本条需求(改成电平触发来解决唤醒不了的问题)在文档上是矛盾的,实现时要先在真机上实测电平触发是否真的能唤醒;如果实测不行,退回到"休眠前强制把 P3IM0/P3IM1 设成固定的某一个边沿方向(比如固定成上升沿),不再依赖乒乓切换留下的随机状态"这个更符合手册说明的方案 - **已实现方案与最初需求不同,供确认**:根据 WO-04 §2.9 查到的《STC32G 技术手册》15.1.3 节真值表,`PxIM1/PxIM0` 的"高电平中断"和"低电平中断"两种模式**都标注为不支持掉电唤醒**,只有下降沿/上升沿两种边沿模式支持。既然手册明确说电平模式不支持掉电唤醒,改成电平触发大概率解决不了"唤醒不了"的问题,所以最终没有采用"改成电平触发",而是实现了手册认可的方案:`App/system.c` 的 `Enter_Low_Power_Sleep()` 里,`P3WKUE |= 0x40;` 之前,`P3IM1`/`P3IM0` 强制固定为上升沿 (`P3IM1&=~0x40; P3IM0|=0x40;`,与 `RF_Init()` 开机初始配置一致),不再依赖乒乓切换留下的随机状态。`Wakeup_Restore()` 不需要改动,因为固定后的值就是开机时的初始值,唤醒后解码状态机自然从已知状态开始
- 具体改法(不管选电平还是固定边沿):在 `App/system.c` 的 `Enter_Low_Power_Sleep()` 里,`P3WKUE |= 0x40;` 之前,加一段显式设置 `P3IM1`/`P3IM0` 的代码,覆盖掉睡前可能残留的任意状态;如果验证后确定要改回边沿触发,`Wakeup_Restore()` 里对应也要把 `P3IM1`/`P3IM0` 重新设回 `RF_Init()` 里的初始方向,保证唤醒后解码状态机从一个已知状态重新开始 - 状态:代码已完成,待实机验证休眠后 P3.6 (RF 信号) 能否稳定唤醒;如果实测仍不能唤醒,再考虑真的去试电平触发(即便手册说不支持)