看门狗概述
| 项目 | 内容 |
|---|---|
| 作用 | 监控程序运行状态,当程序卡死或跑飞时及时复位,保证系统可靠性和安全性 |
| 本质 | 定时器,定时范围内没喂狗就产生复位信号 |
| STM32内置类型 | 独立看门狗(IWDG)和窗口看门狗(WWDG) |
- 特性对比图
| 特性 | IWDG独立看门狗 | WWDG窗口看门狗 |
|---|---|---|
| 复位 | 计数器减到0后 | 计数器T[5:0]减到0后、过早重装计数器 |
| 中断 | 无 | 早期唤醒中断 |
| 时钟源 | LSI (40KHz) | PCLK1 (36MHz) |
| 预分频系数 | 4、8、32、64、128、256 | 1、2、4、8 |
| 计数器 | 12位 | 6位(有效计数) |
| 超时时间 | 0.1ms~26214.4ms | 113us~58.25ms |
| 喂狗方式 | 写入键寄存器,重装固定值RLR | 直接写入计数器,写多少重装多少 |
| 防误操作 | 键寄存器和写保护 | 无 |
| 用途 | 独立工作,对时间精度要求较低 | 要求看门狗在精确计时窗口起作用 |
独立看门狗(IWDG)
键寄存器
- 功能:本质上是控制寄存器,用于控制硬件电路的工作,降低硬件电路受到干扰的概率
| 写入键寄存器的值 | 作用 |
|---|---|
| 0xCCCC | 启用独立看门狗 |
| 0xAAAA | IWDG_RLR中的值重新加载到计数器(喂狗) |
| 0x5555 | 解除IWDG_PR和IWDG_RLR的写保护 |
| 0x5555之外的其他值 | 启用IWDG_PR和IWDG_RLR的写保护 |
超时时间
- 公式:
T_IWDG = T_LSI × PR预分频系数 × (RL + 1) 其中:T_LSI = 1 / F_LSI
| 预分频系数 | PR[2:0]位 | 最短时间(ms) | 最长时间(ms) |
|---|---|---|---|
| /4 | 0 | 0.1 | 409.6 |
| /8 | 1 | 0.2 | 819.2 |
| /16 | 2 | 0.4 | 1638.4 |
| /32 | 3 | 0.8 | 3276.8 |
| /64 | 4 | 1.6 | 6553.6 |
| /128 | 5 | 3.2 | 13107.2 |
| /256 | (6或7) | 6.4 | 26214.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 | 最小时间值 | 最大时间值 |
|---|---|---|
| 0 | 113μs | 7.28ms |
| 1 | 227μs | 14.56ms |
| 2 | 455μs | 29.12ms |
| 3 | 910μs | 58.25ms |
工作流程
WWDG工作流程
├── 初始化WWDG
│ ├── 设置预分频系数
│ ├── 设置窗口值
│ └── 设置计数器初始值
├── 启动WWDG
├── 主程序运行
│ ├── 定期喂狗(在窗口时间内)
│ └── 处理业务逻辑
├── 计数器递减
│ ├── 计数器 > 窗口值:禁止喂狗
│ ├── 窗口值 ≥ 计数器 ≥ 0x40:允许喂狗
│ ├── 计数器 = 0x40:产生早期唤醒中断
│ └── 计数器 < 0x40:产生复位
└── 复位或继续运行代码配置
- IWDG
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
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);
}