一、WWDG功能介绍
1. WWDG简介
WWDG是STM32的窗口看门狗,与IWDG不同,WWDG专用于监测软件异常(如循环、阻塞),它使用6位递减计数器,从0x7F递减到0x40时触发复位;
WWDG必须在指定时间窗口内刷新,在计数器的值大于W[6:0]值时喂狗也会复位;
WWDG的时钟源来自APB1(PCLK1)经过预分频。
在递计数器等于0x40时可以产生提前唤醒中断。
2. WWDG的作用
WWDG主要作用有以下三点:
(1)精准时序控制
- 必须在指定时间窗口(0x40~0x7F)内刷新
- 防止过早刷新(程序运行过快)或过晚刷新(程序阻塞)
- 典型应用:保障关键任务(如通信协议处理)的实时性
(2)异常检测机制
// 当计数器递减到0x40时触发复位
// 若在计数器>0x7F时刷新会立即复位(防程序跑飞)
HAL_WWDG_Refresh(&hwwdg); // 必须在窗口期内调用
(3)故障预警功能
/* USER CODE BEGIN 4 */
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
// 在复位前记录错误信息(比IWDG多出预警阶段)
HAL_UART_Transmit(&huart1, (uint8_t *)"SYSTEM_WARNING!\r\n", 16, 100);
__ASM volatile("nop"); // 预留处理时间
}
/* USER CODE END 4 */
3. IWDG与WWDG的比较
特性 | WWDG | IWDG |
时钟源 | PCLK1(最高36MHz) | LSI(约40kHz) |
复位条件 | 过早/过晚刷新 | 超时未刷新 |
中断支持 | 支持早期中断(可记录错误) | 无中断 |
适用场景 | 关键任务监控 | 防系统死锁 |
实际工程中建议将两者结合使用,如:
- IWDG:作为系统级保底防护(类似防火墙)
- WWDG:保护核心业务逻辑(如报文解析循环)
4. WWDG框图
时钟源
在STM32不同系列里,时钟源频率有所不同。
- F103:PCLK1(36MHz)
- F407:PCLK1(42MHz)
- F429:PCLK1(45MHz)
- F767:PCLK1(54MHz)
- F743:PCLK1(100MHz)
- ……
二、WWDG的工作过程
- 计数器的初始值是0x7F(127),随时时间增加计数器开始递减。
- 减到窗口上限值(图示0x5F)之前,如果喂狗,就会产生复位,这个值是可以改的;
- 减到0x40(64)之间,可产生中断,这个值是可以改的;
- 减到窗口下限值 0x63 ,产生复位,这个值是固定的。
窗口期是 W[6:0] >= 窗口期 > 0x3F
三、WWDG寄存器
1. WWDG_CR控制寄存器
- 第6:0位:递减计数器(T[6:0])
- 第7位:激活位(WDGA),置1启用WWDG
2. WWDG_CFR 配置寄存器
- 第6:0位:窗口值(W[6:0])
- 第8:7位:预分频器(WDGTB[1:0])
- 第9位:提前唤醒中断使能(EWI),计数器达到0x40时产生中断(另外需要启动NVIC才能工作)
预分频器值列表:
- 00: CK计时器时钟(PCLK1除以4096) 除以1
- 01: CK计时器时钟(PCLK1除以4096) 除以2
- 10: CK计时器时钟(PCLK1除以4096) 除以4
- 11: CK计时器时钟(PCLK1除以4096) 除以8
3. WWDG_SR 状态寄存器
- 第0位:提前唤醒中断标志(EWIF)。当计数器值达到40h时,此位由硬件置1。它必须通过软件写“0”来清除。
四、WWDG超时时间计算
基本公式
符号 | 说明 | 典型值范围 |
T: | 计数器低6位值(CR寄存器[5:0]) | 0x00 ~ 0x3F |
WDGTB | 预分频系数(CFR寄存器[8:7]) | 0(1分频)~3(8分频) |
PCLK | APB总线时钟频率(MHz) | 8~72 (MHz) |
使用示例
当配置参数:
- 计数器初始值 = 0x7F
- 窗口值 = 0x5F
- 预分频 = WWDG_PRESCALER_1 (WDGTB=0)
- PCLK = 32 MHz
计算步骤:
最小超时时间:
最大超时时间:
对于F1系列可以得到下表:
WDGTB | 最小超时值 | 最大超时值 |
0 | 113us | 7.28ms |
1 | 227us | 14.56ms |
2 | 455us | 29.12ms |
3 | 910us | 58.25ms |
五、WWDG HAL库配置步骤
1. 整体流程
2. 相关HAL库函数介绍
(1)HAL_WWDG_Init
HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);
主要作用是设置窗口值、计数值、预分频系统等进行设置,主要寄存器是 WWDG_CR,WWDGCRF,其典型代码:
// 典型用法示例:
WWDG_HandleTypeDef hwwdg;
void MX_WWDG_Init(void)
{
hwwdg.Instance = WWDG; // 选择WWDG外设
hwwdg.Init.Prescaler = WWDG_PRESCALER_8; // 预分频系数
hwwdg.Init.Window = 0x5F; // 窗口值(0x40 ~ 0x7F)
hwwdg.Init.Counter = 0x7F; // 初始计数器(必须 >= 窗口值)
hwwdg.Init.EWIMode = WWDG_EWI_ENABLE; // 使能提前唤醒中断
if (HAL_WWDG_Init(&hwwdg) != HAL_OK) {
Error_Handler();
}
}
(2)HAL_WWDG_Refresh
重装载计数器,即喂狗,主要操作寄存器是 WWDG_CR T[6:0]。
典型用法示例:
/* USER CODE BEGIN 4 */
// 典型用法示例:
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
// 在窗口期内刷新计数器(喂狗)
HAL_WWDG_Refresh(hwwdg); // 重新加载计数器值为初始值
// 可以添加调试信息
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0); // LED状态翻转
}
/* USER CODE END 4 */
3. STM32CubeMX 配置WWDG
本示例使用早期中断,设置如下:
- 预分频系数设置为8,
- 窗口值 0x5F,
- 计数器值为0x7F,
- 启用Early wakeup interrupt(图中忘启用了,从代码中启用)。
查看项目,
main文件
main函数会自动添加:
WWDG_HandleTypeDef hwwdg;
并增加函数:
static void MX_WWDG_Init(void);
/**
* @brief WWDG Initialization Function
* @param None
* @retval None
*/
static void MX_WWDG_Init(void)
{
/* USER CODE BEGIN WWDG_Init 0 */
/* USER CODE END WWDG_Init 0 */
/* USER CODE BEGIN WWDG_Init 1 */
/* USER CODE END WWDG_Init 1 */
hwwdg.Instance = WWDG;
hwwdg.Init.Prescaler = WWDG_PRESCALER_8;
hwwdg.Init.Window = 0x5F;
hwwdg.Init.Counter = 0x7F;
hwwdg.Init.EWIMode = WWDG_EWI_ENABLE;
if (HAL_WWDG_Init(&hwwdg) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN WWDG_Init 2 */
// 添加中断优先级配置
HAL_NVIC_SetPriority(WWDG_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(WWDG_IRQn);
/* USER CODE END WWDG_Init 2 */
}
中断函数:
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
HAL_WWDG_Refresh(hwwdg); // 必须在此中断中喂狗
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_0); // 添加LED指示
}
在main函数里会调用 :
MX_GPIO_Init();
MX_USART1_UART_Init();
//MX_IWDG_Init();
MX_WWDG_Init();
stm32f1xx_it.c 中断设置
extern WWDG_HandleTypeDef hwwdg;
// 在stm32xxx_it.c中添加(若不存在)
void WWDG_IRQHandler(void)
{
HAL_WWDG_IRQHandler(&hwwdg);
}