STM32 第16讲 窗口看门狗(WWDG工作原理/寄存器/超时计算/配置步骤/实验源码/IWDG&WWDG对比)

基础知识

简介

  • WWDG: Window watchdog,窗口看门狗
  • 本质: 能产生系统复位信号提前唤醒中断的计数器
  • 特性:
  1. 递减的计数器
  2. 当递减计数器值从 0x40减到0x3F时复位(即T6位跳变到0)
  3. 计数器的值大于W[6:0]值时喂狗会复位
  4. 提前唤醒中断 (EWI):当递减计数器等于 0x40 时可产生
    喂狗:在窗口期内重装载计数器的值,防止复位

作用

  • 用于监测单片机程序运行时效是否精准,主要检测软件异常
  • 应用:需要精准检测程序运行时间的场合(时钟来自于系统时钟)

工作原理

在这里插入图片描述
递减计数器的值递减过程中,当 T[6:0]>W[6:0]是不允许刷新 T[6:0]的值,即不允许喂狗,否则会产生复位。只有在 W[6:0]<T[6:0]< 0x3F 这个时间可以喂狗,这就是喂狗的窗口时间。当T[6:0]=0x3F,即 T6 位为 0 这一刻,也会产生复位。上限值 W[6:0]是由用户自己设置,但是一定要确保大于 0x40,否则就不存在上图的窗口了,下限值 0x40 是固定的,不可修改。

框图

在这里插入图片描述

  • WWDG 有一个来自 RCC 的 PCLK1 输入时钟,经过一个 4096 的分频器(4096 分频在设计时已经设定死了,图中并没有给出来,但我们可以通过查看寄存器WWDG_CFR 的 WDGTB 位的描述知道),再经过一个分频系数可选(1、2、4、8)的可编程预分频器提供时钟给一个 7 位递减计数器。
  • 结合寄存器分析窗口看门狗的上限值和下限值。W[6:0] 是 WWDG_CFR 寄存器的低 7 位,用于与递减计数器 T[6:0]比较的窗口值,也就是我们说的上限值,由用户设置。0x40 就是下限值,递减计数器达到这个值就会产生复位。T6 位就是WWDG_CR 寄存器的位 6,即递减计数器 T[6:0]的最高位。

寄存器

控制寄存器 WWDG_CR

在这里插入图片描述

  • 该寄存器只有低八位有效,其中 T[6:0]用来存储看门狗的计数器的值,随时更新的,每隔(4096×2^ WDGTB[2:0])PCLK 个周期减 1。当该计数器的值从 0x40 变为 0x3F 的时候,将产生看门狗复位。
  • WDGA 位则是看门狗的激活位,该位由软件置 1,启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了。

配置寄存器 WWDG_CFR

在这里插入图片描述

  • 该寄存器中的 EWI 位是提前唤醒中断,如果该位置 1,当递减计数器等于 0x40 时产生提前唤醒中断,我们就可以及时喂狗以避免 WWDG 复位。因此,我们一般都会用该位来设置中断,当窗口看门狗的计数器值减到 0x40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。注意这里在进入中断后,必须在不大于 1 个窗口看门狗计数周期的时间(在 pclk1 频率为 42M 且 WDGTB 为0 的条件下,该时间为 97.52us)内重新写 WWDG_CR,否则,看门狗将产生复位!

状态寄存器 WWDG_SR

在这里插入图片描述
该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位 0 有效,其他都是保留位。当计数器值达到 0x40 时,此位由硬件置 1。它必须通过软件写 0 来清除。对此位写 1 无效。即使中断未被使能,在计数器的值达到 0x40 的时候,此位也会被置 1。

超时时间计算

  • 计算公式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

配置步骤

  • 工作参数初始化
  • Msp 初始化
  • 设置优先级、使能中断
  • 编写中断服务函数
  • 重定义提前唤醒回调函数
  • 在窗口期内喂狗

函数介绍

在这里插入图片描述

HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg)
{
  /* Check the WWDG handle allocation */
  if (hwwdg == NULL)
  {
    return HAL_ERROR;
  }

typedef struct
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
{
  WWDG_TypeDef      *Instance;  /*!< Register base address */

  WWDG_InitTypeDef  Init;       /*!< WWDG required parameters */

#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
  void (* EwiCallback)(struct __WWDG_HandleTypeDef *hwwdg);                  /*!< WWDG Early WakeUp Interrupt callback */

  void (* MspInitCallback)(struct __WWDG_HandleTypeDef *hwwdg);              /*!< WWDG Msp Init callback */
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
} WWDG_HandleTypeDef;


 /* 初始化结构体 */
 typedef struct
{
  uint32_t Prescaler;     /*!< Specifies the prescaler value of the WWDG.
                               This parameter can be a value of @ref WWDG_Prescaler */

  uint32_t Window;        /*!< Specifies the WWDG window value to be compared to the downcounter.
                               This parameter must be a number Min_Data = 0x40 and Max_Data = 0x7F */

  uint32_t Counter;       /*!< Specifies the WWDG free-running downcounter  value.
                               This parameter must be a number between Min_Data = 0x40 and Max_Data = 0x7F */

  uint32_t EWIMode ;      /*!< Specifies if WWDG Early Wakeup Interrupt is enable or not.
                               This parameter can be a value of @ref WWDG_EWI_Mode */

} WWDG_InitTypeDef;
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
{
  /* Write to WWDG CR the WWDG Counter value to refresh with */
  WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));

  /* Return function status */
  return HAL_OK;
}

实验

wwdg.c

  • 初始化WWDG
WWDG_HandleTypeDef g_wwdg_handler;        /* 窗口看门狗句柄 */

/**
 * @brief       初始化窗口看门狗
 * @param       tr: T[6:0],计数器值
 * @param       tw: W[6:0],窗口值
 * @note        fprer:分频系数(WDGTB),范围:WWDG_PRESCALER_1~WWDG_PRESCALER_8,表示2^WDGTB分频
 *              Fwwdg=PCLK1/(4096*2^fprer). 一般PCLK1=42Mhz
 * @retval      无
 */
void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer)
{
    g_wwdg_handler.Instance = WWDG;
    g_wwdg_handler.Init.Prescaler = fprer;         /* 设置分频系数 */
    g_wwdg_handler.Init.Window = wr;               /* 设置窗口值 */
    g_wwdg_handler.Init.Counter = tr;              /* 设置计数器值 */
    g_wwdg_handler.Init.EWIMode = WWDG_EWI_ENABLE; /* 使能窗口看门狗提前唤醒中断 */
    HAL_WWDG_Init(&g_wwdg_handler);                /* 初始化WWDG */
}
  • MSP回调函数
/**
 * @brief       WWDG底层驱动,时钟配置,中断配置
                此函数会被HAL_WWDG_Init()调用
 * @param       hwwdg:窗口看门狗句柄
 * @retval      无
 */
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
    __HAL_RCC_WWDG_CLK_ENABLE();            /* 使能窗口看门狗时钟 */

    HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3);  /* 抢占优先级2,子优先级为3 */
    HAL_NVIC_EnableIRQ(WWDG_IRQn);          /* 使能窗口看门狗中断 */
}
  • 中断服务函数
/**
 * @brief       窗口看门狗中断服务程序
 * @param       无
 * @retval      无
 */
void WWDG_IRQHandler(void)
{
    HAL_WWDG_IRQHandler(&g_wwdg_handler);     /* 调用WWDG共用中断处理函数 */
}
  • 提前唤醒回调函数
/**
 * @brief       中断服务函数处理过程
                此函数会被HAL_WWDG_IRQHandler()调用
 * @param       无
 * @retval      无
 */
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
    HAL_WWDG_Refresh(&g_wwdg_handler);        /* 更新窗口看门狗值 */
    LED1_TOGGLE();                          /*  绿灯闪烁 */
}

wwdg.h

#ifndef __WDG_H
#define __WDG_H

#include "./SYSTEM/sys/sys.h"

void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer); /*窗口看门狗初始化*/
extern WWDG_HandleTypeDef g_wwdg_handle;

#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/WDG/wdg.h"


int main(void)
{    
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    LED0(0);                                /* 点亮LED0(红灯) */    
    if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET) 
    {
        printf("窗口看门狗复位\r\n");
        __HAL_RCC_CLEAR_RESET_FLAGS();
    }
    else
    {
        printf("外部复位\r\n\r\n");
    }
    printf("请在窗口期内喂狗!\r\n\r\n");
    delay_ms(500);                           
    wwdg_init(0X7F, 0X5F, WWDG_PRESCALER_8);/* 计数器值为7f,窗口寄存器为5f,分频数为8 */
    
    while(1)
    {
        delay_ms(60);                       /* 窗口期为24.98~49.97ms,更改时间为20/40/60验证实验结果 */
        HAL_WWDG_Refresh(&g_wwdg_handler);
        LED0_TOGGLE();                           /* LED0(红灯)闪烁 */
    }
}

IWDG与WWDG对比

在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值