STM32F103独立看门狗(IWDG)完全指南:从原理到实战,再也不怕程序“跑飞”
关键词: STM32F103,独立看门狗,IWDG, 嵌入式教程,看门狗原理,喂狗,复位机制,单片机死机,STM32开发,标准库
本文深入讲解STM32F103独立看门狗(IWDG)的工作原理、寄存器配置与计算方法,并基于标准库提供完整代码实战。教你如何用IWDG防止程序跑飞,提升系统稳定性,内含避坑指南与调试技巧。
在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,发生不可预料的后果。在嵌入式开发中,没有什么比在现场设备突然死机更让人头疼的了。无论是工业控制器还是智能家居设备,一旦程序陷入死循环,如果没有有效的监控机制,设备就会“罢工”,甚至引发安全事故。
而 “看门狗” 就是解决这一问题的“保安”。在系统跑飞(程序异常执行)的情况,系统复位,让程序重新执行。本文将带你深入浅出了解STM32F103中的独立看门狗(IWDG),并通过实战代码演示如何让它为你的程序保驾护航。
一、 什么是独立看门狗?为什么需要它?
看门狗定时器(Watchdog Timer)本质上是一个硬件计时器,它的作用就是监控系统的运行状态。在STM32F103中,内置了两个看门狗:独立看门狗(IWDG)和窗口看门狗(WWDG)。可以用来检测和解决由软件错误引起的故障。
- 独立看门狗(IWDG)之所以叫“独立”,是因为它由专用的低速时钟(LSI)驱动,即使主时钟发生故障,它依然能工作。独立看门狗适合应用于需要看门狗作为一个在主程序之外 能够完全独立工作,并且对时间精度要求低的场合。
- 窗口看门狗由从APB1时钟分频后得到时钟驱动。通过可配置的时间窗口来检测应用程序非正常的过迟或过早操作。 窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。
本文的主角是 “独立看门狗” ,江湖人称 “宠物狗”。
独立看门狗它的工作原理非常简单粗暴:
- 它是一个12位的递减计数器。
- 它从设定的初值开始不断往下减,减到0时,就会强制给单片机发送一个复位信号,让程序从头开始运行。
- 正常的程序应该在计数器减到0之前,定期去“重置”这个计数器,这就是我们俗称的 “喂狗”。
如果你的程序因为某种干扰(如静电、电源波动)跑飞了或者陷入了死循环,导致无法按时“喂狗”,看门狗就会毫不留情地重启单片机,让系统恢复运行。
二、 IWDG的核心原理剖析
要熟练使用IWDG,我们得先看看它内部是怎么组成的。下图(需参考手册)展示了IWDG的功能框图,核心围绕几个关键的寄存器展开。
1. 时钟源:LSI
IWDG使用的是内部低速时钟(LSI),频率大约是40kHz。需要注意的是,RC振荡器的精度不高,会随着温度电压漂移(通常在30kHz~60kHz之间),所以IWDG不适合对时间精度要求极高的场合。
2. 三大关键寄存器
操作IWDG,其实就是操作以下三个寄存器,而它们都由一个“钥匙”寄存器(IWDG_KR)来控制:
键寄存器 (IWDG_KR):0~15位有效。这是控制中心。在程序中写入特定的值,会产生不同效果:
- 0xCCCC:启动看门狗。一旦启动,除非复位,否则无法关闭。
- 0x5555:允许访问预分频寄存器(PR)和重装载寄存器(RLR)。要配置时间,必须先写这个值解锁。
- 0xAAAA:喂狗。将RLR的值重新加载到计数器,防止复位。
我这里找来了官方的寄存器截图:
预分频寄存器 (IWDG_PR):0~2位有效。具有写保护功能,要操作先取消写保护。用来对40kHz的LSI时钟进行分频,分频系数可以是4、8、16...最高256。
重装载寄存器 (IWDG_RLR):0~11位有效。具有写保护功能,要操作先取消写保护。这里存储着喂狗时要加载到计数器的值,范围是0到4095(12位最大值0xFFF)。
状态寄存器 (IWDG_SR):0~1位有效
3. 溢出时间怎么算?
这是大家最关心的:我到底多久必须喂一次狗?计算公式如下:
prer:预分频系数(对应IWDG_PR的值,0~7,分别代表4,8,16...256分频)。
rlr:重装载值(0~4095)。
举个例子:如果我们设置预分频系数为64(即prer配置为4),重装载值设为625。
代入公式:Tout = (64 * 625) / 40 = 40000 / 40 = 1000ms = 1秒。
这意味着,如果程序在1秒内没有喂狗,系统就会复位。
看门狗超时时间(40kHz的输入时钟(LSI)):
| 预分频系数 | PR[2:0]位 | 最短时间(ms) RL[11:0] = 0x000 | 最长时间(ms) RL[11:0] = 0xFFF |
| /4 | 0 | 0.1 | 409.6 |
| /8 | 1 | 0.2 | 819.2 |
| /16 | 2 | 0.4 | 1638.4 |
| /32 | 3 | 0.8 | 3276.8 |
| /64 | 4 | 1.6 | 6553.6 |
| /128 | 5 | 3.2 | 13107.2 |
| /256 | (6或7) | 6.4 | 26214.4 |
注: 这些时间是按照40kHz时钟给出。实际上,MCU内部的RC频率会在30kHz到60kHz之间变化。此外,即使RC振荡器的频率是精确的,确切的时序仍然依赖于APB接口时钟与RC振荡器时钟之间的相位差,因此总会有一个完整的RC周期是不确定的。通过对LSI进行校准可获得相对精确的看门狗超时时间。
三、 实战演练:基于标准库的IWDG实验
理论讲完了,我们来看看如何在STM32F103上实现一个简单的喂狗实验。本例使用标准外设库,硬件上需要一个按键(用于喂狗)和一个LED(用于指示状态)。
实验目标
- 程序启动时,LED点亮。
- 初始化看门狗,设置超时时间为1秒。
- 主循环检测按键,如果按下按键,执行喂狗操作,LED保持常亮。
- 如果超过1秒没有按下按键(没有喂狗),系统复位,LED会短暂熄灭后重新点亮(肉眼可见的闪烁)。
1. IWDG初始化函数
IWDG独立看门狗操作库函数
取消寄存器写保护:0x5555使能
IWDG_WriteAccessCmd();
设置独立看门狗的预分频系数,确定时钟:写PR
IWDG_SetPrescaler();
设置看门狗重装载值,确定溢出时间:写RLR
IWDG_SetReload();
使能看门狗:写0xCCCC到KR
IWDG_Enable();
应用程序喂狗:写0xAAAA到KR
IWDG_ReloadCounter();
状态:重装载/预分频 更新
FlagStatus IWDG_GetFlagStatus();
我们创建一个 iwdg.c 文件,编写初始化函数。
//初始化独立看门狗
//prer:分频数:0~7(只有低3位有效!)
//分频因子=4*2^prer.但最大值只能是256!
//rlr:重装载寄存器值:低11位有效.
//时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作
IWDG_SetPrescaler(prer); //设置IWDG预分频值:设置IWDG预分频值为64
IWDG_SetReload(rlr); //设置IWDG重装载值
IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器
IWDG_Enable(); //使能IWDG
}
//喂独立看门狗
void IWDG_Feed(void)
{
IWDG_ReloadCounter();//reload
}2. 主函数逻辑
在主函数中,我们首先判断复位原因,然后初始化硬件并启动看门狗。
int main(void)
{
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //按键初始化
delay_ms(500); //让人看得到灭
IWDG_Init(4,625); //与分频数为64,重载值为625,溢出时间为1s
LED0=0; //点亮LED0
while(1)
{
if(KEY_Scan(0)==WKUP_PRES)
{
IWDG_Feed();//如果WK_UP按下,则喂狗
}
delay_ms(10);
};
}四、 高级注意事项与避坑指南
在实际项目中,仅仅学会调用库函数是不够的。以下是一些开发多年总结的“避坑”经验:
1. 喂狗的“黄金位置”
千万不要在中断中喂狗! 这是一个常见的陷阱。
如果你的程序主循环已经死机,但中断(如SysTick、定时器中断)还在正常工作,此时如果在中断里喂狗,看门狗永远不会复位。这就失去了监控主程序的意义。正确的做法是只在主循环的恰当位置喂狗,确保整个程序的逻辑流是通畅的。
2. 时间余量要留足
由于LSI时钟并不精确(可能在30kHz~60kHz之间波动),计算出的1秒超时在实际中可能是0.8秒或1.2秒。因此,在设计喂狗周期时,不要卡着极限值喂狗。比如计算溢出时间是1秒,你的程序应该保证每500ms或600ms就喂一次狗,留出一倍的余量,以防环境温度变化导致时钟变慢,造成意外复位。
3. 硬件设计对IWDG的影响
这是一个非常隐秘的问题:如果IWDG配置正确,但就是不产生复位?
曾经有案例发现,如果外部复位芯片的驱动类型与STM32的NRST引脚不匹配(使用了CMOS推挽驱动),会导致STM32内部产生的复位信号无法传递出去。解决办法通常是在复位引脚串联一个电阻(如1KΩ)进行隔离。
4. 调试时的困扰
在Debug模式下,当你停在断点时,看门狗可不会停止计数。很快你会发现,在你单步调试代码时,看门狗超时复位了,导致无法调试。
解决办法:在代码初始化阶段,可以操作DBGMCU寄存器,调试时冻结看门狗。对于IWDG,需要设置 DBGMCU->CR |= DBGMCU_IWDG_STOP;。在STLink调试环境下,也可以配置IDE选项让仿真时停止看门狗计数。
5. 一旦启用,概不退换
IWDG一旦通过写入0xCCCC启动,就不能被软件关闭。唯一关闭它的方法就是发生系统复位,并且在复位后不再执行IWDG的使能代码。所以如果打算在程序里临时开启看门狗做测试,记得测试完要把初始化代码注释掉,否则下次上电它还会在。
五、 总结
STM32F103的独立看门狗(IWDG)是一个强大而简单的防死机工具。它就像一个忠诚的卫士,不依赖主时钟,独立运行,时刻盯着程序的运行。
- 优点:完全独立,极度可靠,适合整机死机监控。
- 缺点:时间精度差,不能精细监控程序段的执行窗口。
掌握了IWDG,你的嵌入式产品就多了一层重要的防护。希望这篇文章能帮助你更好地理解和使用STM32的独立看门狗。下次遇到设备无故死机不再动的情况,不妨试试用IWDG来“看住”它!
评论 (0)
登录后即可发表评论