目录
一. 前言
1. STM32内置看门狗
2. 看门狗的实质
二. 独立看门狗
1. 独立看门狗的系统框图
2. 键寄存器
3. IWDG的超时时间
三. 窗口看门狗
1. 窗口看门狗的系统框图
2. WWDG的工作特性
四. 独立看门狗和窗口看门狗的代码配置
1. 独立看门狗
2. 窗口看门狗
一. 前言
1. STM32内置看门狗
STM具有两个内置看门狗,分别是独立看门狗(IWDG)和窗口看门狗(WWDG)。其中,独立看门狗独立工作,对时间精度要求较低。窗口看门狗则要求看门狗在精确计时窗口起作用。
2. 看门狗的实质
看门狗实质上是一个定时器,当在指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就会自动产生复位信号。
所以看门狗专门用来监控程序的运行状态,当发生程序卡死或跑飞等情况的时候,看门狗能够及时复位程序,防止陷入长时间的卡死。这大大提高了我们程序的健壮性。
二. 独立看门狗
1. 独立看门狗的系统框图
如下所示:
从这个系统框图中的左下角部分我们可以看到,输入时钟是LSI内部低速时钟,频率是40KHz。
当时钟进入后,看门狗就会对重装载值进行递减,如果递减到0,还没有进行喂狗(手动重装计数器)操作,那么就会使IWDG复位,也就是触发了我们的独立看门狗进行复位。
对于右上角的这个键寄存器,也可以说是很重要的。键寄存器本质上是一个控制寄存器,用于控制硬件电路的工作。所以我们可以对它写入一些值,用来实现某些功能。
2. 键寄存器
如下所示:
从中我们可以看出,我们的喂狗操作,就是在键寄存器中写入0xAAAA来完成的。
由于我们的这个喂狗等操作并不是根据标志位来决定的,而是通过写入值得方式,所以我们的指令抗干扰能力是非常强的。
键寄存器有抗干扰能力,不能偏心,所以在IWDG框图中的PR,SR,RLR这三个寄存器也要有抗干扰能力,所以就给了它们一个写保护。只有当我们写入0x5555给键寄存器的时候,才能解除它的写保护。这个在后面我们编写代码的时候就会出现,当我们想要写入预分频器值和重装载值的时候,就需要先进行这一步操作。
3. IWDG的超时时间
公式如下所示:
其中PR预分频系数和RL重装载值都不是固定的。
三. 窗口看门狗
1. 窗口看门狗的系统框图
我们窗口看门狗跟独立看门狗的区别之一就在于它拥有一个最晚超时时间和一个最早超时时间。
其中看门狗配置寄存器CFR就是窗口时间(也就是喂狗的最早时间界限)。
2. WWDG的工作特性
1)当CNT递减计数器值小于0x40时,WWDG会产生复位,也就是触发了WWDG看门狗。
2)CNT递减计数器在窗口值W[6:0]外被重新装载时,WWDG产生复位。
所以我们需要定期写入WWDG_CR寄存器(喂狗),才能避免WWDG复位。
3. WWDG的超时和窗口时间
之所以多乘以一个4096,是因为在上面窗口看门狗框图里的PCLK1进来时,是先执行了一个固定的4096分频。主要是为了降低速度。毕竟36MHz还是很快的。
四. 独立看门狗和窗口看门狗的代码配置
1. 独立看门狗
独立看门狗的配置流程如下所示:
1)开启时钟,LSI必须开启。在手册6.2.9看门狗时钟这一节中,有一句话,如果独立看门狗已经由硬件选项或软件启动,那么LSI振荡器将被强制在打开状态,并且不能关闭。在LSI振荡器稳定后,时钟供应给IWDG。
2)写入预分频器和重装载值。
这个别忘了上面我们说的先解除写保护哦。
3)写入键值启动开门狗
4)写入键值不断喂狗
相关代码如下所示:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
int main(void)
{
OLED_Init();
Key_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);
IWDG_SetReload(2499); //1000ms
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);
}
}
2. 窗口看门狗
配置流程如下所示:
1)开启窗口看门狗APB1的时钟。
2)配置各个寄存器。比如预分频和窗口值。窗口看门狗没有写保护,所以第二步就可以直接写这些寄存器了。
3)写入控制寄存器CR。控制寄存器包括看门狗使能位,计数器溢出标志位和计数器有效位。这些东西需要一起设置。
相关代码如下所示:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
int main(void)
{
OLED_Init();
Key_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); //30ms
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);
}
}