当前位置: 首页 > backend >正文

独立看门狗(IWDG)

1. IWDG 简介

  • 定义:独立看门狗(Independent Watchdog, IWDG)是一种硬件定时器,主要用来防止系统进入死循环、跑飞等异常状态。

  • 时钟源:内部低速时钟 LSI(典型值 40kHz),不依赖系统主时钟 (HSE/HSE),即使主时钟故障也能工作。

  • 作用

    • MCU 运行过程中必须定期喂狗(刷新计数器),否则计数器溢出将自动复位 MCU

    • 保证系统在异常时自动恢复运行,提高可靠性。

  • 特点

    • 独立于 CPU,不能被软件停止,一旦开启只能通过复位关闭。

    • 适合工业控制、无人值守设备。


2. IWDG 工作原理及框图

工作原理:

  1. IWDG 从 LSI 时钟 (40kHz) 获取时钟输入。

  2. 通过 预分频器 (Prescaler) 进行分频,得到计数时钟。

  3. 计数器 递减计数,当减到 0 → 触发系统复位。

  4. 软件需定期写入 刷新寄存器 (IWDG_KR = 0xAAAA),重新装载计数器,避免复位。

框图(简化版):

     LSI (40kHz)│[预分频器]│[12位递减计数器]│计数到0 → 触发复位

3. IWDG 寄存器及函数介绍

关键寄存器

  1. KR (Key Register, 0x00)

    • 写入 0xCCCC → 启动 IWDG

    • 写入 0xAAAA → 喂狗(刷新计数器)

    • 写入 0x5555 → 允许修改预分频器和重装载寄存器

  2. PR (Prescaler Register, 0x04)

    • 设置预分频系数,取值范围:4, 8, 16, 32, 64, 128, 256

  3. RLR (Reload Register, 0x08)

    • 设置重载值 (0 ~ 0xFFF)

    • 计数器每次刷新后从 RLR 装载,向下递减

  4. SR (Status Register, 0x0C)

    • 标志位:PR/RLR 是否正在更新,防止写入冲突

HAL 库函数

  • HAL_IWDG_Init():初始化并启动 IWDG

  • HAL_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 配置步骤

  1. 开启 LSI 时钟(CubeMX 自动配置,手动时需打开)

  2. 解锁 PR/RLR:写 0x5555 到 KR

  3. 设置预分频器 PR、重载值 RLR

  4. 启动 IWDG:写 0xCCCC 到 KR

  5. 周期性喂狗:写 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);
}

实验现象

  1. 程序启动时

    • 串口打印:

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 上一次复位的原因。


总结

  1. 代码注释:逐行解释了看门狗初始化、喂狗流程。

  2. 实验现象

    • delay_ms < 超时时间 → 程序正常运行。

    • delay_ms > 超时时间 → MCU 会反复复位,并打印“独立看门狗复位”。

  3. 参数说明

    • 预分频器:IWDG_PRESCALER_4 ~ 256

    • 重载值:0 ~ 4095,决定溢出时间。

    • 复位标志:可区分 IWDG、WWDG、外部复位、上电复位、软件复位。

http://www.xdnf.cn/news/18096.html

相关文章:

  • 决策树简单实战
  • 「数据获取」《防城港市统计年鉴》(2014-2020)(获取方式看绑定的资源)
  • 图像分类精度评价的方法——误差矩阵、总体精度、用户精度、生产者精度、Kappa 系数
  • 详细探讨AI在金融、医疗、教育和制造业四大领域的具体落地案例,并通过代码、流程图、Prompt示例和图表等方式展示这些应用的实际效果。
  • 一套GoldenGate → Kafka → Flink → MySQL 的端到端增量同步方案
  • IDE开发系列(1)基于QT的简易IDE框架设计
  • 3D检测笔记:基础坐标系与标注框介绍
  • 深层语义知识图谱:提升NLP文本预处理效果的关键技术
  • 【P18 3-10】OpenCV Python—— 鼠标控制,鼠标回调函数(鼠标移动、按下、。。。),鼠标绘制基本图形(直线、圆、矩形)
  • 在 PyCharm Notebook 中安装 YOLO
  • Jupyter 中实现交互式图表:ipywidgets 从入门到部署
  • 短剧小程序系统开发:推动短剧行业规范化与标准化发展
  • 01数据结构-交换排序
  • AWS Neptune:图数据库的强大潜力
  • Spring AI RAG 检索增强 应用
  • BPO(Business Process Optimization,业务流程优化)
  • 决策树(1)
  • 【领码课堂】AI写码不再“盲跑”,方案先行,自动化高效落地
  • 数据挖掘 3.5 支持向量机——边界和正则化
  • 深度理解分布式事务——强一致分布式事务解决方案
  • linux-高级IO(中)
  • LINUX 818 shell:random;for for
  • ReactNative开发实战——React Native开发环境配置指南
  • VS Code Copilot 完整使用教程(含图解)
  • LeetCode热题100--226. 翻转二叉树--简单
  • 我们为什么需要时序数据库?
  • Docker学习--认识Docker
  • 基于nvm安装管理多个node.js版本切换使用(附上详细安装使用图文教程+nvm命令大全)
  • 视觉语言导航(6)——Speaker-Follower模型 数据增强 混合学习 CLIP 3.1后半段
  • Vision Master的C#脚本与opencv联合编程