STM32 看门狗概述

项目内容
作用监控程序运行状态,当程序卡死或跑飞时及时复位,保证系统可靠性和安全性
本质定时器,定时范围内没喂狗就产生复位信号
STM32内置类型独立看门狗(IWDG)和窗口看门狗(WWDG)
  • 特性对比图
特性IWDG独立看门狗WWDG窗口看门狗
复位计数器减到0后计数器T[5:0]减到0后、过早重装计数器
中断无早期唤醒中断
时钟源LSI (40KHz)PCLK1 (36MHz)
预分频系数4、8、32、64、128、2561、2、4、8
计数器12位6位(有效计数)
超时时间0.1ms~26214.4ms113us~58.25ms
喂狗方式写入键寄存器,重装固定值RLR直接写入计数器,写多少重装多少
防误操作键寄存器和写保护无
用途独立工作,对时间精度要求较低要求看门狗在精确计时窗口起作用

独立看门狗(IWDG)

键寄存器

  • 功能:本质上是控制寄存器,用于控制硬件电路的工作,降低硬件电路受到干扰的概率
写入键寄存器的值作用
0xCCCC启用独立看门狗
0xAAAAIWDG_RLR中的值重新加载到计数器(喂狗)
0x5555解除IWDG_PR和IWDG_RLR的写保护
0x5555之外的其他值启用IWDG_PR和IWDG_RLR的写保护

超时时间

  • 公式:
    text
    T_IWDG = T_LSI × PR预分频系数 × (RL + 1)
    其中:T_LSI = 1 / F_LSI
    
预分频系数PR[2:0]位最短时间(ms)最长时间(ms)
/400.1409.6
/810.2819.2
/1620.41638.4
/3230.83276.8
/6441.66553.6
/12853.213107.2
/256(6或7)6.426214.4

窗口看门狗(WWDG)

工作原理

  • 递减计数器T[6:0]的值小于0x40时,WWDG产生复位
  • 递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位
  • 递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重新装载计数器以避免WWDG复位
  • 定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位

超时时间

  • 计算公式:
类型公式
超时时间T_WWDG = T_PCLK1 × 4096 × WDTB预分频系数 × (T[5:0] + 1)
窗口时间T_WIN = T_PCLK1 × 4096 × WDTB预分频系数 × (T[5:0] - W[5:0])
时间单位T_PCLK1 = 1 / F_PCLK1
WDTB最小时间值最大时间值
0113μs7.28ms
1227μs14.56ms
2455μs29.12ms
3910μs58.25ms

工作流程

text
WWDG工作流程
    ├── 初始化WWDG
    │   ├── 设置预分频系数
    │   ├── 设置窗口值
    │   └── 设置计数器初始值
    ├── 启动WWDG
    ├── 主程序运行
    │   ├── 定期喂狗(在窗口时间内)
    │   └── 处理业务逻辑
    ├── 计数器递减
    │   ├── 计数器 > 窗口值:禁止喂狗
    │   ├── 窗口值 ≥ 计数器 ≥ 0x40:允许喂狗
    │   ├── 计数器 = 0x40:产生早期唤醒中断
    │   └── 计数器 < 0x40:产生复位
    └── 复位或继续运行

代码配置

IWDG

c
void IWDG_Init(uint8_t prer, uint16_t rlr)
{
	//使能IWDG访问寄存器
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    
    //设置预分帧系数
    IWDG_SetPrescaler(prer);
    
    //设置重装值
    IWDG_SetReload(rlr);
    
    //喂狗重载
    IWDG_ReloadCounter();
    
    //使能IWDG
    IWDG_Enable();
}
//喂狗函数
void IWDG_Feed(void)
{
    IWDG_ReloadCounter();
}

WWDG

c
void WWDG_Init(uint8_t tr, uint8_t wr, uint8_t fprer)
{
	//使能WWDG
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
    
    //设置预分帧系数
    WWDG_SetPrescaler(fprer);
    
    //设置窗口值
    WWDG_SetWindowValue(wr);
    
    //设置计数器初始值并启动WWDG
    WWDG_Enable(tr);
    
    //清除早期唤醒WWDG的标志位
    WWDG_ClearFlag();
    
    //配置WWDG外部中断
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    //启动早期唤醒中断
    WWDG_EnableIT();
}

//喂狗程序
void WWDG_Feed(uint8_t tr)
{
    WWDG_SetCounter(tr);
}

//提前喂狗
void WWDG_IRQHandler(void)
{
    WWDG_ClearFlag();
    WWDG_Feed(0x7F);
}