WDG看门狗(独立看门狗和窗口看门狗)

WDG看门狗

文章目录

1.WDG简介

  • WDG(Watchdog)看门狗
  • 看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性
  • 看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号
  • STM32内置两个看门狗
    • 独立看门狗(IWDG):独立工作,对时间精度要求较低
    • 窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用

独立工作,就是独立看门狗的时钟是专用的LSI,内部低速时钟,即使主时钟出现问题了,看门狗也可以正常工作,独立看门狗有一个最短界限,只要喂狗间隔只要不超过这个最晚界限就行了

精确计时窗口:意思就是喂狗的时间有个最晚的界限,也有个最早的界限,必须在这个界限的窗口内喂狗,使用的是APB1的时钟没有专用的时钟,所以不算独立

2.IWDG独立看门狗

2.1IWDG框图

独立看门狗

2.1.1实现步骤(配置流程)
  1. 开启LSI(开启独立看门狗,LSI就会被强制打开)
  2. 写入预分频器和重装寄存器(需要先解除写保护),根据超时时间公式写入预分频值和重装值
  3. 使用0xCCCC启动独立看门狗
  4. 在主程序中写入0xAAAA来进行喂狗操作
2.1.2相关库函数
c 复制代码
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);//写使能操作,定义处0x5555(解除写保护)就是enbale使能,0x0000(启用写保护)就是disable失能
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//写预分频器,就是写PR寄存器
void IWDG_SetReload(uint16_t Reload);//写重装值,RLR寄存器
void IWDG_ReloadCounter(void);//重新装载寄存器,就是喂狗
void IWDG_Enable(void);//键寄存器写入0xCCCC,启动看门狗
FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);//获取标志位状态

查看复位是看门狗导致的复位还是,系统或复位键导致的复位。

c 复制代码
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);//查看标志位的函数,根据参数查看对应的标志位,时钟或触发状态等
void RCC_ClearFlag(void);//清除标志位

2.2IWDG键寄存器

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

如果只有一位,那么一位被误写的概率大,所以采用特定的值(16位),如下表:

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

在键寄存器写入特定的值,进行设置,对其他寄存器进行保护和修改(PR,SR,RLR)

总之,键寄存器设置的用途就是防止误操作。

2.3超时时间计算

写入PR和RL寄存器来确定超时时间。

  • 超时时间: T I W D G T_{IWDG} TIWDG = T L S I T_{LSI} TLSI × PR预分频系数 × (RL + 1)

  • 其中: T L S I T_{LSI} TLSI = 1 F L S I \frac{1}{ F_{LSI}} FLSI1

在40kHz下,T周期为1/40KHz = 0.025ms,表格:如果PR等于选择0的话,预分频系数可选4,最短时间RL可选0x000(0+1),最长时间RL可选0xFFF(4095+1),0.025*4*1=0.1;0.025*4*4096 = 409.6

3.WWDG窗口看门狗

3.1WWDG框图

3.1.1实现步骤
  1. 开启窗口看门狗APB1的时钟(不会自动开启)
  2. 配置寄存器(预分频和窗口值),没有写保护
  3. 写入控制寄存器CR(包含看门狗使能位,计数器溢出标志位和计数器有效位)
  4. 不断向计数器写入想要的重装值就可以进行喂狗了
3.1.2相关库函数
c 复制代码
void WWDG_DeInit(void);//恢复缺省配置
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);//写入预分频器
void WWDG_SetWindowValue(uint8_t WindowValue);//写入窗口值(初始化配置采用这两个函数)
void WWDG_EnableIT(void);//使能中断,只有一个中断所以不需要指定参数
void WWDG_SetCounter(uint8_t Counter);//写入计数器,喂狗使用这个函数
void WWDG_Enable(uint8_t Counter);//使能窗口看门狗,初始化后启动看门狗就用这个函数,参数是防止一使能就复位,所以指定喂狗
FlagStatus WWDG_GetFlagStatus(void);//获取标志位
void WWDG_ClearFlag(void);//和清除标志位的函数

3.2工作特性

  • 递减计数器T[6:0]的值小于0x40时,WWDG产生复位
  • 递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位
  • 递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位
  • 定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位

等于0x40:就是在发送复位信号的前一刻,可以进行一些紧急操作,比如保存数据或这直接处理问题等,可以在早期唤醒中断中直接执行喂狗,阻止系统复位

3.3WWDG超时时间

  • 超时时间:

    • ​ T W W D G T_{WWDG} TWWDG = T P C L K 1 T_{PCLK1} TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] + 1)

      (上面的T[5:0]是计数器减到0的时间)

  • 窗口时间:

    • ​ T W I N T_{WIN} TWIN= T P C L K 1 T_{PCLK1} TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] - W[5:0])

      (上面的T[5:0] - W[5:0]为计数器减到窗口值得时间)

  • 其中: T P C L K 1 T_{PCLK1} TPCLK1 = 1 F P C L K 1 \frac{1 }{F_{PCLK1}} FPCLK11

TPCLK1 = 1/36MHz

TWWDG = 1/36MHz*4096* 2 0 2^0 20*(0+1)=113us(6位计数器最小值)

TWWDG = 1/36MHz*4096* 2 0 2^0 20*( 2 6 2^6 26+1)=7.28ms(6位计数器最大值值)

3.4窗口看门狗的配置寄存器和控制寄存器的位用处

寄存器 作用 位域说明
WWDG_CR 控制看门狗的使能、当前计数器值 - 位 7 (WDGA) : 看门狗激活位(置 1 后锁定配置) - 位 6:0 (T[6:0]) : 当前计数器值(7 位,范围 0x00~0x7F
WWDG_CFR 配置窗口值、预分频系数和中断 - 位 6:0 (W[6:0]) : 窗口值(7 位,必须大于 0x3F) - 位 9:8 (WDGTB[1:0]) : 预分频系数 - 位 9 (EWI): 早期唤醒中断使能位

4.IWDG和WWDG对比(区别)

IWDG独立看门狗 WWDG窗口看门狗
复位 计数器减到0后 计数器T[5:0]减到0后、过早重装计数器
中断 早期唤醒中断
时钟源 LSI(40KHz) PCLK1(36MHz)
预分频系数 4、8、32、64、128、256 1、2、4、8
计数器 12位 6位(有效计数)
超时时间 0.1ms~26214.4ms 113us~58.25ms
喂狗方式 写入键寄存器,重装固定值RLR 直接写入计数器,写多少重装多少
防误操作 键寄存器和写保护
用途 独立工作,对时间精度要求较低 要求看门狗在精确计时窗口起作用

看门狗一旦启用,就无法关闭

5.独立看门狗(实操)

5.1接线图

5.2代码部分

main.c

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
#include "OLED.h"
//#include "OLED_Font.h"



int main(void){
	
	OLED_Init();
	Key_Init();
	
	OLED_ShowString(1,1,"IWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET){//看门狗标志位是否为1
		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);
	//超时时间计算公式见笔记
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	IWDG_SetReload(2499);
	IWDG_ReloadCounter();//喂一次狗
	IWDG_Enable();
	
	while(1){
		Key_getNum();//按下按钮,长时间没响应触发中断
		
		IWDG_ReloadCounter();
		
		OLED_ShowString(4,1,"FEED");
		Delay_ms(200);
		OLED_ShowString(4,1,"    ");
		Delay_ms(600);//共延迟800ms,没有超过1000ms,不会
	
	}
}

按键未按下时

  • 主循环正常执行,每 800ms 喂狗一次(<1 秒超时时间)
  • 看门狗不会触发复位
  • OLED 交替显示 "FEED" 和空白

按键按下时

  • Key_getNum()进入阻塞状态,等待按键释放
  • 如果按住时间超过 1 秒,看门狗计数器溢出,触发系统复位
  • 重启后检测到RCC_FLAG_IWDGRST标志,显示 "IWDGRST"

6.窗口看门狗

6.1接线图

6.2代码部分

main.c

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
#include "OLED.h"
//#include "OLED_Font.h"



int main(void){
	
	OLED_Init();
	Key_Init();
	
	OLED_ShowString(1,1,"WWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET){//看门狗标志位是否为1
		OLED_ShowString(2,1,"WWDFRST");
		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);
	WWDG_SetWindowValue(0x40 + 21);		//30ms
	WWDG_Enable(0x40 + 54);				//50ms
	//窗口看门狗需要在使能窗口看门狗的时候写入计数器时间
	
	
	while(1){
		Key_getNum();//按下按钮,长时间没响应触发中断
		
		
		OLED_ShowString(4,1,"FEED");
		Delay_ms(24);
		OLED_ShowString(4,1,"    ");
		Delay_ms(25);//共延迟800ms,没有超过1000ms,不会
		
		WWDG_SetCounter(0x40 + 54);//喂狗
	}
}

需要加上0x40是因为,公式计算的数值是T[5:0]的数值,而实际上6位,所以要加上最高位也就是0x40。

需要注意的是,看门狗的使能时写入计数器的值与进入主循环后再向计数器中写入重装值不能靠的太近,否则会出错。

相关推荐
Tummer83631 小时前
C语言与C++的区别
c语言·c++·算法
爱分享的程序员2 小时前
微信小程序执行C语言库的详细方案
c语言·微信小程序·小程序
柒柒的代码学习日记7 小时前
数组和指针典型例题合集(一维数组、字符数组、二维数组)
c语言
△曉風殘月〆9 小时前
C#串口通信
嵌入式硬件·c#·串口
大龄Python青年11 小时前
C语言 交换算法之加减法,及溢出防范
c语言·开发语言·算法
谷雪_65812 小时前
鼠标交互初体验:点击屏幕生成彩色气泡(EGE 库基础)
c语言·开发语言·microsoft·交互
我不是帅戈13 小时前
STM32+安信可Ai-WB2-12F连接阿里云物联网平台
stm32·物联网·阿里云·云计算·安信可
教练、我想打篮球13 小时前
04 基于 STM32 的时钟展示程序
stm32·单片机·嵌入式硬件
大鱼YY13 小时前
STM32系统定时器以及微秒延时函数分析
stm32·滴答定时器