【STM32】知识点介绍九:看门狗功能

文章目录


一、简介

1.IWDG简介

STM32有两个看门狗,一个是独立看门狗另外一个是,窗口看门狗,独立看门狗号称宠物狗,窗口看门狗号称警犬。独立看门狗用通俗一点的话来解释就是一个12位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即IWDG_RESET。如果在计数没减到0之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。看门狗功能由 VDD 电压域供电,在停止模式和待机模式下仍能工作。

2.工作原理剖析

STM32 的独立看门狗(IWDG)由内部专门的低速时钟(LSI,Low Speed Internal clock)驱动 ,这是其最为显著的特点之一。LSI 时钟频率通常在 32kHz 左右(实际频率可能在一定范围内波动,但在计算和应用中一般近似为 32kHz),这种独立性使得 IWDG 即使在主时钟发生故障的情况下,依然能够稳定工作,为系统的可靠性提供了坚实的后盾。

其工作机制可以简单理解为一个倒计时器。当独立看门狗被启用后,一个 12 位的递减计数器会从初始设定的复位值(通常是 0xFFF,即 4095)开始向下递减计数。在系统正常运行时,程序需要在计数器的值减到 0 之前,向独立看门狗发送一个 "喂狗" 信号,这个操作也被称为 "刷新看门狗" 。具体的实现方式是向特定的寄存器(键值寄存器 IWDG_KR)写入特定的值(0xAAAA),这样就会将重装载寄存器 IWDG_RLR 中的值重新加载到计数器中,使得计数器重新开始从设定的重载值递减计数,从而避免看门狗超时产生复位信号。

如果程序因为某些异常情况,比如受到外界干扰导致程序跑飞,或者进入死循环等,无法按时向独立看门狗发送喂狗信号,那么计数器就会一直递减,当计数值到达 0 时,独立看门狗就会认为系统出现了故障,进而产生一个复位信号(IWDG_RESET),这个复位信号会将整个 STM32 系统复位,使得系统重新启动,回到初始状态,就像给系统做了一次 "重启治疗",让系统有机会从错误状态中恢复过来 。

3.看门狗异常事件

序号 独立看门狗 窗口看门狗
1 出现程序跑飞 软件逻辑出现错误
2 出现死循环 死机
3 睡眠不合理时 死循环
4 休眠不合理 软件执行不按预期效果执行
5 外部主晶振坏掉 软件需要重新复位下但是需要数据恢复
6 需要从新复位系统,不保留任何数据 喂狗太快--复位,喂狗太慢--复位,迟了喂狗,还可以有中断喂狗

4.窗口看门狗

在系统复位后,看门狗总是处于关闭状态。可通过设置 WWDG_CR 寄存器中的 WDGA 位来使能看门狗,之后除非执行复位操作,否则不能再次关闭。

c 复制代码
.窗口看门狗的时钟频率1281Hz,每进行减一计数,所花的时间
     T=1/f=1/1281Hz≈780.6us

.从127减到80,要进行47次的计数,所花的时间
     T=780.6us * 47 =36.69ms

.从127减到0x3F,要进行64次的计数,所花的时间
     T=780.6us * 63 =49.96ms

二、IWDG功能框图

1.独立看门狗时钟

独立看门狗的时钟由独立的RC振荡器LSI提供,即使主时钟发生故障它仍然有效,非常独立。LSI的频率一般在30~60KHZ之 间,根据温度和工作场合会有一定的漂移,我们一般取32KHZ,所以独立看门狗的定时时间并不一定非常精确,只适用于对时间精度要求比较低的场合。

2.计数器时钟

递减计数器的时钟由LSI经过一个8位的预分频器得到,我们可以操作预分频器寄存器IWDG_PR来设置分频因子,分频因子可以是:[4,8,16,32,64,128,256,256],计数器时钟CK_CNT= 40/ 4*2^PRV,一个计数器时钟计数器就减一。

3.计数器

独立看门狗的计数器是一个12位的递减计数器,最大值 为0XFFF,当计数器减到0时,会产生一个复位信号:IWDG_RESET,让程序重新启动运行,如果在计数器减到0之前刷新了计数器的值的话,就不会产生复位信号,重新刷新计数器值的这个动作我们俗称喂狗。

4.重装载寄存器

重装载寄存器是一个12位的寄存器,里面装着要刷新到计数器的值,这个值的大小决定着独立看门狗的溢出时间。超时时间Tout = (4*2^prv) / 40 * rlv (s),prv是预分频器寄存器的值,rlv是重装载寄存器的值。

5.键寄存器

键寄存器IWDG_KR可以说是独立看门狗的一个控制寄存器,主要有三种控制方式,往这个寄存器写入下面三个不同的值有不同的效果。

通过写往键寄存器写0XCCC来启动看门狗是属于软件启动的方式,一旦独立看门狗启动,它就关不掉,只有复位才能关掉

键值 键值作用
0xAAAA 把RLR的值重装载到CNT
0x5555 PR和RLR这两个寄存器可写
0xCCCC 启动IWDG

6.状态寄存器

状态寄存器SR只有位0:PVU和位1:RVU有效,这两位只能由硬件操作,软件操作不了。RVU:看门狗计数器重装载值更新,硬件置1表示重装载值的更新正在进行中,更新完毕之后由硬件清0。PVU: 看门狗预分频值更新,硬件置'1'指示预分频值的更新正在进行中,当更新完成后,由硬件清0。所以只有当RVU/PVU等于0的时候才可以更新重装载寄存器/预分频寄存器。


三、IWDG 代码实现全流程

1.初始化配置

①.取消寄存器写保护 :在对独立看门狗的预分频寄存器(IWDG_PR)和重装载寄存器(IWDG_RLR)进行配置之前,需要先取消对这两个寄存器的写保护。在 HAL 库中,可以通过调用__HAL_IWDG_ENABLE_WRITE_ACCESS(&hiwdg);函数来实现这一操作,其中hiwdg是IWDG_HandleTypeDef类型的结构体变量,用于表示独立看门狗的句柄,通过这个句柄可以访问和操作独立看门狗的相关寄存器和功能 。

②.设置预分频系数:预分频系数决定了独立看门狗计数器的时钟分频,从而影响看门狗的计时精度和超时时间。例如,如果希望看门狗的计时精度较高,超时时间较短,可以选择较小的预分频系数;反之,如果希望超时时间较长,可以选择较大的预分频系数 。

2.设置重装载值

重装载值是独立看门狗计数器的初始值,当计数器递减到 0 时,如果还没有进行喂狗操作,就会触发系统复位 。重装载值的大小与预分频系数一起决定了看门狗的超时时间。计算超时时间的公式为Tout = ((4×2^prer) ×rlr) / LSI_freq ,其中Tout是超时时间,prer是预分频值,rlr是重装载值,LSI_freq是 LSI 时钟频率(约 32kHz) 。例如,设置重装载值为 625,结合前面设置的预分频系数 64,代入公式计算可得超时时间约为 1 秒(Tout = ((4×2^6) ×625) / 32000 = 1s) 。设置重装载值的代码如下:

c 复制代码
hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
hiwdg.Init.Reload = 625;

3.重载计数值喂狗

在完成预分频系数和重装载值的设置后,需要进行一次喂狗操作,即将重装载值加载到计数器中,使计数器从初始值开始递减计数 。在 HAL 库中,可以通过调用HAL_IWDG_Refresh(&hiwdg);函数来实现喂狗操作,确保看门狗在初始化后不会立即触发复位 。

启动看门狗:完成上述配置后,最后一步是启动独立看门狗,使其开始工作。在 HAL 库中,调用HAL_IWDG_Init(&hiwdg);函数即可启动独立看门狗,该函数会根据之前设置的参数对独立看门狗进行初始化并启动 。


四、完整代码

1.独立看门狗初始化

c 复制代码
void MX_IWDG_Init(void)
{
	IWDG_HandleTypeDef hiwdg;
	hiwdg.Instance = IWDG;
	hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
	hiwdg.Init.Reload = 625;

	// 取消寄存器写保护
	__HAL_IWDG_ENABLE_WRITE_ACCESS(&hiwdg);
	if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
	{
		// 初始化失败处理
		Error_Handler();
	}

	// 喂狗操作
	HAL_IWDG_Refresh(&hiwdg);
}

2.喂狗操作

喂狗操作在程序运行过程中至关重要,它是确保系统正常运行,避免看门狗超时复位的关键步骤。在主循环或关键代码段中,需要定期进行喂狗操作,以表明系统正在正常运行 。在 HAL 库中,喂狗操作非常简单,只需要调用HAL_IWDG_Refresh(&hiwdg);函数即可,其中hiwdg是独立看门狗的句柄 。例如,在主循环中进行喂狗操作的代码如下:

c 复制代码
int main(void)
{
	// 初始化代码
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_IWDG_Init();

	while (1)
	{
		// 模拟系统任务
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
		HAL_Delay(500);

		// 喂狗操作
		HAL_IWDG_Refresh(&hiwdg);
	}
}

在上述代码中,主循环中每隔 500 毫秒翻转一次 PC13 引脚上的 LED 状态,模拟系统的正常任务执行,同时在每次循环中调用HAL_IWDG_Refresh(&hiwdg);函数进行喂狗操作,确保看门狗不会因为超时触发复位 。如果喂狗时机不当,比如长时间没有进行喂狗操作,当看门狗计数器递减到 0 时,就会触发系统复位,导致系统重新启动 。例如,如果在某个关键代码段中,由于程序逻辑错误或其他原因导致喂狗操作被遗漏,那么看门狗就会在超时后将系统复位 。所以,在编写程序时,一定要仔细规划喂狗的时机和频率,确保系统能够稳定运行。

3.窗口看门狗

(1)检查复位状态,有助于观察当前工作的可靠性

c 复制代码
	/* 检查是否窗口看门狗导致的复位,如果发现由窗口看门狗导致的复位,输出打印信息 */
	if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET)
	{ 
		/* WWDGRST flag set */
		printf("wwdg reset cpu\r\n");

		/* Clear reset flags */
		RCC_ClearFlag();
	}
	else
	{
		/* WWDGRST flag is not set */
		printf("normal reset cpu\r\n");
	}
	
	delay_ms(500);
	delay_ms(500);

(2)窗口看门狗的初始化

c 复制代码
	/* 窗口看门狗的配置 */
	/* 使能窗口看门狗的时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);

	/* 窗口看门狗的时钟 = (PCLK1 (42MHz)/4096)/8 = 1281 Hz (~780 us)  */
	WWDG_SetPrescaler(WWDG_Prescaler_8);

	/* 设置窗口的上限值为80 */
	WWDG_SetWindowValue(80);

	/* 设置计数值的初值为127,则窗口看门狗的最大超时时间 = 780 us * 64 = 49.92 ms 
		这个时候窗口刷新时间如下
     ~780 * (127-80) = 36.66ms < refresh window < ~780 * 64 = 49.9ms */
	WWDG_Enable(127);

	//WWDG NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;			//窗口看门狗中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;		//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		//子优先级0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);					//根据指定的参数初始化VIC寄存器	
	//清空提前唤醒中断标志位
	WWDG_ClearFlag();
	
	//使能提前唤醒中断
	WWDG_EnableIT();

(3)看门狗中断服务函数

c 复制代码
void WWDG_IRQHandler(void)
{
	if(WWDG_GetFlagStatus()==SET)
	{
		//进行喂狗
		WWDG_SetCounter(127);

		//清空提前唤醒中断标志位
		WWDG_ClearFlag();
	}
}

五、常见问题与解答

1.什么是看门狗?STM32 有哪两种看门狗?

看门狗(WatchDog)是一个硬件定时器,作用是监控程序运行状态,防止程序跑飞、死机、死循环。当程序异常无法 "喂狗" 时,看门狗溢出会自动复位单片机,让系统恢复正常。

STM32 有两种看门狗:IWDG 独立看门狗、WWDG 窗口看门狗

2. IWDG 和 WWDG 的核心区别?

特性 IWDG 独立看门狗 WWDG 窗口看门狗
时钟源 独立 RC 振荡器(LSI) 系统时钟 PCLK1
是否独立 独立于主时钟,主时钟失效仍工作 依赖系统时钟,时钟失效则失效
复位条件 计数器减到 0 就复位 计数器 < 0x40 复位;提前喂狗(< 窗口下限)复位
功能 单纯防死机 防死机 + 检测程序执行时间异常
中断 无中断,只能复位 有早期唤醒中断(EWI)
使用场景 绝大多数产品通用 精准监控程序执行周期

3.WWDG 的 "窗口" 是什么意思?为什么不能提前喂狗?

WWDG 有上窗口值和下窗口值(固定 0x40):

  1. 只能在窗口内喂狗:计数器 <上窗口,且> 0x40
  2. 提前喂狗(计数器 > 上窗口)→ 直接复位
  3. 超时喂狗(计数器 < 0x40)→ 直接复位

不仅监控程序死机,还能监控程序执行速度是否异常(比如中断抢占、代码跑飞导致执行过快 / 过慢)。

4.看门狗可以软件关闭吗?

  • IWDG:一旦启动,无法软件关闭,只能硬件复位
  • WWDG:可以通过寄存器关闭(实际产品一般不关闭)

5.什么时候用 IWDG,什么时候用 WWDG?

  • IWDG:90% 产品使用,要求高可靠、简单,只需要防死机
  • WWDG:对程序执行时间精度要求高,需要监控程序是否跑飞、执行过快 / 过慢

PS:

  1. STM32 两种看门狗:IWDG(独立)、WWDG(窗口)
  2. IWDG 时钟:LSI 独立时钟,最可靠,无法关闭
  3. WWDG 时钟:PCLK1,有窗口限制,可监控执行时间
  4. 喂狗必须放主循环,不能放中断
  5. IWDG 超时公式:重装载值 × 分频 / 32000
  6. 看门狗作用:防死机、跑飞、死循环,自动复位

相关推荐
VBsemi-专注于MOSFET研发定制2 小时前
面向高端汽车暖风系统控制器的功率MOSFET选型策略与器件适配手册
单片机·嵌入式硬件
Byron Loong2 小时前
【常识】通俗易懂的讲CPU,GPU,MCU,FPGA,DSP的区别和特点
单片机·嵌入式硬件·fpga开发
zmj3203242 小时前
工业通信--CRC校验分类及实现细节
人工智能·单片机·数据挖掘·can
潜创微科技2 小时前
CH398:高集成度 USB 3.0 转千兆以太网芯片方案
嵌入式硬件·音视频
charlie11451419113 小时前
嵌入式C++工程实践第16篇:第四次重构 —— LED模板,从通用GPIO到专用抽象
c语言·开发语言·c++·驱动开发·嵌入式硬件·重构
深圳市九鼎创展科技15 小时前
MT8883 vs RK3588 开发板全面对比:选型与场景落地指南
大数据·linux·人工智能·嵌入式硬件·ubuntu
三品吉他手会点灯17 小时前
STM32 VSCode 开发-C/C++的环境配置中,找不到C/C++: Edit Configurations选项
c语言·c++·vscode·stm32·单片机·嵌入式硬件·编辑器
LongRunning19 小时前
【BLE】STM32WB55_定时器碎片(九)
stm32
yu859395819 小时前
STM32 智能红外循迹小车(含码盘测速 + 避障)
stm32·单片机·嵌入式硬件