独立看门狗IWDG

Tutorial: 电子电路 Category: 嵌入式 Published: 2026-10-08 01:26:37 Views: 1 Likes: 0 Comments: 0

156.9独立看门狗IWDG

/*
 * 整体目的:启动 STM32F103 的独立看门狗,并用 KEY0 决定是否持续刷新;松开按键后
 *           倒计时到零触发系统复位,复位后 LED0 再闪烁 500 ms 作为可见现象。
 * 设计思路:LSI 经 64 分频驱动 12 位递减计数器,Reload=3125;主循环仅在 KEY0
 *           读到低电平时喂狗,刷新会把重装载值重新装入计数器,而不是把它清零。
 * 硬件依据:工程把 LED0 定义在 PB5、KEY0 定义在 PE4;LED0 低电平点亮,KEY0
 *           低电平有效且 GPIO 配置为无内部上下拉,因此按键稳定性依赖板级外部电路。
 * 时间依据:按标称 40 kHz LSI,超时约为 (3125+1)*64/40000=5.0016 s;LSI 实际
 *           可能约为 30~60 kHz,不能把课堂现象当作精确 5 秒计时器。
 * 执行效果:按住 KEY0 时循环反复刷新而不复位;松开约一个超时周期后 IWDG 复位 MCU,
 *           程序重新初始化并让低电平有效的 LED0 再亮约 500 ms。
 * 代码范围:摘录 CubeIDE/15IWDG 的 iwdg.c、main.c 与时钟关键代码,不展开 HAL 内部。
 */

/* Core/Src/iwdg.c:配套工程的实际 IWDG 配置。 */
IWDG_HandleTypeDef hiwdg;                 /* 定义全工程使用的独立看门狗 HAL 句柄。 */

void MX_IWDG_Init(void)                   /* 配置并启动 IWDG;启动后只能通过系统复位停止。 */
{                                          /* IWDG 初始化函数体开始。 */
    hiwdg.Instance = IWDG;                /* 将句柄绑定到芯片内部独立看门狗。 */
    hiwdg.Init.Prescaler =                /* 选择 LSI 到 IWDG 计数器之间的预分频系数。 */
        IWDG_PRESCALER_64;                /* 将标称 40 kHz 除以 64,得到约 625 Hz 计数频率。 */
    hiwdg.Init.Reload = 3125U;            /* 设置 12 位重装载值;3125 到 0 共经历 3126 个计数。 */
    if (HAL_IWDG_Init(&hiwdg) != HAL_OK)  /* 写入参数、启动并首次装载计数器,随后检查结果。 */
    {                                      /* IWDG 初始化失败分支开始。 */
        Error_Handler();                  /* 进入工程统一错误处理;不要继续假定看门狗有效。 */
    }                                      /* IWDG 初始化状态判断结束。 */
}                                          /* IWDG 初始化函数结束,看门狗已经开始倒计时。 */

/* main.c:IWDG 启动后,只有低电平有效的 KEY0 才持续刷新计数器。 */
MX_GPIO_Init();                            /* 先配置 PB5/LED0 与 PE4/KEY0,确保实验引脚状态明确。 */
MX_IWDG_Init();                            /* 启动独立看门狗;后续所有阻塞路径都必须短于超时上限。 */

HAL_GPIO_WritePin(                        /* 建立复位后可观察的 LED0 点亮状态。 */
    LED0_GPIO_Port,                        /* 选择 LED0 所在的 GPIOB。 */
    LED0_Pin,                              /* 选择 PB5 对应的 LED0 位。 */
    GPIO_PIN_RESET);                       /* 输出低电平;本板 LED0 低电平点亮。 */
HAL_Delay(500U);                          /* 保持点亮约 500 ms,使每次复位都能被肉眼观察。 */
HAL_GPIO_WritePin(                        /* 结束上电或复位后的 LED 指示脉冲。 */
    LED0_GPIO_Port,                        /* 仍操作 LED0 所在 GPIOB。 */
    LED0_Pin,                              /* 仍只改变 PB5,不影响同端口其他引脚。 */
    GPIO_PIN_SET);                         /* 输出高电平,让低电平有效的 LED0 熄灭。 */

while (1)                                  /* 前台永久检查按键状态,等待喂狗或复位。 */
{                                          /* 主循环一轮开始。 */
    if (HAL_GPIO_ReadPin(                  /* 读取 KEY0 当前逻辑电平。 */
            KEY0_GPIO_Port,                /* 选择 KEY0 所在的 GPIOE。 */
            KEY0_Pin) == GPIO_PIN_RESET)  /* PE4 为低表示按键有效;依赖板上的外部上拉。 */
    {                                      /* KEY0 有效时进入刷新分支。 */
        HAL_IWDG_Refresh(&hiwdg);          /* 把 Reload 重新装入递减计数器,推迟复位。 */
    }                                      /* KEY0 无效时不刷新,让计数器继续减至 0。 */
}                                          /* 返回循环顶部;若已超时,硬件复位会中断该流程。 */

/* SystemClock_Config():实际同时选择 HSE 系统时钟源和 IWDG 所需的 LSI。 */
RCC_OscInitStruct.OscillatorType =         /* 声明本次需要配置的两个振荡器。 */
    RCC_OSCILLATORTYPE_LSI |              /* 选择片内低速 RC,作为 IWDG 的独立时钟。 */
    RCC_OSCILLATORTYPE_HSE;               /* 同时选择外部高速晶体,供系统主时钟链使用。 */
RCC_OscInitStruct.LSIState = RCC_LSI_ON;  /* 明确启动 LSI,使 IWDG 在主时钟异常时仍能计数。 */

一、看门狗

看门狗的目的不是让程序“永不出错”,而是在软件没有按预期完成健康检查时把 MCU 拉回可控的复位起点。独立看门狗(IWDG)由片内低速内部 RC 振荡器 LSI 驱动,主系统时钟异常时仍可运行,因此特别适合处理死循环、任务卡死等故障。

原稿的“从 0 数到 100、到期产生复位中断”只是教学类比。STM32F1 的 IWDG 实际从重装载值向下计数至 0x000,随后产生的是硬件复位信号,而非进入可由用户编写 IWDG_IRQHandler 处理的普通中断。喂狗也不是把计数器写成零,而是把 IWDG_RLR 的重装载值重新装入计数器,使倒计时重新开始。

项目STM32F1 IWDG 的实际含义
时钟源片内 LSI RC,数据手册标称 40 kHz,范围约 30--60 kHz
计数方向从重装载值递减,到 0x000 产生 IWDG 复位
计数器宽度12 位,重装载值范围为 0--4095
启动后状态软件或选项字节均可启动;一旦启动,除系统复位外不能关闭
喂狗动作HAL_IWDG_Refresh() 向键寄存器写入刷新键,将 Reload 装回计数器

超时近似公式为:

T_timeout = (Reload + 1) x Prescaler / f_LSI

这里的 +1 来自计数器从重装载值递减到零所经历的计数周期数。这个公式用于估算和选型;LSI 是 RC 振荡器,不能把标称频率误认为精密时基。

1.1 实验演示喂狗

  • 配套工程先初始化 GPIO,再执行 MX_IWDG_Init()。HAL_IWDG_Init() 会启动 IWDG、开放配置写入、写入预分频与重装载值,并在返回前刷新一次计数器;看门狗从这里开始计时。
  • 板级信号在 main.h 中定义为 LED0 = PB5、KEY0 = PE4。GPIO 配置中 PB5 为推挽输出,PE4 为普通输入,均未启用片内上下拉。
  • 初始化代码向 PB5 写低电平、延时 500 ms、再写高电平。课程现象中的“上电或复位时灯闪一下”来自这三行;它还表明该板 LED 是低电平点亮。这只描述此板连接方式,其他板的 LED 可能相反。
  • HAL_GPIO_ReadPin(PE4) 返回低电平时才执行刷新。若 PE4 的按键电路确为“按下接地、松开由外部电阻上拉”,按住按键会在高速循环中反复喂狗;松开后约一个超时时间发生复位,随后再次执行 500 ms 闪灯。
  • 由于代码把 PE4 配成 GPIO_NOPULL,低电平有效依赖开发板已有的外部上拉和按键接地电路。工程中没有原理图,接线和电阻不能凭空假定;若改接自制按键,必须提供确定的上拉或下拉,悬空输入会随机读到 0/1。
  • 该按键方案仅用于可见的课堂实验。产品中不应把“用户按着一个键”当作系统健康证明;应在所有关键任务都按时完成之后,才由集中位置刷新看门狗。否则程序即使卡在一个仍会执行 HAL_IWDG_Refresh() 的错误循环里,也不会被复位。

1.2 窗口看门狗

独立看门狗只要求“在到期前刷新”,没有规定过早刷新会出错。窗口看门狗(WWDG)额外限定了允许刷新的时间窗,因此既能发现程序太久不运行,也能发现程序异常地跑得过快、过早刷新。

  • 原稿以“从 0 向 100 上数”的示意说明窗口,这可用于直觉理解,但不是 STM32F1 WWDG 的寄存器计数方向。
  • STM32F1 的 WWDG 使用 PCLK1 派生时钟并向下计数:计数器尚高于设定窗口值时刷新,属于过早刷新,会导致复位;当计数器继续递减到 0x3F 以下时,也会复位。正确窗口是计数值已降至窗口值及以下、但仍高于下溢复位阈值的时段。
  • WWDG 与 IWDG 的取舍:WWDG 的时钟依赖主时钟,窗口检测能力更强;IWDG 的 LSI 与主时钟独立,更适合主时钟失效或主程序整体卡死的恢复。两者都不是外部独立供电的监控芯片。

1.3 看门狗芯片

外部看门狗/复位监控芯片是 MCU 之外的独立器件。典型连接是 MCU 周期性翻转或脉冲驱动芯片的 WDI 输入,芯片的复位输出连接 MCU 的 NRST 或复位网络;在规定时间内没有有效边沿或电平变化时,芯片主动复位 MCU。

  • 外部芯片的 WDI 触发方式、允许时间窗、复位输出极性与供电范围由具体型号决定,不能笼统认定“高电平、低电平或任意脉冲都可以”。
  • 当内部时钟、片内看门狗配置或 MCU 自身状态不够可信时,外部监控能提供另一条监督链路;但它同样依赖正确的复位连接、供电设计和固件喂狗策略,不能替代电源完整性设计。
  • 本节 15IWDG 工程只使用 STM32 内部 IWDG,没有外置看门狗芯片的 GPIO 或原理图配置。

1.4 实验演示喂狗

  • 该工程配置 IWDG_PRESCALER_64、Reload = 3125。按标称 LSI 40 kHz 计算,分频后为 40 000 / 64 = 625 Hz,超时约为 (3125 + 1) / 625 = 5.0016 s。原稿的“3125 对应正好 5 秒”忽略了一个计数周期,只能视作近似。
  • 更重要的是 LSI 的数据手册范围约为 30--60 kHz。同一配置的理论超时约在 3.334--6.669 s 之间,温度和电压也会影响 RC 频率。需要严格 5 秒的设计,应测量 LSI 并留出任务调度余量,或选用更适合的外部时基/监控方案。
  • IWDG 没有 GPIO 输出脚,也不需要在 NVIC 中启用中断。LED 和按键是为了观察复位及决定是否刷新而添加的外围电路;IWDG 本身完全在芯片内部运行。
  • 每次 IWDG 复位后,RCC 的 IWDGRSTF 复位标志会被置位。当前示例没有读取该标志,所以只能从 LED 闪烁推测复位原因。实际调试应在启动早期记录复位标志,再按芯片手册清除,区分上电、外部复位、软件复位和 IWDG 复位。
  • 调试暂停时,IWDG 可能继续倒计时并导致程序在断点处复位。F1 HAL 提供冻结/解冻 IWDG 的调试宏;它适合临时调试,不应被当作生产环境的失效保护策略。

二、总结

  • IWDG 的核心链路是:LSI 时钟 -> 预分频 -> 12 位递减计数器 -> 到零产生系统复位。喂狗是把重装载值重新写入计数器,而不是清零。
  • 本工程的参数是 40 kHz / 64 = 625 Hz(标称),Reload = 3125,故标称超时约 5 秒;严格公式应使用 (Reload + 1),并必须考虑 LSI 的频率误差。
  • 启动 IWDG 后不能靠普通代码将其关闭,只能通过系统复位重新开始。因此初始化顺序、最长阻塞时间和任务健康判据要在启用前设计好。
  • IWDG 是故障恢复的最后一道措施,不是正确程序逻辑的替代品。要把刷新放在真正证明系统健康的位置,并在启动时记录复位原因,才能让看门狗既能复位,也能帮助定位故障。