独立看门狗(IWDG)
1. IWDG 简介
定义:独立看门狗(Independent Watchdog, IWDG)是一种硬件定时器,主要用来防止系统进入死循环、跑飞等异常状态。
时钟源:内部低速时钟 LSI(典型值 40kHz),不依赖系统主时钟 (HSE/HSE),即使主时钟故障也能工作。
作用:
MCU 运行过程中必须定期喂狗(刷新计数器),否则计数器溢出将自动复位 MCU。
保证系统在异常时自动恢复运行,提高可靠性。
特点:
独立于 CPU,不能被软件停止,一旦开启只能通过复位关闭。
适合工业控制、无人值守设备。
2. IWDG 工作原理及框图
工作原理:
IWDG 从 LSI 时钟 (40kHz) 获取时钟输入。
通过 预分频器 (Prescaler) 进行分频,得到计数时钟。
计数器 递减计数,当减到 0 → 触发系统复位。
软件需定期写入 刷新寄存器 (IWDG_KR = 0xAAAA),重新装载计数器,避免复位。
框图(简化版):
LSI (40kHz)│[预分频器]│[12位递减计数器]│计数到0 → 触发复位
3. IWDG 寄存器及函数介绍
关键寄存器
KR (Key Register, 0x00)
写入
0xCCCC
→ 启动 IWDG写入
0xAAAA
→ 喂狗(刷新计数器)写入
0x5555
→ 允许修改预分频器和重装载寄存器
PR (Prescaler Register, 0x04)
设置预分频系数,取值范围:
4, 8, 16, 32, 64, 128, 256
RLR (Reload Register, 0x08)
设置重载值 (0 ~ 0xFFF)
计数器每次刷新后从 RLR 装载,向下递减
SR (Status Register, 0x0C)
标志位:PR/RLR 是否正在更新,防止写入冲突
HAL 库函数
HAL_IWDG_Init()
:初始化并启动 IWDGHAL_IWDG_Refresh()
:喂狗,刷新计数器__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)
:判断是否 IWDG 复位__HAL_RCC_CLEAR_RESET_FLAGS()
:清除复位标志
4. IWDG 溢出时间计算
公式:
RLR
:重载值 (0 ~ 4095)Prescaler
:分频系数 (4,8,16,32,64,128,256)LSI_Freq
:LSI 时钟频率 (典型值 40kHz)
例子(你代码里的参数):
psc = 32,RLR = 1250
这意味着:如果 1s 内没有喂狗 → MCU 会复位。
5. IWDG 配置步骤
开启 LSI 时钟(CubeMX 自动配置,手动时需打开)
解锁 PR/RLR:写
0x5555
到 KR设置预分频器 PR、重载值 RLR
启动 IWDG:写
0xCCCC
到 KR周期性喂狗:写
0xAAAA
到 KR
补充知识点
复位标志判断:通过
RCC_FLAG_IWDGRST
区分是否由 IWDG 复位。与窗口看门狗 (WWDG) 区别:
IWDG 独立时钟,无法停止;WWDG 用主时钟,复位前可产生中断。
典型应用:无人值守设备(采集器、传感器节点、逆变器控制器、工业控制器)。
总结一句话:
独立看门狗 (IWDG) = “硬件定时器 + 强制复位”,定期喂狗保证程序正常运行,否则 MCU 自动复位。
STM32F103 独立看门狗 (IWDG) 实验
main.c
#include "sys.h" // 系统时钟初始化相关函数
#include "delay.h" // 延时函数(ms、us)
#include "led.h" // LED 控制函数
#include "uart1.h" // 串口1初始化与收发
#include "iwdg.h" // 独立看门狗 IWDG 驱动int main(void)
{HAL_Init(); /* 初始化 HAL 库:包括 NVIC 分组、SysTick 配置等 */stm32_clock_init(RCC_PLL_MUL9); /* 系统时钟设置为 72MHz (HSE=8MHz, PLL*9) */led_init(); /* 初始化板载 LED */uart1_init(115200); /* 初始化串口1,波特率 115200 *//* 初始化独立看门狗 IWDG* 参数1 Prescaler:预分频器,取值 IWDG_PRESCALER_x* 参数2 Reload:重载值,计数到0则触发复位* 本例:psc=32,rlr=1250* 时钟源固定为 LSI = 40kHz (典型值)* IWDG 超时时间 = (Reload+1) * Prescaler / 40kHz* = (1250+1) * 32 / 40000 ≈ 1.0 s*/iwdg_init(IWDG_PRESCALER_32, 1250);printf("hello world!\r\n");printf("狗儿肚子饿了,再不喂它的话就咬人了!\r\n");/* 判断复位原因:是否由独立看门狗触发 */if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) // 读取 RCC 寄存器复位标志{printf("独立看门狗复位!\r\n");__HAL_RCC_CLEAR_RESET_FLAGS(); // 清除复位标志,防止下次开机误判}elseprintf("外部复位!\r\n"); // 若不是IWDG复位,则说明是上电/手动复位while(1){ delay_ms(1500); // 延时 1500ms (> 1s 看门狗溢出时间)iwdg_feed(); // 喂狗(刷新计数器,防止复位)printf("狗儿已经喂饱了,不会咬人了!\r\n");}
}
iwdg.c
#include "iwdg.h"IWDG_HandleTypeDef iwdg_handle = {0}; // 定义 IWDG 句柄,全局变量/* 独立看门狗初始化* 参数 psc:预分频器 (IWDG_PRESCALER_x)* 参数 rlr:重载值 (0~0xFFF)*/
void iwdg_init(uint8_t psc, uint16_t rlr)
{iwdg_handle.Instance = IWDG; // 指定硬件实例为 IWDG 外设iwdg_handle.Init.Prescaler = psc; // 设置预分频器 (2,4,8,16,32,64,128,256)iwdg_handle.Init.Reload = rlr; // 设置重载值 (0~4095)HAL_IWDG_Init(&iwdg_handle); // 调用 HAL 库函数,写入寄存器并启动看门狗
}/* 喂狗函数* 功能:刷新计数器,防止看门狗复位* 本质:往 IWDG_KR 寄存器写入 0xAAAA*/
void iwdg_feed(void)
{HAL_IWDG_Refresh(&iwdg_handle);
}
实验现象
程序启动时
串口打印:
hello world!
狗儿肚子饿了,再不喂它的话就咬人了!
外部复位!
LED 初始化完成(如点亮/熄灭,看 led_init() 定义)。
进入 while(1) 循环
延时 1500 ms,超过 IWDG 超时时间 (~1s)。
但在延时结束后才喂狗。
结果
在大多数情况下,看门狗会在 1s 左右复位 MCU,根本来不及执行
iwdg_feed()
。复位后再次启动,程序会检测到
RCC_FLAG_IWDGRST
,于是串口打印:
独立看门狗复位!
如果把 delay_ms(1500)
改小于 1000ms(比如 500ms),则能正常喂狗,程序不会复位,每 1.5s 打印:
狗儿已经喂饱了,不会咬人了!
所以现象分两种:
延时 < 超时时间 → 程序一直运行,循环打印“狗儿已经喂饱了”。
延时 > 超时时间 → 程序不断复位,循环打印“独立看门狗复位”。
参数的可选项
A. iwdg_handle.Init.Prescaler
HAL 库定义的宏:
IWDG_PRESCALER_4
IWDG_PRESCALER_8
IWDG_PRESCALER_16
IWDG_PRESCALER_32
IWDG_PRESCALER_64
IWDG_PRESCALER_128
IWDG_PRESCALER_256
作用:决定 IWDG 时钟分频系数(基于 LSI ~40kHz)。
B. iwdg_handle.Init.Reload
取值范围:
0x000 ~ 0xFFF
(即 0 ~ 4095)。重载寄存器值,计数到 0 时触发复位。
超时时间公式:
例:
psc = 32, rlr = 1250 → 超时时间 ≈ 1.0 s
psc = 64, rlr = 4000 → 超时时间 ≈ 6.4 s
C. __HAL_RCC_GET_FLAG()
可选标志(对应STM32中文参考手册V10)
RCC_FLAG_IWDGRST
→ 独立看门狗复位RCC_FLAG_WWDGRST
→ 窗口看门狗复位RCC_FLAG_PINRST
→ 外部复位 (NRST 引脚)RCC_FLAG_PORRST
→ 上电复位RCC_FLAG_SFTRST
→ 软件复位(写 AIRCR 寄存器触发)
用于判断 MCU 上一次复位的原因。
总结
代码注释:逐行解释了看门狗初始化、喂狗流程。
实验现象:
delay_ms < 超时时间
→ 程序正常运行。delay_ms > 超时时间
→ MCU 会反复复位,并打印“独立看门狗复位”。
参数说明:
预分频器:
IWDG_PRESCALER_4 ~ 256
。重载值:
0 ~ 4095
,决定溢出时间。复位标志:可区分 IWDG、WWDG、外部复位、上电复位、软件复位。