写在前面:上节我们学习了独立看门狗(IWDG)相关知识,本节我们来学习另外一个看门狗——WWDG窗口看门狗,内容并不难,但是目前这些看门狗的具体内容,还没有得到一个很好的应用,还是先学习吧,后面应该会得到一个应用。

目录

一、WWDG介绍

二、WWDG工作原理

三、WWDG工作框图

  四、WWDG相关寄存器      

4.1控制寄存器WWDG_CR

4.2配置寄存器(WWDG_CFR)

4.3状态寄存器WWDG_SR

4.4WWDG超时时间计算

五、WWDG配置步骤

5.1配置步骤

5.2相关HAL库函数介绍

六、实验源码 

6.1实验说明

6.2源码

6.3实验现象

6.4 IWDG同WWDG的区别:  

一、WWDG介绍

全称:Windows watchdog,即窗口看门狗;

本质:能产生系统复位信号提前唤醒中断的计数器;

特性:1、递减计数器;

           2、产生复位信号的条件有两个:当递减计数器从0x40减至0x3F时会产生复位信号当计数器的值大于W[6:0]值时,喂狗会产生复位信号。后面会对这两点做详细的说明。

          3、提前唤醒中断(EWI):当递减计数器等于0x40时,会产生一个提前唤醒中断。

喂狗:在窗口期内重装载计数器的值,防止复位信号的产生;

作用:用于监测单片机程序运行时效是否准确,主要检测软件异常。

应用:在需要精准检测程序运行时间的场合;

二、WWDG工作原理

其工作原理用下图可以进行一个很好的说明:

        如上图所示:首先WWDG的本质是一个递减计数器,是一个能够产生复位信号以及中断信号的递减计数器 ,纵坐标为递减计数器的值,此递减计数器共有7位(T[6:0]),这样递减计数器的最大值位127,而且递减计数器的值是可以进行软件设置的。

        递减计数器的值一旦给定后,随着时钟信号的到来,递减计数器的值进行递减。此时我们会设置一个窗口上限值W[6:0],窗口上限值共7位,最大值为127。在递减计数器初值与窗口上限期这一段时间,我们称为非窗口期,这个时期内喂狗就会产生复位。

        既然有窗口上限值,那么也一定有窗口下限值,窗口下限值为0x3F,是固定的不能改变。那么窗口上限值就必须比窗口下限值高,否则无窗口期。窗口期就是窗口上限值到窗口下限值之间的时期。在窗口期内进行喂狗是不会产生复位的,而当递减计数器的值减至窗口下限值时,也会产生复位。

        此外,如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI)。

综上所述:

产生复位的条件:1、当递减计数器的值小于0x40,(若看门狗被启动)则产生复位。2、 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。

产生中断的条件:启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI)。

三、WWDG工作框图

        如上图所示,其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,(若看门狗被启动)则产生复位 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。

  四、WWDG相关寄存器      

4.1控制寄存器WWDG_CR

该寄存器的功能为:用于使能窗口看门狗工作,以及计数器的值。

控制寄存器共有8位:位7:为上面流程图中的WDGA激活位 。T[6:0]用来存储看门狗的计数器的值,随时更新的,每隔 (4096×2^ WDGTB[2:0])PCLK 个周期减 1。当该计数器的值从 0x40 变为 0x3F 的时候,将产生看门狗复位。

注:此处同IWDG不同的是,WWDG中计数器的值可以直接赋,不要在经过什么其他的寄存器进行赋值。

4.2配置寄存器(WWDG_CFR)

该寄存器共有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]设置窗口上限值。

4.3状态寄存器WWDG_SR

        该寄存器只有一位有效,当计数器值达到40h时,此位由硬件置’1’。它必须通过软件写’0’来清除。对此位写’1’无效。若中断未被使能,此位也会被置’1。主要用于判断是否发生了WWDG提前唤醒中断。

4.4WWDG超时时间计算

五、WWDG配置步骤

5.1配置步骤

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();

5.2相关HAL库函数介绍

HAL_WWDG_Init()使能WWDG,设置预分频系数和窗口值等

该函数的参数主要有:外设基地址,预分频系数,窗口值,计数器值,以及是否开启中断。

HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)进行重装载值,也就是喂狗。

六、实验源码 

6.1实验说明

        本次我们所设计的实验,主要是基于WWDG的一个操作,利用喂狗进行LED等的控制。设置一个计数器值为0X7F,窗口值为0X5F,预分频系数为8。在中断中喂狗,并且LED1 开始不停的闪烁。喂一次狗,LED1的状态发生一个转变。

6.2源码

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

6.3实验现象

        我们首先进入main函数,初始化系统和用户外设,然后点亮LED0,延时300ms后,初始化看门狗,进入循环,关闭LED0。然后在看门狗中进行LED1的状态转变与喂狗,如果LED1的状态发生转变,则说明喂狗成功。

窗口看门狗

6.4 IWDG同WWDG的区别 

STM32---IWDG(独立看门狗),超详细,小白入-CSDN博客

IWDGWWDG
时钟源LSI 40KHzPCLK1
复位条件递减计数到0

计数值大于窗口值,喂狗

计数值减到0X3F

中断没有中断计数值减到0x40可产生中断
递减计数器12位7位
应用场合防止程序跑飞,死循环检测程序时效

总结:本节我们接着独立看门狗的内容,讲述了窗口看门狗的内容,主要有简介、工作原理、工作框图、相关寄存器以及配置步骤,还有相关实验进行说明,以及IWDG同WWDG的对比。内容不算太难,大家可以多多尝试。

创作不易,还请大家多多点赞支持!!!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐