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

①独立看门狗的时钟信号来源是LSI(内部低速时钟),只有40kHZ的频率.
②IWDG由主电源VDD直接供电,即使是在停机和待机模式下也能正常工作.
- IWDG键寄存器
IWDG寄存器实质上是控制寄存器,用来控制电路的运行,IWDG是程序卡死复位的一道有利屏障,所以要保证其各项指令不被其他信号干扰,所以写入键寄存器的值很有特点,如图:

如:0x5555的二进制值是:0101 0101 0101 0101;0xAAAA的二进制值是:1010 1010 1010 1010,这种0和1交叉出现的二进制值有效防止了因信号干扰而造成某一位由0变1或由1变0.
-IWDG超时时间
计算公式如下:

IWDG中的分频系数较多,有4 8 16 32 64 128 256 这7中分频系数可选,各分频系数对应的最短响应时间和最长响应时间如图:

具体需要哪种分频系数要根据自己设置的响应时间来查找.
- WWDG(窗口看门狗)
-
框图:

-
WWDG超时时间
计算公式:

WWDG的有1 2 4 8四种分频,各分频系数对应的最短响应时间和最长响应时间如图:

-
WWDG工作特性
①递减计数器T[6:0]的值小于0x40时,WWDG产生复位.
②递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位.
③递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位.
④定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位.1
⑤当把T0~ T5看作一个计数器体系,把T6单拎出来看作另一个体系时:
WWDG的T0~T5是6位的计数器,T6是溢出标志位,当T6位为1时,表示没有溢出,为0时,表示溢出.
例如:当给T6~T0值为:1111 111时,每来一个脉冲信号,值就减1,当减到1000 000时(十六进制为0x40),只剩下T6位位1,其余为全为0,再来一个脉冲信号(值再减去1),T6的1就会变为0,这就产生了溢出标志位.
⑥时钟信号来源于APB1,36MHZ.
⑦配置寄存器W0~W6用来设置WWDG的最早界限的计数值.
⑧当看门狗控制寄存器(WWDG_CR)的值大于看门狗配置寄存器(WWDG_CFR)的值,此时表示喂狗太早,程序复位.当看门狗控制寄存器(WWDG_CR)的值小于看门狗配置寄存器(WWDG_CFR)的值,看门狗控制寄存器(WWDG_CR)的值自减到0,此时表示喂狗太晚,程序复位.所以在WWDG_CFR的值和WWDG_CR的自减为0的值之间形成了一个窗口值,只有WWDG在此窗口值之间运行时才不会使系统复位.
-WWDG运行流程图:
0x3F是看门狗控制寄存器(WWDG_CR)溢出计数器为0时,即T6位为0,其他位全为1时.
独立看门狗&窗口看门狗
独立看门狗(IWDG)
- 接线图如下:

- 本工程只涉及main.c文件
main.c代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
int main(void)
{
/*模块初始化*/
OLED_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的写保护
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//配置超时时间位1000ms,使用的系统时钟LSI的频率位40khz,默认开启
//配置分频系数
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(600);
OLED_ShowString(4,1," ");
Delay_ms(200);
}
}
值得注意的是:
①IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);解除IWDG的写保护后,在执行喂狗操作 (IWDG_ReloadCounter())或向键寄存器(IWDG_KR)写入除0x5555之外的任何其他值写保护会自动生效.
②按键按住不放,就会阻塞程序.
③运行时间超过IWDG的设置时间,IWDG就会复位,程序代码从头执行.
- IWDG程序执行流程图:
窗口看门狗(WWDG)
- 接线图如下:

- 本工程只涉及main.c文件
main.c代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
int main(void)
{
/*模块初始化*/
OLED_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);
WWDG_SetWindowValue(0x40 | 21);
WWDG_Enable(0x40 | 54); //50ms
while (1)
{
//按住按键不放,就会阻塞程序
Key_GetNum();
OLED_ShowString(4,1,"FEED");
Delay_ms(20);
OLED_ShowString(4,1," ");
Delay_ms(20);
WWDG_SetCounter(0x40 | 54);
}
}
值得注意的是:
①根据WWDG的超时时间公式,要想得到超时时间位50ms,即预分频(WDGTB预分频系数)给8,重装值(T[5:0])给54,0x40 | 54的含义是将寄存器T6位设置为1(1表示不溢出).
②根据WWDG的窗口时间公式,知道了WDGTB预分频系数以及T[5:0]的重装值,要想得到窗口时间位30ms,则W[5:0]的值应为21,0x40 | 21的含义是将寄存器W6位置为1,W6应该也是表示溢不溢出的标志位.
③WWDG没有重装寄存器,重装时直接给寄存器赋值即可.
④循环中的代码WWDG_SetCounter(0x40 | 54);不应放在循环开头,这会导致在程序一启动设置的WWDG的值大于窗口值(过早喂狗).喂狗时间应在0~30ms内算正常.
- 程序运行流程图:
1334

被折叠的 条评论
为什么被折叠?



