[STM32]Day14独立看门狗+窗口看门狗

WDG看门狗

WDG(Watch Dog),看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性

看门狗本质上是一个定时器,当指定事件范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号

STM32内置两个看门狗:

  • 独立看门狗(IWDG):独立工作,对时间精度要求较低
  • 窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用

独立看门狗框图

IWDG键寄存器

键寄存器本质上是控制寄存器,用于控制硬件电路的工作

在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率

写入键寄存器的值 作用
0xCCCC 启动独立看门狗
0xAAAA IWDG_RLR中的值重新加载到计数器(喂狗)
0x5555 解除IWDG_PR和IWDG_RLR的写保护
其他值 启用IWDG_PR和IWDG_RLR的写保护

IWDG超时时间

超时时间:T_IWDG = T_LSI * PR分频系数 * (RL + 1)

其中:T_LSI = 1 / F_LSI

WWDG框图

窗口看门狗使用PCLK1也就是APB1的时钟,默认为36MHz,经过预分频器分频后驱动计数器递减计数。T6 - T0为计数位,T6为溢出标志位,T6 = 0时表示计数器溢出。当设置CNT初值为111 1111时,如果把T6看作计数器的一部分,计数器在100 0000 = 0x40溢出;如果把T6看作标志位,计数器在00 0000 = 0x00溢出

WDGA时窗口看门狗使能位,WDGA = 1启用窗口看门狗。T6 = 0时,可以产生复位信号。

W6:0存放的是最早界限的计数值,写入后保持不变。每次喂狗(写入WWDG_CR)时,比较器比较W6:0与当前计数值T6:0,如果T6:0 > W6:0说明喂狗时间太早(注意计数器递减),比较器输出1,产生复位信号。

WWDG工作特性

递减计数器T6:0的值小于0x40时,WWDG产生复位

递减计数器T6:0在窗口W6:0外被重新装载时,WWDG产生复位

递减计数器T6:0等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位

定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位

超时时间:T_WWDG = T_PCLK1 * 4096 * WDGTB预分频系数 * (T5:0 + 1)

窗口时间:T_WIN = T_PCLK1 * 4096 * WDGTB预分频系数 * (T5:0 - W5:0

其中:T_PCLK1 = 1 / F_PCLK1

乘以4096是因为在进入WDGTB之前还经过了分频,分频系数为4096

WDGTB预分频系数 = 2的WDGTP次方

IWDG和WWDG对比

独立看门狗

按键用于阻塞喂狗

独立看门狗配置流程:开启LSI时钟(开启看门狗后系统自动开启,无需手动操作) -> 解除预分频器和重装载寄存器写保护 -> 向预分频器和重装载寄存器写入 -> 向键寄存器写入0xCCCC启动看门狗 -> 主循环中喂狗

F_LSI = 40kHz,T_LSI = 0.025ms

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "OLED_Software.h"
#include "Delay.h"
#include "Button.h"

int main(void)
{
	
	OLED_Init();
	Button_Init();
	
	OLED_ShowString(1, 1, "IWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) {
		// 独立看门狗引起的复位
		OLED_ShowString(2, 1, "IWDGRST");
		Delay_ms(500);
		OLED_ShowString(2, 1, "       ");
		Delay_ms(100);
		
		RCC_ClearFlag();
	} else {
		OLED_ShowString(3, 1, "RST");
		Delay_ms(500);  
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	// 解除预分频器和重装寄存器写保护
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	
	// 向预分频器和重装寄存器写入,T_LSI = 0.025ms,设置超时时间为1000ms
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	IWDG_SetReload(2499);
	
	// 先喂一次狗,确保重装寄存器中的值为2499
	IWDG_ReloadCounter();
	
	// 启动看门狗
	IWDG_Enable();

	while(1)
	{
		Button_Read(Pin_11);
		
		IWDG_ReloadCounter();
		
		OLED_ShowString(4, 1, "FEED");
		Delay_ms(200);  
		OLED_ShowString(4, 1, "    ");
		Delay_ms(600);
	}
}

窗口看门狗

窗口看门狗初始化流程:开启时钟(开启APB1时钟) -> 配置预分频器和配置寄存器 -> 使能WWDG并写入控制寄存器 -> 主循环喂狗

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "OLED_Software.h"
#include "Delay.h"
#include "Button.h"

int main(void)
{
	
	OLED_Init();
	Button_Init();
	
	OLED_ShowString(1, 1, "WWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) {
		// 窗口看门狗引起的复位
		OLED_ShowString(2, 1, "WWDGRST");
		Delay_ms(500);
		OLED_ShowString(2, 1, "       ");
		Delay_ms(100);
		
		RCC_ClearFlag();
	} else {
		OLED_ShowString(3, 1, "RST");
		Delay_ms(500);  
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	// 开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	
	// 设置预分频和窗口值
	WWDG_SetPrescaler(WWDG_Prescaler_8);	// 分频系数8,分频系数55 -> 超时时间50ms
	WWDG_SetWindowValue(21 | 0x40);		// 窗口值21 -> 30ms以后才可喂狗
	
	// 使能WWDG并写入控制寄存器
	WWDG_Enable(54 | 0x40);

	while(1)
	{
		Button_Read(Pin_11);
			
		OLED_ShowString(4, 1, "FEED");
		Delay_ms(20);  
		OLED_ShowString(4, 1, "    ");
		Delay_ms(20);
		
		// 喂狗,放在下面避免喂狗过早
		WWDG_SetCounter(54 | 0x40);
	}
}
相关推荐
H__Rick1 小时前
C51学习-DAY7
单片机·嵌入式硬件·学习·51单片机
济6171 小时前
BMS系统专栏:认知电池管理系统BMS的知识与功能
嵌入式硬件·嵌入式·ros2·机器人开发·机器人方向
欢乐熊嵌入式编程1 小时前
第2讲:什么是优秀的软件架构?
stm32·单片机·freertos·低功耗蓝牙·嵌入式架构·efr32
嵌入式ZYXC1 小时前
第9篇:《面试题:ADC前端为什么要加运放跟随器?什么情况下可以不加?》
stm32·单片机·嵌入式硬件·面试·职场和发展
DS小龙哥2 小时前
基于STM32设计的电动车智能充电计费系统
stm32·单片机·嵌入式硬件
普中科技2 小时前
【普中STM32F1xx开发攻略--标准库版】-- 第 49 章 FLASH 字库实验
stm32·单片机·嵌入式硬件·flash·gbk·字库·普中科技
kyle~2 小时前
机器人日志系统
c++·单片机·嵌入式硬件·机器人·ros2
踏着七彩祥云的小丑3 小时前
嵌入式测试学习第 34 天:常见bug类型:死机、重启、数据错乱、通信丢包
单片机·嵌入式硬件·学习
一个嵌入式学徒3 小时前
STM32+ESP8266 接入机智云平台完整步
stm32·单片机·嵌入式硬件