WDG看门狗简介
作用:看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性
看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号
STM32内置两个看门狗
1.独立看门狗(IWDG):独立工作,对时间精度要求较低
2.窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用
独立看门狗(IWDG)
就是一个12 位的递减计数器(最大值为0xFFFF),当计数器的值从某个值一直减到0还没有喂狗时,系统就会产生一个复位信号,即IWDG_RESET。如果在计数没减到0 之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。
独立看门狗的时钟由独立的RC 振荡器LSI 提供,即使主时钟发生故障它仍然有效,非常独立。LSI 的频率一般在30~60KHZ 之间,根据温度和工作场合会有一定的漂移,所以独立看门狗的定时时间并不一定非常精确,只适用于对时间精度要求比较低的场合。
递减计数器的时钟由LSI 经过一个8 位的预分频器得到,我们可以操作预分频器寄存器IWDG_PR 来设置分频因子,分频因子可以是:[4,8,16,32,64,128,256]
计数器时钟CK_CNT = 40/ 4*2^PRV,一个计数时钟到来,计数器就减一
重装载寄存器是一个12 位的寄存器,里面装着要刷新到计数器的值,这个值的大小决定着独立看门狗的溢出时间。超时时间Tout = (4*2^prv) / 40 * rlv (s) ,prv 是预分频器寄存器的值,rlv 是重装载寄存器的值。
键寄存器IWDG_KR
键寄存器IWDG_KR 可以说是独立看门狗的一个控制寄存器,主要有三种控制方式,往这个寄存 器写入下面三个不同的值有不同的效果。
代码
IWDG 属于单片机内部资源,不需要外部电路,需要一个外部的按键和LED,通过按键来喂狗,喂狗成功LED 灭,喂狗失败,程序重启,LED 亮一次。
#include "public.h"
/*
1.取消写保护 IWDG_WriteAccessCmd 0x5555
2.对LSI时钟分频,32分频 32khz/32=1khz 计一个数:1/1khz = 1ms
IWDG_SetPrescaler
3.设置看门狗溢出时间:重装载寄存器值
IWDG_SetReload
4.填充自动重装载值
IWDG_ReloadCounter
5.使能看门狗
IWDG_Enable
6.在程序中定时喂狗
按键喂狗:判断按键按下后调用IWDG_ReloadCounter
*/
void IWDG_Init_Config(void)
{
//取消写保护
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//设置分频系统
IWDG_SetPrescaler(IWDG_Prescaler_32);
//32分频 32khz/32=1khz 倒数一个数:1/1khz = 1/1000hz =0.001s = 1ms
//设置重装载值
IWDG_SetReload(2000); //数2000个数,用时2s
IWDG_ReloadCounter();
//启动
IWDG_Enable();
}
main.c
#include "public.h"
int main(void)
{
//2号分组:2bit给抢占 2bit给响应 0-3 0-3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Init();
KEY_Init();
LED_Init();
IWDG_Init_Config();
GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10); //如果复位,则灯亮
while(1)
{
if(GetStaKey()==true) //按键KEY_UP
{
GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10); //灯灭
IWDG_ReloadCounter(); //喂狗
}
}
}
窗口看门狗(WWDG)
也是一个递减计数器(7位)不断的往下递减计数,当减到一个固定值0X40 时还不喂狗的话,产生复位(到0x3F),这个值叫窗口的下限,是固定的值,不能改变。
这是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。
(上限就是7位都是1,所以计数范围为0x7F ~ 0x40,所以WWDG的窗口上限最大只能是0x7F)
从0X40 变为0X3F时候,会产生看门狗复位
窗口看门狗时钟来自PCLK1,PCLK1 最大是42M,由RCC 时钟控制器开启。
计数器时钟由CK 计时器时钟经过预分频器分频得到,分频系数由配置寄存器CFR 的WDGTB[1:0] 配置。
其中CK 计时器时钟=PCLK1/4096,除以4096 是手 册规定的,手册没有解释为什么(个人猜测还是为了降频)。所以计数器的时钟CNT_CK=PCLK1/4096/(2^WDGTB),
这就可以算出计数器减一个数的时间T= 1/CNT_CK = 4096 * (2^WDGTB) / PCLK1。
窗口看门狗的使用时机
WWDG 一般被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序 列而产生的软件故障。比如一个程序段正常运行的时间是50ms,在运行完这个段程序之后紧接 着进行喂狗,如果在规定的时间窗口内还没有喂狗,那就说明我们监控的程序出故障了,跑飞了, 那么就会产生系统复位,让程序重新运行。
代码
#include "public.h"
/*
1.APB1时钟使能
2.时钟分频 42MHZ
WWDG_SetPrescaler
3.设置窗口值
WWDG_SetWindowValue
4.窗口计数器使能
WWDG_Enable
5.需要定时喂狗
*/
// 上窗口前时间(127-100)*780us = 21.06ms
// 喂狗时间 (100-64)*780us = 28.08ms
void WWDG_Init_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
WWDG_SetPrescaler(WWDG_Prescaler_8); //4分频, 42Mhz/ 4096 / 8 = 1281hz 计数计一个数时间为780us
//0x7f - 0x40 127-64
WWDG_SetWindowValue(100);
WWDG_Enable(0x7f);
}
main.c
#include "public.h"
int main(void)
{
//2号分组:2bit给抢占 2bit给响应 0-3 0-3
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SysTick_Init();
KEY_Init();
LED_Init();
GPIO_ResetBits(GPIOF,GPIO_Pin_9); //如果复位,则灯亮
WWDG_Init_Config();
while(1)
{
Delay_ms(30);
WWDG_SetCounter(0x7f);
//改变灯的状态
}
}
标签:IWDG,窗口,WDG,看门狗,计数器,喂狗,WWDG,STM32F4
From: https://blog.csdn.net/m0_61256689/article/details/141992250