一、为什么需要看门狗与低功耗共存?

在工业传感器、智能门锁等电池供电场景中,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 秒),使能闹钟中断,并允许从待机模式唤醒。

五、完整代码示例

/* 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 可以在待机模式下保持“看门狗”监控,同时以极低功耗运行。本文的方案已在多个项目中验证,可有效防止系统死机,并保证周期性巡检任务。开发者可根据实际需求调整唤醒周期和看门狗超时,实现功耗与可靠性的最佳平衡。