> 技术文档 > 【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码

【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码

这篇文章系统总结了 STM32 独立看门狗(IWDG) 的知识,并且我提供了完整的实验示例代码(基于标准库实现)。

为什么要用看门狗?

如果单片机在运行中死机了,此时我们再进行任何操作,单片机都不会再做出响应,这时候只能通过断电让设备重启,设备才能恢复正常。为了解决单片机死机的问题,设计者们给单片机设计了一种叫做 看门狗 的模块,以复位解决单片机死机的问题。

【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码
专业点说,

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog)

简单点说,

在嵌入式系统中,程序有可能由于 干扰、电磁波、堆栈溢出等原因而“跑飞”,导致系统死机或卡死。
看门狗(Watchdog) 就像一个“定时检查的保安”:
① 正常运行时我们“喂狗”;
② 如果程序异常未喂狗 → 看门狗复位MCU → 系统自动重启。

STM32 的两个看门狗

STM32内置两个看门狗,提供了更高的安全性,时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗/窗口看门狗)可以用来检测和解决由软件错误引起的故障。当计数器达到给定的超时值时,触发一个中断(仅适用窗口看门狗)或者产生系统复位。

独立看门狗

独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它仍有效。
独立看门狗适合应用于需要看门狗作为一个在主程序之外 能够完全独立工作,并且对时间精度要求低的场合。

窗口看门狗

窗口看门狗由从APB1时钟分频后得到时钟驱动。通过可配置的时间窗口来检测应用程序非正常的过迟或过早操作。
窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。

看门狗类型 时钟来源 特点 适用场景 独立看门狗(IWDG) LSI(40kHz) 与主系统无关,掉电也能工作 更稳定、更安全 窗口看门狗(WWDG) APB1时钟 可设“喂狗窗口”,时间控制精细 定时要求严格

独立看门狗(IWDG)关键特性

独立看门狗功能描述

① 在键值寄存器(IWDG_KR)中写入 0xCCCC,开始启用独立看门狗。此时计数器开始从其复位值0xFFF递减,当计数器值计数到尾值0x000时会产生一个复位信号(IWDG_RESET)。
② 无论何时,只要在键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗), 自动重装载寄存器IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。
③ 如果程序异常,就无法正常喂狗,从而系统复位。

【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码

键值寄存器IWDG_KR: 0~15位有效预分频寄存器IWDG_PR:0~2位有效。--- 具有写保护功能,要操作先取消写保护重装载寄存器IWDG_RLR:0~11位有效。--- 具有写保护功能,要操作先取消写保护。状态寄存器IWDG_SR:0~1位有效

常用寄存器和对应库函数:

寄存器 作用 库函数 IWDG_KR 控制入口(写0x5555取消保护,0xAAAA喂狗,0xCCCC启动 IWDG_WriteAccessCmd()IWDG_Enable()IWDG_ReloadCounter() IWDG_PR 设置预分频值(0~7) IWDG_SetPrescaler() IWDG_RLR 设置计数器初始值(0~0xFFF) IWDG_SetReload() IWDG_SR 状态寄存器,判断是否写入完成 IWDG_GetFlagStatus()

【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码


【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码


【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码


【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码

独立看门狗(IWDG)超时时间

时钟来源:内部 LSI 40kHz
启动后不可关闭(除非复位)
有写保护,修改前需取消写保护

【STM32】独立看门狗(提供完整实例代码)_看门狗驱动代码

溢出时间计算:

Tout = ((4×2^prer) ×rlr) /40 (M3)

时钟频率 LSI=40K, 一个看门狗时钟周期就是最短超时时间。
最长超时时间 = (IWDG_RLR寄存器最大值)X看门狗时钟周期

IWDG独立看门狗操作库函数

void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);//取消写保护:0x5555使能void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//设置预分频系数:写PRvoid IWDG_SetReload(uint16_t Reload);//设置重装载值:写RLRvoid IWDG_ReloadCounter(void);//喂狗:写0xAAAA到KRvoid IWDG_Enable(void);//使能看门狗:写0xCCCC到KRFlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);//状态:重装载/预分频 更新
独立看门狗初始化步骤

① 取消寄存器写保护:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

② 设置独立看门狗的预分频系数,确定时钟:(如:256)
IWDG_SetPrescaler(IWDG_Prescaler_256);

③ 设置看门狗重装载值,确定溢出时间:(最大0xFFF):
IWDG_SetReload(0x0FFF);

④ 使能看门狗(等待寄存器更新完成):
while(IWDG_GetFlagStatus(...) == SET);

⑤ 应用程序喂狗:
IWDG_ReloadCounter();

⑥ 启动看门狗:
IWDG_Enable();


溢出时间计算:
Tout=((4×2^prer) ×rlr) /40 (M3)

实验完整代码(标准库实现)

  • 设置 IWDG 超时时间为约 5 秒
  • 程序中定时喂狗,避免复位
  • 如果人为注释掉喂狗 → 系统将在 5 秒后自动复位
#include \"stm32f10x.h\"// 延时函数(粗略估算用)void Delay(uint32_t time){ while(time--);}// 看门狗初始化函数(超时时间约5秒)void IWDG_Init(void){ // ① 允许写访问 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); // ② 设置预分频值:256 IWDG_SetPrescaler(IWDG_Prescaler_256); // 40kHz ÷ 256 = 156.25Hz // ③ 设置重装载值:0x0FFF(4095) IWDG_SetReload(0x0FFF); // 最大值 // ④ 等待更新完成 while(IWDG_GetFlagStatus(IWDG_FLAG_PVU) != RESET); // 等待预分频更新完成 while(IWDG_GetFlagStatus(IWDG_FLAG_RVU) != RESET); // 等待重装载更新完成 // ⑤ 喂狗一次 IWDG_ReloadCounter(); // ⑥ 启动看门狗 IWDG_Enable();}int main(void){ // 可加LED初始化等调试 IWDG_Init(); // 初始化看门狗 while(1) { // 模拟正常程序,每隔一段时间喂狗 Delay(5000000); // 粗略延时 IWDG_ReloadCounter(); // 喂狗 // 注释掉这一句试试看系统是否会复位 // IWDG_ReloadCounter(); }}

运行效果:正常运行并喂狗 —> 程序持续运行,不复位;注释掉喂狗函数 —> 系统约 5 秒后复位,重新执行 main()

超时时间计算方法:(使用上面参数)

  • PR = 256,对应 IWDG_Prescaler_256
  • RL = 0x0FFF = 4095
Tout = ((4 × 2^7) × 4095) / 40 = (512 × 4095) / 40 = 2097152 / 4052428 ms ≈ 5.24 s

因篇幅有限,这里单独开一篇文章来介绍 看门狗模块 中的关键步骤:弄清楚 超时时间计算 的核心原理 —> 预分频因子(Prescaler)和重装载值(Reload Value)

总结,因为在 Keil 软件中,函数设计是模块划分的(代码整理):

wdg.c

#include \"wdg.h\"// Tout=((4×2^prer) ×rlr) /40 (M3)// prer:分频因子,值范围 0~7// rlr:重装载值 最大值 2^12 - 1 = 4095// 假如喂狗时间设置为 0.5s = ((4×2^prer) ×rlr) /40// prer 预设值为 2 // 最后算出 rlr void IWDG_Init(uint8_t IWDG_Prescaler,uint16_t Reload){IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消写保护,允许写操作IWDG->KR = 0x5555;IWDG_SetPrescaler( IWDG_Prescaler );//设置预分频值IWDG_SetReload( Reload );//设置重装载值IWDG_ReloadCounter();//喂狗IWDG_Enable();//使能看门狗}

wdg.h

#ifndef _IWDG_H_#define _IWDG_H_#include \"stm32f10x.h\"#include void IWDG_Init(uint8_t IWDG_Prescaler,uint16_t Reload);#endif

main.c

/** ****************************************************************************** * @file Project/STM32F10x_StdPeriph_Template/main.c * @author MCD Application Team * @version V3.5.0 * @date 08-April-2011 * @brief Main program body ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * * 

© COPYRIGHT 2011 STMicroelectronics

****************************************************************************** */
/* Includes ------------------------------------------------------------------*/#include \"stm32f10x.h\"#include \"stdio.h\"#include \"gpio.h\"#include \"systick.h\"#include \"exti.h\"#include \"usart.h\"#include \"string.h\"#include \"wdg.h\"uint8_t SendData [] = {\"你好,世界 \\r\\n\"};int main(){int IWDG_Count = 0;int i = 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断使用分组2MX_GPIO_Init();delay_Init();//Systick_Initerupt_Init();MX_EXTI0_Init();MX_USART1_Init(115200);USART1_NVIC_Init(1,1);GPIO_WriteBit(GPIOC, GPIO_Pin_7 , Bit_RESET);delay_ms(500);IWDG_Init( 2 , 1250);//预分频因子系数 2 对应预分频系数 16看门狗当前复位时间为500msGPIO_WriteBit(GPIOC, GPIO_Pin_7 , Bit_SET);while(1){if(GPIO_ReadInputDataBit( GPIOA, GPIO_Pin_0) == Bit_RESET){IWDG_Count ++;IWDG_ReloadCounter();//喂狗printf(\"IWDG_Count = %d \\r\\n\", IWDG_Count);}}}/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

总而言之,独立看门狗是一个可靠的 “程序异常自恢复机制”,非常适合用于工业、无人值守等关键场景,提高系统运行的稳定性。

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!