概述:
- WDG(Watchdog) 看门狗,看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能计时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性
- 看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号
- STM32内置两个看门狗:
- 独立看门狗(IWDG):独立工作,对时间精度要求较低
- 窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用
一、独立看门狗(IWDG)
1、框图
首先,利用的是LSI(40KHz)时钟信号,先通过8位预分频器进行分频,会产生一个状态标志位给状态寄存器,分频后的信号来驱动计数器递减。
重装载寄存器是12位的,值是4096,给计数器重装载值。看门狗被激活后,则在计数器计数至0x000时产生复位。
键寄存器:本质上是控制寄存器,用于控制硬件电路的工作,在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率。
键寄存器的值:
超时时间:TIWDG = TLSI × PR预分频系数 × (RL + 1) 其中:TLSI = 1 / FLSI。
2、代码:
main.c:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "delay.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_WriteAccessCmd(IWDG_WriteAccess_Enable); //解除写保护
IWDG_SetPrescaler(IWDG_Prescaler_16); //16分频
IWDG_SetReload(2499); //重装值,超时时间为1s
IWDG_ReloadCounter(); //重装载计数器
IWDG_Enable(); //启动看门狗
while(1)
{
IWDG_ReloadCounter();
OLED_ShowString(4,1,"FEED");
Delay_ms(410);
OLED_ShowString(4,1," ");
Delay_ms(600);
}
}
二、窗口看门狗(WWDG)
1、作用
窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在T6位变成0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个MCU复位。在递减计数器达到窗口寄存器数值之前,如果7位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个MCU复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。
主要特性:
- 可编程的*运行递减计数器
- 条件复位:当递减计数器的值小于0x40, (若看门狗被启动)则产生复位。当递减计数器在窗口外(由框图可以知道,T6:0>W6:0时)被重新装载, (若看门狗被启动)则产生复位。
- 如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以被用于重装载计数器以避免WWDG复位,也就是看门狗要中断了,不想让它中断,就可以进行唤醒中断。
2、框图
利用PCLK1时钟(36KHz)通过预分频器(2位)后作为计数器的输入信号。
根据框图可知,复位有两种:
1、超时复位:当递减计数器的值小于0x40,根据下图WWDG_CR可知,有7位计数器,只有低6位进行计数,而T6是做为溢出标志位,T6初始值为1,,当变为0时就会产生复位信号,在经过非下变为1,通过或符号就会产生1,与WDGA相与就会复位。WDGA是一个类似于开关,为1打开看门狗,为0关闭看门狗。
2、窗口复位:当T6:0>W6:0且递减计数器被重装载,这是会产生复位信号。
3、时间计算
超时时间: TWWDG = TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] + 1)
窗口时间: TWIN = TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] - W[5:0]) 其中:TPCLK1 = 1 / FPCLK1
这个4096分频在框图上没有展示出来。手册寄存器有写。
4、工作特性
- 递减计数器T[6:0]的值小于0x40时,WWD*生复位
- 递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWD*生复位
- 递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免
- WWDG复位 定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位
5、代码
main.c:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "delay.h"
int main(void)
{
OLED_Init();
OLED_ShowString(1,1,"IWDG TEST");
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST)==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);
}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
WWDG_SetPrescaler(WWDG_Prescaler_8);
//窗口时间就是某一时间间隔内
//小于窗口时间会复位
//大于窗口时间小于等于超时时间不会复位
WWDG_SetWindowValue(0x40+21); //30ms
WWDG_Enable(0x40+54); //50ms
while(1)
{
// OLED_ShowString(4,1,"FEED");
// Delay_ms(20);
// OLED_ShowString(4,1," ");
Delay_ms(49);
WWDG_SetCounter(0x40+54); //喂狗,设置最大超时时间为50ms
}
}