【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. 看门狗作用:防死机、跑飞、死循环,自动复位

相关推荐
蓝斯49721 小时前
从.到实现一个Windows上的虚拟hid键盘设备
windows·单片机·计算机外设
熙芯XiChip1 天前
硬实时与软实时RTOS核心区别
嵌入式硬件
伟大的前程1 天前
unsigned int 定义的变量 在 电脑的 64 位系统中 和 32 位 cortex-m0 和 8 位的 51 单片机
单片机·嵌入式硬件
小渔村的拉线工1 天前
1.HPM6E80 解析芯片整体工作原理和存储架构
单片机·嵌入式硬件·mcu·架构·hpm6e80
熙芯XiChip1 天前
CAN与CANopen的本质区别
单片机
lilihewo1 天前
Altium Designer 封装库的创建(分享pcb 3D封装库)
嵌入式硬件·51单片机
神罚天下ET1 天前
典型arm位单片机启动流程(从上电到main.c)
c语言·arm开发·单片机
碧海银沙音频科技研究院1 天前
蓝牙耳机使用WSDF5361锂保芯片进入船运模式实现方法
嵌入式硬件·算法
Zevalin爱灰灰1 天前
模拟信号链电路——基于TL431的电压基准电路
单片机·嵌入式硬件
csdn杰哥1 天前
瑞萨单片机开发教程[二十七] DTC 外部中断触发传输实验
单片机·嵌入式硬件·mongodb·瑞萨·ra6m5