您现在的位置是:首页 >技术交流 >【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出网站首页技术交流

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

我是小白呀 2024-06-19 13:56:33
简介【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

概述

在嵌入式开发中, 可靠性和稳定性是至关重要的. 这就是为什么许多单片机, 比如 STM32, 提供了窗口看门狗 (Window Watchdog, WWDF) 的功能. WWDG 是一种硬件定时器, 其目的在于防止软件错误导致的系统故障. WWDG 是通过监控软件运行的正常新, 并在检测到异常情况时自动重启系统, 从而防止系统长时间处于错误状态. 虽然 STM32 同时提供了独立看门狗 (Independent Watchdog, IWDG) 和 WWDG, 但 WWDG 具有更高精度和更灵活的配置选项, 使其在一些需要精确定时或特殊需求的应用中具有优势.

STM32 窗口看门狗

窗口看门狗 (WWDG)

WWDG 的核心是一个 7 位的定时器 (取值范围 0-127). 用户可以设定一个窗口值和一个计数重载值. 当定时器计数值在重载值到窗口值之间倒数时, 称为窗口期. 窗口期是唯一可以刷新 WWDG 的时机. 也就是说, 只有在 “窗口” 打开期间, 才可以 “喂狗”.

如果在窗口未打开前就重载了 WWDG, 或者在窗口打开后没有及时重载 WWDG, 那么 WWDG 都会产生系统复位.

这样的设计能够使系统检测到两种软件错误:

  • 执行过快: 窗口未打开前就重载了 WWDG
  • 执行过慢: 窗口打开后没有及时重载 WWDG

WWDG_SR 状态寄存器

在 STM32 中, WWDG_SR 是窗口看门狗状态寄存器 (Windows Watchdog Status Register). WWDG_SR 只有一个比特位, 即比特 0 (EWIF), 又称为早早期唤醒中断标志 (Early Wakeup Interrupt Flag). 这个标志位用来表示窗口看门狗定时器已达到了 63 (也就是 127-64), 即将达到重载值. 这个功能可以用来唤醒 CPU, 让它有足够的时间去刷新窗口看门狗, 防止系统复位.

注: 虽热 EWIF 位可以通过软件清零, 但是在窗口看门狗启动后, 这个标志位会自动置位, 所以在大多数情况下, 我们需要手动清零这个标志位.

WWDG 配置与使用

在 STM32 中, 使用 WWDG 首先需要启动 WWDG 时钟, 并设置预分频器和窗口值. 通过访问 WWDG 的控制寄存器 (WWDG_CR) 和配置寄存器 (WWDG_CFR) 来实现.

具体步骤如下:

  1. 启动 WWDG 时钟: 通过访问复位和时钟控制 (RCC) 的 APB1 使能寄存器 (RCC_APB1ENR), 能使 WWDG 时钟
  2. 设置 WWDG 的预分频器和窗口值:通过访问 WWDG 的配置寄存器 (WWFG_CRF), 设置预分频器 (WDGTB) 和窗口值 (W). 同时, 可以使能窗口看门狗早期中断 (EWI)
  3. 设置 WWDG 的计数器重载值: 通过访问 WWDG 的控制寄存器 (WWDG_CR), 设置计数器的重载值, 并使能 WWDG

使用 WWDG 进行故障检测

WWDG 能够检测出软件中心过快和执行过慢两种类型的错误. 当主程序在窗口打开后没有及时重载 WWDG, 说明团建执行过慢, 这两种情况都会引发 WWDG 产生系统复位.

因为在实际应用中, 软件执行的速度往往与任务的完成密切相关. 如果软件执行过快, 可能意味着某些任务被跳过或者未被正确处理. 如果软件执行过慢, 可能意味着系统的性能无法满足需求, 或者某些任务执行时间过长. 通过 WWDG, 我们可以确保软件在预定的时间范围内正确的运行.

案例

#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(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    delay_init(72);                         /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    LED0(0);                                /* 点亮LED0 红灯 */
    delay_ms(300);                          /* 延时300ms再初始化看门狗,LED0的变化"可见" */
    wwdg_init(0X7F, 0X5F, WWDG_PRESCALER_8);/* 计数器值为7f,窗口寄存器为5f,分频数为8 */

    while (1)
    {
        LED0(1);                            /* 关闭红灯 */
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。