【7】STM32·HAL库·看门狗

本文详细介绍了STM32平台上的独立看门狗(IWDG)和窗口看门狗(WWDG)的工作原理、寄存器结构、寄存器配置方法、溢出时间计算以及编程实战,包括如何使能、初始化、喂狗和检测异常情况。
摘要由CSDN通过智能技术生成

目录

一、IWDG简介

二、IWDG工作原理

三、IWDG框图

四、IWDG寄存器

4.1、关键字寄存器(IWDG_KR)

4.2、预分频器寄存器(IWDG_PR)

4.3、重载寄存器(IWDG_RLR)

4.4、状态寄存器(IWDG_SR)

4.5、寄存器配置操作步骤

五、IWDG溢出时间计算

5.1、IWDG溢出时间计算公式(HAL库)

5.2、寄存器设置分频系数的方法

5.3、IWDG溢出时间计算公式(寄存器)

5.4、IWDG最短最长超时时间(F4/F7/H7)

六、IWDG配置步骤

6.1、使能并初始化IWDG

6.2、及时喂狗

七、编程实战:验证不及时喂狗,系统将复位重启

八、WWDG简介

九、WWDG工作原理

十、WWDG框图

十一、WWDG寄存器

11.1、控制寄存器(WWDG_CR)

11.2、配置寄存器(WWDG_CFR)

11.3、状态寄存器(WWDG_SR)

十二、WWDG超时时间计算

十三、WWDG配置步骤

13.1、使能并初始化WWDG

13.2、窗口期喂狗

十四、编程实战:验证窗口看门狗功能

十五、IWDG和WWDG的主要区别


一、IWDG简介

IWDG(Independent watchdog),即独立看门狗

本质:能产生系统复位信号的计数器

特性:递减的计数器,时钟由独立的 RC 振荡器提供(可在待机和停止模式下运行),看门狗被激活后,当递减计数器计数到 0x000 时产生复位

喂狗:在计数器计数到 0 之前,重装载计数器的值,防止复位

异常

外界电磁干扰或者自身系统(硬件或软件)异常,造成程序跑飞,如:陷入某个不正常的死循环,打断正常的程序运行

作用

主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题

应用

在一些需要高稳定性的产品中,并且对时间精度要求较低的场合

独立看门狗是异常处理的最后手段,不可依赖,应在设计时尽量避免异常的发生!

二、IWDG工作原理

原理图

CPU 必须及时喂狗,否则系统复位重启!

三、IWDG框图

启用 IWDG 后,LSI 时钟会自动开启

LSI 时钟频率并不精确,F1 用 40kHz,F4/F7/H7 用 32kHz 进行计算即可

四、IWDG寄存器

4.1、关键字寄存器(IWDG_KR)

用于喂狗,解除PR和RLR寄存器写访问保护,以及启动看门狗工作

4.2、预分频器寄存器(IWDG_PR)

4.3、重载寄存器(IWDG_RLR)

用于存放重装载值,低12位有效,即最大值为4096

4.4、状态寄存器(IWDG_SR)

4.5、寄存器配置操作步骤

1、通过在键寄存器 (IWDG_KR) 中写入 0xCCCC 来使能 IWDG

2、通过在键寄存器 (IWDG_KR) 中写入 0x5555 来使能寄存器访问

3、通过将预分频器寄存器 (IWDG_PR) 编程为 0~7 中的数值来配置预分频器

4、对重载寄存器 (IWDG_RLR) 进行写操作

5、等待寄存器更新 (IWDG_SR = 0x0000 0000)

6、刷新计数器值为 IWDG_RLR 的值 (IWDG_KR = 0xAAAA)

五、IWDG溢出时间计算

5.1、IWDG溢出时间计算公式(HAL库)

T_{out} 是看门狗溢出时间

f_{IWDG} 是看门狗的时钟源频率

psc 是看门狗预分频系数

rlr 是看门狗重装载值

5.2、寄存器设置分频系数的方法

prer 是 IWDG_PR 的值

5.3、IWDG溢出时间计算公式(寄存器)

5.4、IWDG最短最长超时时间(F4/F7/H7)

六、IWDG配置步骤

6.1、使能并初始化IWDG

取消 PR/RLR 寄存器写保护,设置 IWDG 预分频系数和重装载值,启动 IWDG

HAL库驱动函数:HAL_IWDG_Init()

/**
  * @brief  Initialize the IWDG according to the specified parameters in the
  *         IWDG_InitTypeDef and start watchdog. Before exiting function,
  *         watchdog is refreshed in order to have correct time base.
  * @param  hiwdg  pointer to a IWDG_HandleTypeDef structure that contains
  *                the configuration information for the specified IWDG module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);

关键结构体

/**
  * @brief  IWDG Init structure definition
  */
typedef struct
{
  uint32_t Prescaler;  /*!< Select the prescaler of the IWDG.
                            This parameter can be a value of @ref IWDG_Prescaler */

  uint32_t Reload;     /*!< Specifies the IWDG down-counter reload value.
                            This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */

} IWDG_InitTypeDef;

6.2、及时喂狗

把重装载寄存器的值重载到计数器中,写入 0xAAAA 到 IWDG_KR,喂狗

HAL库驱动函数:HAL_IWDG_Refresh()

/**
  * @brief  Refresh the IWDG.
  * @param  hiwdg  pointer to a IWDG_HandleTypeDef structure that contains
  *                the configuration information for the specified IWDG module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);

七、编程实战:验证不及时喂狗,系统将复位重启

验证思路:按下 WKUP 时可喂狗,当超过 1s 没喂狗时系统将复位重启,LED0 反复初始化点亮,正常喂狗时 LED0 常亮

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.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 */
    key_init();                         /* 初始化按键 */

    delay_ms(100);                     /* 延时100ms再初始化看门狗,LED0的变化"可见" */
    iwdg_init(IWDG_PRESCALER_64, 500); /* 预分频数为64,重载值为500,溢出时间约为1s */
    LED0(0);                           /* 点亮LED0(红灯) */

    while (1)
    {
        if (key_scan(1) == WKUP_PRES) /* 如果WK_UP按下,则喂狗,支持连按 */
        {
            iwdg_feed(); /* 喂狗 */
        }
        delay_ms(10);
    }
}

wdg.c

#include "./BSP/WDG/wdg.h"

IWDG_HandleTypeDef iwdg_handler; /*独立看门狗句柄 */

/**
 * @brief       初始化独立看门狗
 * @param       prer: IWDG_PRESCALER_4~IWDG_PRESCALER_256,对应4~256分频
 *   @arg       分频因子 = 4 * 2^prer. 但最大值只能是256!
 * @param       rlr: 自动重装载值,0~0XFFF.
 * @note        时间计算(大概):Tout=((4 * 2^prer) * rlr) / 32 (ms).
 * @retval      无
 */
void iwdg_init(uint32_t prer, uint16_t rlr)
{
    iwdg_handler.Instance = IWDG;
    iwdg_handler.Init.Prescaler = prer; /* 设置IWDG分频系数 */
    iwdg_handler.Init.Reload = rlr;     /* 从加载寄存器 IWDG->RLR 重装载值 */
    HAL_IWDG_Init(&iwdg_handler);       /* 初始化IWDG并使能 */
}

/* 喂独立看门狗 */
void iwdg_feed(void)
{
    HAL_IWDG_Refresh(&iwdg_handler); /* 喂狗 */
}

wdg.h

#ifndef __WDG_H
#define __WDG_H

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

void iwdg_init(uint32_t prer, uint16_t rlr); /* 初始化IWDG,并使能IWDG */
void iwdg_feed(void);                        /* 喂狗 */

#endif

八、WWDG简介

WWDG(Window watchdog),即窗口看门狗

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

特性:递减的计数器,当递减计数器值从 0x40 减到 0x3F 时复位(即 T6 位跳变到 0),计数器的值大于 W[6:0] 值时喂狗会复位,提前唤醒中断 (EWI):当递减计数器等于 0x40 时可产生

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

作用

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

应用

需要精准检测程序运行时间的场合

九、WWDG工作原理

注意:W[6:0] 必须大于窗口下限值 0x3F,否则无窗口期

十、WWDG框图

时钟源

PCLK1
F10336MHz
F40742MHz
F42945MHz
F76754MHz
H743100MHz

十一、WWDG寄存器

11.1、控制寄存器(WWDG_CR)

用于使能窗口看门狗工作,以及重装载计数器值(即喂狗)

11.2、配置寄存器(WWDG_CFR)

用于使能窗口看门狗提前唤醒中断,设置预分频系数,设置窗口上限值

11.3、状态寄存器(WWDG_SR)

用于判断是否发生了 WWDG 提前唤醒中断

十二、WWDG超时时间计算

WWDG 超时时间计算公式

T_{out} 是 WWDG 超时时间(没喂狗)

F_{wwdg} 是 WWDG 的时钟源频率

4096 是 WWDG 固定的预分频系数

2^{WDGTB} 是 WWDG_CFR 寄存器设置的预分频系数值

T[5:0] 是 WWDG 计数器低 6 位

WWDG 最短最长超时时间(F4/F7/H7)

十三、WWDG配置步骤

13.1、使能并初始化WWDG

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

HAL库驱动函数:HAL_WWDG_Init()

/**
  * @brief  Initialize the WWDG according to the specified.
  *         parameters in the WWDG_InitTypeDef of  associated handle.
  * @param  hwwdg  pointer to a WWDG_HandleTypeDef structure that contains
  *                the configuration information for the specified WWDG module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);

关键结构体

/**
  * @brief  WWDG Init structure definition
  */
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;

13.2、窗口期喂狗

重装载计数器,即喂狗

HAL库驱动函数:HAL_WWDG_Refresh()

/**
  * @brief  Refresh the WWDG.
  * @param  hwwdg  pointer to a WWDG_HandleTypeDef structure that contains
  *                the configuration information for the specified WWDG module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);

十四、编程实战:验证窗口看门狗功能

验证思路:LED0 熄灭 LED1 闪烁说明正常喂狗,程序正常执行;LED1 熄灭 LED0 闪烁说明没有正常喂狗,程序反复执行复位

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.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(红灯) */
    delay_ms(300);                           /* 延时100ms再初始化看门狗,LED0的变化"可见" */
    wwdg_init(0X7F, 0X5F, WWDG_PRESCALER_8); /* 计数器值为7f,窗口寄存器为5f,分频数为8 */

    while (1)
    {
        LED0(1); /* 关闭LED0(红灯) */
    }
}

wdg.c

#include "./BSP/WDG/wdg.h"

WWDG_HandleTypeDef 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)
{
    wwdg_handler.Instance = WWDG;
    wwdg_handler.Init.Prescaler = fprer;         /* 设置分频系数 */
    wwdg_handler.Init.Window = wr;               /* 设置窗口值 */
    wwdg_handler.Init.Counter = tr;              /* 设置计数器值 */
    wwdg_handler.Init.EWIMode = WWDG_EWI_ENABLE; /* 使能窗口看门狗提前唤醒中断 */
    HAL_WWDG_Init(&wwdg_handler);                /* 初始化WWDG */
}

/* WWDG底层驱动,时钟配置,中断配置 */
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);         /* 使能窗口看门狗中断 */
}

/* 窗口看门狗中断服务程序 */
void WWDG_IRQHandler(void)
{
    HAL_WWDG_IRQHandler(&wwdg_handler); /* 调用WWDG共用中断处理函数 */
}

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
    HAL_WWDG_Refresh(&wwdg_handler); /* 更新窗口看门狗值 */
    LED1_TOGGLE();                   /* 绿灯闪烁 */
}

wdg.h

#ifndef __WDG_H
#define __WDG_H

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

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

#endif

十五、IWDG和WWDG的主要区别

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HZU_Puzzle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值