文章目录
1. WDG
2. IWDG独立看门狗
2.1 main.c
3. WWDG窗口看门狗
3.1 main.c
1. WDG
对于WDG看门狗的详细解析可以看下面这篇文章:
STM32单片机WDG看门狗详解-CSDN博客
看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性。
看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号。
STM32内置两个看门狗
- 独立看门狗(Independent WDG):独立运行(独立看门狗的时钟是专用的LSI,内部低速时钟),对时间精度要求低(只有一个最晚时间界限)
- 窗口看门狗(Window WDG):要求看门狗在精确计时窗口起作用(喂狗时间有个最晚的界限,也有个最早的界限),使用APB1的时钟(没有专用时钟,不算独立)
2. IWDG独立看门狗
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 | 直接写入计数器,写多少重装多少 |
防误操作 | 键寄存器和写保护 | 无 |
用途 | 独立工作,对时间精度要求较低 | 要求看门狗在精确计时窗口起作用 |
独立看门狗配置步骤:
- 开启LSI时钟,不需要手动开启,因为启用独立看门狗时,LSI就会被强制打开。
- 写入0x5555键值,解除写保护。
- 写入预分频器和重装寄存器(预分频和重装值) -> 通过超时计算公式计算出来。
- 写入0xCCCC启用独立看门狗。
- 在主循环中不断执行写入0xAAAA键值语句,进行喂狗。
相关函数在文件stm32f10x_iwdg.c 和 stm32f10x_rcc.c 中。
2.1 main.c
这个代码可以实现当按住按键不放时,主程序卡死,独立看门狗就会进行复位。
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"int main(void)
{/*模块初始化*/OLED_Init(); //OLED初始化Key_Init(); //按键初始化/*显示静态字符串*/OLED_ShowString(1, 1, "IWDG TEST");/*判断复位信号来源*/if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) //如果是独立看门狗复位{OLED_ShowString(2, 1, "IWDGRST"); //OLED闪烁IWDGRST字符串Delay_ms(500);OLED_ShowString(2, 1, " ");Delay_ms(100);RCC_ClearFlag(); //清除标志位}else //否则,即为其他复位{OLED_ShowString(3, 1, "RST"); //OLED闪烁RST字符串Delay_ms(500);OLED_ShowString(3, 1, " ");Delay_ms(100);}/*IWDG初始化*/IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //独立看门狗写使能IWDG_SetPrescaler(IWDG_Prescaler_16); //设置预分频为16IWDG_SetReload(2499); //设置重装值为2499,独立看门狗的超时时间为1000msIWDG_ReloadCounter(); //重装计数器,喂狗IWDG_Enable(); //独立看门狗使能while (1){Key_GetNum(); //调用阻塞式的按键扫描函数,模拟主循环卡死IWDG_ReloadCounter(); //重装计数器,喂狗OLED_ShowString(4, 1, "FEED"); //OLED闪烁FEED字符串Delay_ms(200); //喂狗间隔为200+600=800msOLED_ShowString(4, 1, " ");Delay_ms(600);}
}
3. WWDG窗口看门狗
配置步骤:
- 开启窗口看门狗(WWDG)的APB1时钟。
- 配置各个寄存器(预分频、窗口值) -> 窗口看门狗没有写保护。
- 写入控制寄存器CR -> 包含看门狗使能位、计数器溢出标志位、计数器有效位。
- 喂狗:运行过程中不断向计数器写入想要的重装值。
相关函数在文件stm32f10x_iwdg.c 和 stm32f10x_rcc.c 中。
3.1 main.c
这个代码可以实现当按住按键不放时,主程序卡死,独立看门狗就会进行复位。
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"int main(void)
{/*模块初始化*/OLED_Init(); //OLED初始化Key_Init(); //按键初始化/*显示静态字符串*/OLED_ShowString(1, 1, "WWDG TEST");/*判断复位信号来源*/if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) //如果是窗口看门狗复位{OLED_ShowString(2, 1, "WWDGRST"); //OLED闪烁WWDGRST字符串Delay_ms(500);OLED_ShowString(2, 1, " ");Delay_ms(100);RCC_ClearFlag(); //清除标志位}else //否则,即为其他复位{OLED_ShowString(3, 1, "RST"); //OLED闪烁RST字符串Delay_ms(500);OLED_ShowString(3, 1, " ");Delay_ms(100);}/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //开启WWDG的时钟/*WWDG初始化*/WWDG_SetPrescaler(WWDG_Prescaler_8); //设置预分频为8WWDG_SetWindowValue(0x40 | 21); //设置窗口值,窗口时间为30msWWDG_Enable(0x40 | 54); //使能并第一次喂狗,超时时间为50mswhile (1){Key_GetNum(); //调用阻塞式的按键扫描函数,模拟主循环卡死OLED_ShowString(4, 1, "FEED"); //OLED闪烁FEED字符串Delay_ms(20); //喂狗间隔为20+20=40msOLED_ShowString(4, 1, " ");Delay_ms(20);WWDG_SetCounter(0x40 | 54); //重装计数器,喂狗}
}