WDG看门狗
- 1、看门狗的简介
- 2、独立看门狗
- 3、窗口看门狗
- 4、独立看门狗代码
- 5、窗口看门狗代码
1、看门狗的简介
1、看门狗的作用是监控程序的运行状态。当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性。
2、看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时(即程序卡死,没有执行到重置计数器的代码),看门狗硬件电路就自动产生复位信号。
3、STM32中内置了2个看门狗:
独立看门狗(IWDG):独立工作,对时间精度要求较低。
窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用。
2、独立看门狗
1、下图为独立看门狗的内部结构框图。
如图所示:独立看门狗就如同一个自减定时器,当减到0的时候就会触发复位信号。独立看门狗的时钟源来源于内部低速时钟LSI,然后通过分频器后,脉冲进入12位的自减计数器,来一个脉冲,计数器自减1。而重装载寄存器设定重装值,通过键寄存器减重装值配置到自减计数器里面,如图寄存器都是工作在1.8v的供电区域,而看门狗的计数功能工作在VDD供电区域,所以能在停机/待机模式下正常的工作。
2、下图位键寄存器的数据对应的操作:
3、独立看门狗的溢出事件(超时时间)
如图:当PR寄存器里面写入0时,则分频器为4分频,时钟脉冲 = 40KHz / 4 = 10KHz,则一个时钟周期T = 1 / 10KHz = 0.1ms,超时的时间 = 0.1ms * (RL寄存器里面的值 + 1),RL重装寄存器最小值 = 0,RL重装寄存器最大值 = 0xFFF(4095)。所以超时时间 = <0.1ms,409.6ms>。
3、窗口看门狗
1、下图为窗口看门狗的内部结构框图
如图所示:窗口看门狗的时钟来源于PCLK1(36MHz),然后通过4096分频后,在通过看门狗分频器后进入看门狗的6为自减计数器CNT,其实CNT计数只有后5位有效,第6位作用为标志位,当第6位为1时,看门狗不触发复位信号,当第6位由1->0时,看门狗触发复位信号。即CNT:由1xxxxx变为011111,看门狗触发复位。而窗口的寄存器的值(进入窗口时间) < 自减计数器的值的时候,是不允许喂狗(计数器重装),若发生喂狗则会触发复位,所以只能在窗口的时间里面喂狗。
2、超时时间和窗口时间
4、独立看门狗代码
与之相关标准库编程接口:
因此不用独立开启LSI振荡器了
/*
独立看门狗的简单使用
*/
#include "stm32f10x.h"
#include "OLED.h"
#include "Delay.h"
int main(void)
{
OLED_Init();
OLED_Clear();
OLED_ShowString(1,1,"IWDG Test:");
/*
* 在OLED上面显示是复位建导致的复位还是独立看门狗导致的复位
*/
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == 1)//独立看门狗导致的复位,置标志位
{
OLED_ShowString(2,1,"IWDGRST");
Delay_ms(500);
OLED_ShowString(2,1," ");
RCC_ClearFlag();//清除标志位
}
else
{
OLED_ShowString(4,1,"PINRST");
Delay_ms(500);
OLED_ShowString(4,1," ");
RCC_ClearFlag();//清除标志位
}
/*
* 配置独立看门狗的超时时间为1000ms,即在1000ms内喂狗,就不会执行复位
* 如果超过1000ms没有喂狗(程序卡死),那么就会执行复位
*/
/* 1、解除写保护 */
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
/* 2、配置预分频值,由于超时时间 = 1000ms,所以 Prescaler ≧ 16 */
IWDG_SetPrescaler(IWDG_Prescaler_16);//16分频
/* 3、配置重装值,使其超时时间 = 1000ms,
40KHz / 16 = 2.5KHz,1 / 2.5KHz = 0.4ms,1000ms / 0.4ms = 2500 < 4095
*/
IWDG_SetReload(2499);
/* 4、使能独立看门狗 */
IWDG_Enable();
while(1)
{
/* 每隔800ms喂狗一次,因为800ms < 1000ms,所以不会触发复位*/
IWDG_ReloadCounter();//喂狗
OLED_ShowString(2,1,"weigou");//通过OLED不断显示“weigou”来表示不断执行喂狗操作
Delay_ms(400);
OLED_ShowString(2,1," ");
Delay_ms(400);
}
}
5、窗口看门狗代码
与之相关标准库编程接口:
/*
窗口看门狗的简单使用
*/
#include "stm32f10x.h"
#include "OLED.h"
#include "Delay.h"
int main(void)
{
OLED_Init();
OLED_Clear();
OLED_ShowString(1,1,"WWDG Test:");
/*
* 在OLED上面显示是复位建导致的复位还是独立看门狗导致的复位
*/
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == 1)//独立看门狗导致的复位,置标志位
{
OLED_ShowString(2,1,"WWDGRST");
Delay_ms(500);
OLED_ShowString(2,1," ");
RCC_ClearFlag();//清除标志位
}
else
{
OLED_ShowString(4,1,"PINRST");
Delay_ms(500);
OLED_ShowString(4,1," ");
RCC_ClearFlag();//清除标志位
}
/*
* 配置窗口看门狗的超时时间为50ms,窗口时间为20ms。则进入窗口的时间为50ms-20ms = 30ms
* 即在30ms~50ms内喂狗,就不会执行复位 如果<30ms或者>50ms没有喂狗时,那么就会执行复位
*/
/* 1、开启PCLK1的时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
/* 2、配置预分频值,由于超时时间 = 50ms,所以 Prescaler = 8,计数得出计数器的值为55*/
WWDG_SetPrescaler(WWDG_Prescaler_8);
/* 3、配置窗口值,由于计入窗口时间 = 30ms,所以 Prescaler = 8,计数得出计数器的值为33*/
WWDG_SetWindowValue(0x40 | (54-33));
/* 4、配置计数器值 */
WWDG_Enable(0x40 | 54);
while(1)
{
/* 每隔40ms喂狗一次,因为30ms < 40ms < 50ms,所以不会触发复位*/
OLED_ShowString(2,1,"weigou");//通过OLED不断显示“weigou”来表示不断执行喂狗操作
Delay_ms(20);
OLED_ShowString(2,1," ");
Delay_ms(20);
WWDG_SetCounter(0x40 | 54);//喂狗
}
}