STM32窗口看门狗(WWDG)知识点及标准库使用指南

目录

一、窗口看门狗基本概念

二、工作原理

[1. 计数器与窗口](#1. 计数器与窗口)

[2. 时钟计算](#2. 时钟计算)

三、标准库使用步骤

[1. 初始化配置](#1. 初始化配置)

[2. 喂狗函数](#2. 喂狗函数)

[3. 早期唤醒中断配置(可选)](#3. 早期唤醒中断配置(可选))

四、完整使用示例

示例1:基本配置(无中断)

示例2:带早期唤醒中断的配置

五、关键函数解析

[1. WWDG_SetPrescaler](#1. WWDG_SetPrescaler)

[2. WWDG_SetWindowValue](#2. WWDG_SetWindowValue)

[3. WWDG_Enable](#3. WWDG_Enable)

[4. WWDG_SetCounter](#4. WWDG_SetCounter)

[5. WWDG_EnableIT](#5. WWDG_EnableIT)

[6. WWDG_ClearFlag](#6. WWDG_ClearFlag)

六、使用注意事项

[1. 窗口值设置](#1. 窗口值设置)

[2. 喂狗时机](#2. 喂狗时机)

[3. 早期唤醒中断](#3. 早期唤醒中断)

[4. 时钟依赖](#4. 时钟依赖)

七、窗口看门狗与独立看门狗的对比

八、常见问题与解决方案(question&&solution)

[Q1. 窗口看门狗总是复位](#Q1. 窗口看门狗总是复位)

[Q2. 早期唤醒中断不触发](#Q2. 早期唤醒中断不触发)

[Q3. 超时时间不准确](#Q3. 超时时间不准确)


独立看门狗复习入口

STM32独立看门狗(IWDG)知识点及标准库使用指南

一、窗口看门狗基本概念

窗口看门狗(Window Watchdog,简称WWDG)是STM32微控制器中的另一种看门狗外设,与独立看门狗(IWDG)相比,具有 时间窗口限制的特点:

喂狗时机限制 :喂狗操作必须在特定的时间窗口内进行,太早或太晚都会触发复位

更高的安全性 :可以防止程序在错误的时间点喂狗(例如程序跑飞后进入死循环,定期喂狗但逻辑错误)

主时钟依赖 :使用APB1时钟(最高48MHz),速度更快

早期唤醒中断 :当计数器值降到窗口下限时,可触发中断,用于紧急处理

与独立看门狗不同的是, 独立看门狗是在独立计数器减至 0 前喂狗均为有效喂狗, CPU 不会复位。 而窗口看门狗只有在时间窗口范围内喂狗才为有效喂狗, 其余时间段均为无效喂狗, CPU 会执行复位

主要特点

7位递减计数器 :从0x7F(127)开始递减,到0x3F(63)时触发复位

窗口机制 :只有当计数器值在窗口上限和窗口下限(0x40)之间时,喂狗才有效

早期唤醒中断 :计数器值降到0x40时触发,可用于在复位前执行紧急操作

时钟源 :使用APB1时钟经过预分频后的时钟,频率为PCLK1/(4096×预分频系数)

二、工作原理

1. 计数器与窗口

计数器 :7位递减计数器,范围0x7F-0x00

窗口上限 :由WWDG_CFR寄存器的W[6:0]位设置(必须大于0x40)

窗口下限 :固定为0x40(当计数器值≤0x40时,不能喂狗)

复位条件 :计数器值从0x40减到0x3F时

喂狗操作在窗口外执行时

2. 时钟计算

输入时钟 :PCLK1(APB1时钟,最高48MHz)

预分频系数 :可选1、2、4、8

计数器时钟 :

计数周期 :

超时时间 : ​

三、标准库使用步骤

1. 初始化配置

cpp 复制代码
/**
 * @brief  初始化窗口看门狗
 * @param  prescaler: 预分频系数,可选值:
 *         WWDG_Prescaler_1, WWDG_Prescaler_2, WWDG_Prescaler_4, WWDG_Prescaler_8
 * @param  windowValue: 窗口值(必须大于0x40,小于0x7F)
 * @param  counter: 计数器初始值(建议设置为0x7F)
 * @retval 无
 */
void WWDG_Init(uint32_t prescaler, uint8_t windowValue, uint8_t counter)
{
    // 使能WWDG时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
    
    // 设置预分频系数
    WWDG_SetPrescaler(prescaler);
    
    // 设置窗口值
    WWDG_SetWindowValue(windowValue);
    
    // 设置计数器初始值并启用WWDG
    WWDG_Enable(counter);
    
    // 可选:启用早期唤醒中断
    WWDG_EnableIT();
}

2. 喂狗函数

cpp 复制代码
/**
 * @brief  喂狗函数
 * @param  counter: 计数器值(建议设置为0x7F)
 * @retval 无
 * @note   必须在窗口时间内调用,否则会触发复位
 */
void WWDG_Feed(uint8_t counter)
{
    // 喂狗,重置计数器
    WWDG_SetCounter(counter);
}

3. 早期唤醒中断配置(可选)

cpp 复制代码
/**
 * @brief  配置WWDG早期唤醒中断
 * @param  无
 * @retval 无
 */
void WWDG_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    
    // 配置WWDG中断
    NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// 早期唤醒中断处理函数
void WWDG_IRQHandler(void)
{
    // 清除中断标志位
    WWDG_ClearFlag();
    
    // 在这里执行紧急操作,例如保存关键数据
    // ...
    
    // 喂狗(注意:必须在窗口时间内)
    WWDG_Feed(0x7F);
}

四、完整使用示例

示例1:基本配置(无中断)

cpp 复制代码
#include "stm32f10x.h"
#include "delay.h"

/**
 * @brief  初始化窗口看门狗,超时时间约50ms
 * @param  无
 * @retval 无
 */
void WWDG_Init_50ms(void)
{
    // 使能WWDG时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
    
    // 设置预分频系数为8(PCLK1=36MHz时,WWDG时钟=36MHz/(4096×8)≈1.1kHz)
    WWDG_SetPrescaler(WWDG_Prescaler_8);
    
    // 设置窗口值为0x5F(当计数器值>0x5F时才能喂狗)
    WWDG_SetWindowValue(0x5F);
    
    // 启用WWDG,计数器初始值为0x7F
    WWDG_Enable(0x7F);
}

int main(void)
{
    // 系统初始化...
    
    // 初始化窗口看门狗
    WWDG_Init_50ms();
    
    while(1)
    {
        // 正常程序代码...
        
        // 模拟程序运行,确保在窗口时间内喂狗
        delay_ms(10);
        
        // 喂狗(必须在窗口时间内)
        WWDG_SetCounter(0x7F);
        
        // 模拟程序运行
        delay_ms(30);
    }
}

示例2:带早期唤醒中断的配置

cpp 复制代码
#include "stm32f10x.h"
#include "delay.h"

/**
 * @brief  初始化窗口看门狗
 * @param  无
 * @retval 无
 */
void WWDG_Init(void)
{
    // 使能WWDG时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
    
    // 配置NVIC
    WWDG_NVIC_Config();
    
    // 设置预分频系数为8
    WWDG_SetPrescaler(WWDG_Prescaler_8);
    
    // 设置窗口值为0x5F
    WWDG_SetWindowValue(0x5F);
    
    // 启用早期唤醒中断
    WWDG_EnableIT();
    
    // 启用WWDG,计数器初始值为0x7F
    WWDG_Enable(0x7F);
}

/**
 * @brief  配置WWDG中断
 * @param  无
 * @retval 无
 */
void WWDG_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// WWDG中断处理函数
void WWDG_IRQHandler(void)
{
    // 清除中断标志位
    WWDG_ClearFlag();
    
    // 执行紧急操作,例如保存数据
    // ...
    
    // 喂狗
    WWDG_SetCounter(0x7F);
}

int main(void)
{
    // 系统初始化...
    
    // 初始化窗口看门狗
    WWDG_Init();
    
    while(1)
    {
        // 正常程序代码...
        
        // 无需手动喂狗,由中断处理
        delay_ms(40);
    }
}

五、关键函数解析

1. WWDG_SetPrescaler

cpp 复制代码
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);

功能 :设置窗口看门狗的预分频系数

参数 :

WWDG_Prescaler_1 :预分频系数1

WWDG_Prescaler_2 :预分频系数2

WWDG_Prescaler_4 :预分频系数4

WWDG_Prescaler_8 :预分频系数8

说明 :决定WWDG计数器的时钟频率

2. WWDG_SetWindowValue

cpp 复制代码
void WWDG_SetWindowValue(uint8_t WindowValue);

功能 :设置窗口看门狗的窗口值

参数 :窗口值(必须大于0x40,小于0x7F)

说明 :喂狗操作必须在计数器值大于窗口值且大于0x40时进行

3. WWDG_Enable

cpp 复制代码
void WWDG_Enable(uint8_t Counter);

功能 :启用窗口看门狗并设置初始计数器值

参数 :初始计数器值(建议设置为0x7F)

说明 :一旦启用,WWDG开始计数

4. WWDG_SetCounter

cpp 复制代码
void WWDG_SetCounter(uint8_t Counter);

功能 :设置窗口看门狗的计数器值(喂狗)

参数 :计数器值(建议设置为0x7F)

说明 :必须在窗口时间内调用,否则会触发复位

5. WWDG_EnableIT

cpp 复制代码
void WWDG_EnableIT(void);

功能 :启用窗口看门狗的早期唤醒中断

参数 :无

说明 :当计数器值降到0x40时触发中断

6. WWDG_ClearFlag

cpp 复制代码
void WWDG_ClearFlag(void);

功能 :清除窗口看门狗的早期唤醒中断标志位

参数 :无

说明 :在中断处理函数中调用,清除中断标志

六、使用注意事项

1. 窗口值设置

必须大于0x40 :否则会触发复位

建议小于0x7F :留有足够的计数空间

2. 喂狗时机

必须在窗口时间内 :计数器值 > 窗口值 且 计数器值 > 0x40

避免在中断中喂狗 :除非使用早期唤醒中断,否则可能在窗口外喂狗

3. 早期唤醒中断

用途 :在复位前执行紧急操作,如保存关键数据

处理时间 :中断处理函数的执行时间必须小于从0x40到0x3F的计数时间,否则会触发复位

4. 时钟依赖

依赖APB1时钟 :若APB1时钟故障,WWDG可能无法正常工作

频率计算 :根据PCLK1频率和预分频系数,计算准确的计数周期

七、窗口看门狗与独立看门狗的对比

八、常见问题与解决方案(question&&solution)

Q1. 窗口看门狗总是复位

原因 :喂狗操作不在窗口时间内,或窗口值设置错误

解决 :检查窗口值是否大于0x40,调整喂狗时机

Q2. 早期唤醒中断不触发

原因 :未启用中断,或NVIC配置错误

解决 :确保调用 WWDG_EnableIT() 并正确配置NVIC

Q3. 超时时间不准确

原因 :APB1时钟频率与预期不符,或预分频系数计算错误

解决 :确认PCLK1频率,重新计算预分频系数和窗口值

相关推荐
bingquan33332 小时前
在 Ghidra 中分析STM32裸机固件
stm32·单片机·嵌入式硬件
羽获飞2 小时前
从零开始学嵌入式之STM32——11.STM32---USART串行通讯
stm32·单片机·嵌入式硬件
宵时待雨3 小时前
STM32笔记归纳9:定时器
笔记·stm32·单片机·嵌入式硬件
逐步前行3 小时前
STM32_新建工程(寄存器版)
stm32·单片机·嵌入式硬件
bai5459364 小时前
STM32 CubeIDE 通过PWM占空比控制舵机角度
stm32·单片机·嵌入式硬件
松涛和鸣6 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
简单中的复杂6 小时前
【避坑指南】RK3576 Linux SDK 编译:解决 Buildroot 卡死在 host-gcc-final 的终极方案
linux·嵌入式硬件
上海合宙LuatOS6 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
Hhh __灏7 小时前
stm32的SRAM内存不足如何分析和优化?堆栈空间如何优化?
单片机