写在前面:上节我们学习了独立看门狗(IWDG)相关知识,本节我们来学习另外一个看门狗——WWDG窗口看门狗,内容并不难,但是目前这些看门狗的具体内容,还没有得到一个很好的应用,还是先学习吧,后面应该会得到一个应用。
目录
全称:Windows watchdog,即窗口看门狗;
本质:能产生系统复位信号和提前唤醒中断的计数器;
特性:1、递减计数器;
???????????2、产生复位信号的条件有两个:当递减计数器从0x40减至0x3F时会产生复位信号;当计数器的值大于W[6:0]值时,喂狗会产生复位信号。后面会对这两点做详细的说明。
? ? ? ? ? 3、提前唤醒中断(EWI):当递减计数器等于0x40时,会产生一个提前唤醒中断。
喂狗:在窗口期内重装载计数器的值,防止复位信号的产生;
作用:用于监测单片机程序运行时效是否准确,主要检测软件异常。
应用:在需要精准检测程序运行时间的场合;
其工作原理用下图可以进行一个很好的说明:
????????如上图所示:首先WWDG的本质是一个递减计数器,是一个能够产生复位信号以及中断信号的递减计数器 ,纵坐标为递减计数器的值,此递减计数器共有7位(T[6:0]),这样递减计数器的最大值位127,而且递减计数器的值是可以进行软件设置的。
? ? ? ? 递减计数器的值一旦给定后,随着时钟信号的到来,递减计数器的值进行递减。此时我们会设置一个窗口上限值W[6:0],窗口上限值共7位,最大值为127。在递减计数器初值与窗口上限期这一段时间,我们称为非窗口期,这个时期内喂狗就会产生复位。
? ? ? ? 既然有窗口上限值,那么也一定有窗口下限值,窗口下限值为0x3F,是固定的不能改变。那么窗口上限值就必须比窗口下限值高,否则无窗口期。窗口期就是窗口上限值到窗口下限值之间的时期。在窗口期内进行喂狗是不会产生复位的,而当递减计数器的值减至窗口下限值时,也会产生复位。
? ? ? ? 此外,如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI)。
综上所述:
产生复位的条件:1、当递减计数器的值小于0x40,(若看门狗被启动)则产生复位。2、 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。
产生中断的条件:启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI)。
????????如上图所示,其WWDG的工作框图或者说是工作流程,首先,WWDG的的时钟信号来自PCLK1,(即图1部分)然后经过看门狗预分频器进行分频(即图2部分)此处也涉及相关的寄存器进行操作。然后再到看门狗控制寄存器(即图3部分),共8位,其中首位为激活位,后面为T[6:0]的值。?
? ? ? ? 看门狗配置寄存器(即图4部分),为窗口上限值,当图3看门狗控制寄存器的值W6大于图4看门狗配置寄存器的值T6,则说明已经进入窗口期(比较器输出0),否则为非窗口期(比较器输出1)。
? ? ? ? 在上图的左边还有三个逻辑门电路,
????????a为一个与门,即要产生复位信号必须有两点:1、WDGA(激活位值1);2、b门输出1。
? ? ? ? b为一个或门,要产生1有两种选择,1、T6为0(取翻后就是1)即递减计数器减至窗口下限值。2、c门输出1。
? ? ? ? c为一个与门,要产生1必须有两个条件:1、进行喂狗。2、非窗口期(比较器输出1)。
????????这个电路也满足我们所说的产生复位的两种选择:当递减计数器的值小于0x40,(若看门狗被启动)则产生复位或?当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。
该寄存器的功能为:用于使能窗口看门狗工作,以及计数器的值。
控制寄存器共有8位:位7:为上面流程图中的WDGA激活位?。T[6:0]用来存储看门狗的计数器的值,随时更新的,每隔 (4096×2^ WDGTB[2:0])PCLK 个周期减 1。当该计数器的值从 0x40 变为 0x3F 的时候,将产生看门狗复位。
注:此处同IWDG不同的是,WWDG中计数器的值可以直接赋,不要在经过什么其他的寄存器进行赋值。
该寄存器共有10位;
位9;WEI:提前唤醒中断,如果该位置 1,当递减计数器等于 0x40 时产生提前唤醒中断,我们就可以及时喂狗以避免 WWDG 复位。我们一般都会用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。需要注意这里在进入中断后,必须在不大于 1 个窗口看门狗计数周期的时间(在 pclk1 频率为 36M 且 WDGTB 为 0 的条件下,该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产生复位!
位8:7 WDGTB:设置预分频系数。
位6:0 W[6:0]设置窗口上限值。
????????该寄存器只有一位有效,当计数器值达到40h时,此位由硬件置’1’。它必须通过软件写’0’来清除。对此位写’1’无效。若中断未被使能,此位也会被置’1。主要用于判断是否发生了WWDG提前唤醒中断。
1、WWDG工作参数初始化 HAL_WWDG_Init();
2、WWDGMsp初始化 HAL_WWDG_MspIint(); 配置NVIC,Clock等
3、设置优先级,使能中断 HAL_NVIC_SetPriority()、NVIC_EnabledPQ();
4、编写中断服务函数 WWDG_IPQHandler()、HAL_WWDG_IPQHandler();
5、重定义提前唤醒回调函数 HAL_WWDG_EarlyWakeup Callback();
6、在窗口期喂狗 HAL_WWDG_Refresh();
HAL_WWDG_Init()使能WWDG,设置预分频系数和窗口值等
该函数的参数主要有:外设基地址,预分频系数,窗口值,计数器值,以及是否开启中断。
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)进行重装载值,也就是喂狗。
????????本次我们所设计的实验,主要是基于WWDG的一个操作,利用喂狗进行LED等的控制。设置一个计数器值为0X7F,窗口值为0X5F,预分频系数为8。在中断中喂狗,并且LED1 开始不停的闪烁。喂一次狗,LED1的状态发生一个转变。
main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/wwdg/wwdg.h"
#include "./BSP/led/led.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
led0(0); /* LED点亮 */
delay_ms(300); /* 延时 300ms*/
wwdg_init(0X7F,0X5F,WWDG_PRESCALER_8 ); /* 计数值为 7f,窗口值为 5f,分频数为 8 */
while(1)
{
led0(1);
}
}
wwdg.c
#include "./BSP/wwdg/wwdg.h"
#include "./BSP/led/led.h"
WWDG_HandleTypeDef wwdg_handler;
//窗口看门狗初始化函数
void wwdg_init(uint8_t tr,uint8_t wr,uint32_t fprer )
{
wwdg_handler.Instance= WWDG; //设置寄存器基地址;
wwdg_handler.Init.Counter= tr; //设置计数器的值;
wwdg_handler.Init.Prescaler= fprer; //设置预分频系数;
wwdg_handler.Init.Window= wr; //设置窗口值;
wwdg_handler.Init.EWIMode=WWDG_EWI_ENABLE; //设置使能窗口看门狗唤醒中断;
HAL_WWDG_Init(&wwdg_handler);
}
//WWDG.Msp回调函数
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
__HAL_RCC_WWDG_CLK_ENABLE(); //使能窗口看门狗时钟;
HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3); //设置抢占优先级,子优先级;
HAL_NVIC_EnableIRQ(WWDG_IRQn);
}
//WWDG中断服务函数
void WWDG_IRQHandler(void)
{
HAL_WWDG_IRQHandler(&wwdg_handler);//HAL库函数中断服务函数,会进行回调函数
}
//WWDG提前唤醒函数
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
HAL_WWDG_Refresh(&wwdg_handler);
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5);//led1的状态发生转变。
}
?led.c
#include "./BSP/led/led.h"
void led_init(void)
{
GPIO_InitTypeDef led_Init0;
__HAL_RCC_GPIOB_CLK_ENABLE();
led_Init0.Mode= GPIO_MODE_OUTPUT_PP;
led_Init0.Pin=GPIO_PIN_5;
led_Init0.Pull=GPIO_PULLUP;
led_Init0.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &led_Init0);
GPIO_InitTypeDef led_Init1;
__HAL_RCC_GPIOE_CLK_ENABLE();
led_Init1.Mode= GPIO_MODE_OUTPUT_PP;
led_Init1.Pin=GPIO_PIN_5;
led_Init1.Pull=GPIO_PULLUP;
led_Init1.Speed=GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOE, &led_Init1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5, GPIO_PIN_SET);
}
void led0(uint8_t i)
{
if(i==1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_SET);
}
else
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, GPIO_PIN_RESET);
}
链接:https://pan.baidu.com/s/14dAl0T__LOvOIa1t6NTFaA?
提取码:1022
????????我们首先进入main函数,初始化系统和用户外设,然后点亮LED0,延时300ms后,初始化看门狗,进入循环,关闭LED0。然后在看门狗中进行LED1的状态转变与喂狗,如果LED1的状态发生转变,则说明喂狗成功。
窗口看门狗
STM32---IWDG(独立看门狗),超详细,小白入-CSDN博客
IWDG | WWDG | |
时钟源 | LSI 40KHz | PCLK1 |
复位条件 | 递减计数到0 | 计数值大于窗口值,喂狗 计数值减到0X3F |
中断 | 没有中断 | 计数值减到0x40可产生中断 |
递减计数器 | 12位 | 7位 |
应用场合 | 防止程序跑飞,死循环 | 检测程序时效 |
总结:本节我们接着独立看门狗的内容,讲述了窗口看门狗的内容,主要有简介、工作原理、工作框图、相关寄存器以及配置步骤,还有相关实验进行说明,以及IWDG同WWDG的对比。内容不算太难,大家可以多多尝试。
创作不易,还请大家多多点赞支持!!!