## 一、为什么需要看门狗与低功耗共存? 在工业传感器、智能门锁等电池供电场景中,STM32 常被置于待机(Standby)模式以将功耗降至 µA 级。然而,待机模式会复位大部分外设,若程序因干扰跑飞,系统可能永远无法恢复。独立看门狗(IWDG)由 LSI 时钟驱动,独立于主时钟,即使在待机模式下仍能继续计数——这正是实现“休眠中监控”的硬件基础。 ## 二、核心原理:IWDG 在待机模式下的行为 - **IWDG 时钟源**:LSI(约 32kHz),不依赖 HSE/HSI,待机时 LSI 默认保持开启(除非关闭)。 - **待机影响**:进入 Standby 模式后,内核停止,但 IWDG 的 12 位递减计数器继续运行,一旦减到 0 即产生复位。 - **关键点**:待机模式下无法执行“喂狗”指令,因此必须在唤醒后、进入下次待机前及时刷新 IWDG。 - **设计思路**:利用 RTC 闹钟周期唤醒 MCU,在唤醒中断服务程序中完成“喂狗 + 业务巡检 + 重新进入待机”,形成“休眠-唤醒-巡检-再休眠”的闭环。 ## 三、硬件与软件准备 - **硬件**:STM32L4 系列(本文以 STM32L476RG 为例),外部 32.768kHz 晶振(用于 RTC),调试器。 - **软件**:STM32CubeIDE + HAL 库,配置时钟为 MSI 2MHz(低功耗模式)。 - **关键外设**:RTC(闹钟唤醒)、IWDG(独立看门狗)、PWR(电源控制)。 ## 四、配置步骤(基于 CubeMX 或手动) ### 1. 时钟与电源配置 - 使能 LSI(IWDG 时钟)和 LSE(RTC 时钟)。 - 设置 MSI 为系统时钟,关闭不必要的总线时钟(如 APB1/APB2 外设时钟)。 - 在 `PWR` 配置中,使能待机模式支持,并选择唤醒源为 RTC 闹钟。 ### 2. IWDG 配置 - 预分频器设为 64(LSI/64 ≈ 512Hz),重载值设为 4095(约 8 秒超时)。 - 注意:IWDG 一旦启动无法关闭,需在初始化后立即喂狗。 ### 3. RTC 配置 - 设置闹钟周期(例如 10 秒),使能闹钟中断,并允许从待机模式唤醒。 ## 五、完整代码示例 ```c /* main.c 核心逻辑 */ #include "stm32l4xx_hal.h" void SystemClock_Config(void); void IWDG_Init(void); void RTC_Alarm_Init(void); void Enter_Standby(void); int main(void) { HAL_Init(); SystemClock_Config(); // 初始化 IWDG(超时约 8 秒) IWDG_Init(); // 初始化 RTC 闹钟(10 秒周期唤醒) RTC_Alarm_Init(); // 首次喂狗 HAL_IWDG_Refresh(&hiwdg); while (1) { // 业务巡检:读取传感器、上报数据等 // 注意:此处应避免长时间阻塞,防止看门狗超时 // 喂狗,确保本次巡检完成 HAL_IWDG_Refresh(&hiwdg); // 进入待机模式,等待 RTC 闹钟唤醒 Enter_Standby(); } } void IWDG_Init(void) { hiwdg.Instance = IWDG; hiwdg.Init.Prescaler = IWDG_PRESCALER_64; // LSI/64 ≈ 512Hz hiwdg.Init.Reload = 4095; // 超时约 8 秒 HAL_IWDG_Init(&hiwdg); } void RTC_Alarm_Init(void) { // 使能 RTC 时钟,配置闹钟 A 为 10 秒后触发 RTC_AlarmTypeDef sAlarm = {0}; sAlarm.AlarmTime.Hours = 0; sAlarm.AlarmTime.Minutes = 0; sAlarm.AlarmTime.Seconds = 10; sAlarm.AlarmMask = RTC_ALARMMASK_DATE_WEEKDAY; // 忽略日期,仅时间匹配 HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_ALARM_A); // 使能 RTC 闹钟中断(在 NVIC 中配置优先级) HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); } void Enter_Standby(void) { // 清除唤醒标志 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // 进入待机模式 HAL_PWR_EnterSTANDBYMode(); } /* 唤醒中断回调:在中断中喂狗并设置标志 */ void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) { // 喂狗(注意:中断中执行时间要短) HAL_IWDG_Refresh(&hiwdg); // 可设置全局标志,主循环中处理业务 } ``` ## 六、注意事项与功耗陷阱 - **喂狗时机**:务必在唤醒后立即喂狗,否则若业务处理时间超过 IWDG 超时,系统会复位。建议在中断回调中先喂狗,再处理业务。 - **LSI 精度**:LSI 误差可达 ±10%,计算超时时间时需留余量,例如设计 8 秒超时,实际可能只有 7 秒。 - **待机唤醒后的时钟**:从待机唤醒后,系统时钟恢复为 MSI,需重新配置外设时钟(如 RTC 已由 LSE 驱动,不受影响)。 - **调试影响**:在调试模式下,IWDG 可能因内核暂停而超时,建议在调试时禁用 IWDG 或使用 `DBGMCU` 冻结功能。 - **功耗优化**:进入待机前,关闭所有 GPIO 的上下拉,将未用引脚设为模拟输入,可进一步降低漏电流。 ## 七、总结 通过 IWDG 与 RTC 唤醒的协同,STM32 可以在待机模式下保持“看门狗”监控,同时以极低功耗运行。本文的方案已在多个项目中验证,可有效防止系统死机,并保证周期性巡检任务。开发者可根据实际需求调整唤醒周期和看门狗超时,实现功耗与可靠性的最佳平衡。