第38章 IWDG超时实验
第三十八章 IWDG超时实验
1. 硬件设计
-
IWDG一个
-
按键一个
-
LED三个
IWDG属于单片机内部资源,不需要外部电路,需要一个外部的按键和LED,在 1s 的时间内通过按键来不断的喂狗,如果喂狗失败,红灯闪烁。如果一直喂狗成功,则绿灯常亮。
2. 软件设计
- IWDG配置函数
void IWDG_Config(uint8_t prv ,uint16_t rlv)
{
// 使能 预分频寄存器PR和重装载寄存器RLR可写
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
// 设置预分频器值
IWDG_SetPrescaler(prv);
// 设置重装载寄存器值
IWDG_SetReload(rlv);
// 把重装载寄存器的值放到计数器中
IWDG_ReloadCounter();
// 使能 IWDG
IWDG_Enable();
}
其中一些库函数,我们需要介绍一下:
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable):
- 功能: 使能写访问权限,以允许对预分频寄存器(PR)和重装载寄存器(RLR)进行配置。某些微控制器在未开启写访问时,无法修改这些寄存器的值。
- 参数:
IWDG_WriteAccess_Enable
,使能写权限。
- IWDG_SetPrescaler(uint32_t prescaler):
- 功能: 设置IWDG的预分频器值。预分频器决定了看门狗计时器的计数速率。
- 参数:
prescaler
,通常是一个枚举值或常量,表示预分频器的设置,决定IWDG计数器的更新频率。
- IWDG_SetReload(uint32_t reload):
- 功能: 设置重装载寄存器的值。重装载寄存器决定了看门狗计时器的超时值,即如果在这个时间段内未重装载计数器,IWDG将触发复位。
- 参数:
reload
,一个整数值,表示计数器达到该值后会超时。
- IWDG_ReloadCounter():
- 功能: 将重装载寄存器的值写入计数器中,重置计数器。这是防止IWDG触发复位的关键步骤,通常在主程序循环中定期调用。
- 无参数: 该函数没有输入参数,直接执行重装载操作。
- IWDG_Enable():
- 功能: 启动IWDG,使其开始计数。如果未在设定的超时之前重装载计数器,IWDG将复位微控制器。
- 无参数: 该函数没有输入参数,直接使能看门狗。
IWDG配置函数有两个形参,prv用来设置预分频的值,取值可以是:
/*
* @arg IWDG_Prescaler_4: IWDG prescaler set to 4
* @arg IWDG_Prescaler_8: IWDG prescaler set to 8
* @arg IWDG_Prescaler_16: IWDG prescaler set to 16
* @arg IWDG_Prescaler_32: IWDG prescaler set to 32
* @arg IWDG_Prescaler_64: IWDG prescaler set to 64
* @arg IWDG_Prescaler_128: IWDG prescaler set to 128
* @arg IWDG_Prescaler_256: IWDG prescaler set to 256
*/
这些宏在stm32f10x_iwdg.h中定义,宏展开是8位的16进制数,具体作用是配置配置预分频寄存器IWDG_PR,获得各种分频系数。 形参rlv用来设置重装载寄存器IWDG_RLR的值,取值范围为0~0XFFF。溢出时间Tout = prv/40 * rlv(s), prv可以是[4,8,16,32,64,128,256]。如果我们需要设置1s的超时溢出,prv可以取IWDG_Prescaler_64,rlv取625, 即调用:IWDG_Config(IWDG_Prescaler_64 ,625)。Tout=64/40*625=1s。
- 喂狗函数
void IWDG_Feed(void)
{
// 把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
// 当计数器的值减到0的时候会产生系统复位
IWDG_ReloadCounter();
}
- 主函数
int main(void)
{
// 配置LED GPIO,并关闭LED
LED_GPIO_Config();
Delay(0X8FFFFF);
// 检查是否为独立看门狗复位
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
{
// 独立看门狗复位
// 亮红灯
LED_RED;
// 清除标志
RCC_ClearFlag();
/*如果一直不喂狗,会一直复位,加上前面的延时,会看到红灯闪烁
在1s 时间内喂狗的话,则会持续亮绿灯*/
}
else
{
// 不是独立看门狗复位(可能为上电复位或者手动按键复位之类的)
// 亮蓝灯
LED_BLUE;
}
// 配置按键GPIO
Key_GPIO_Config();
// IWDG 1s 超时溢出
IWDG_Config(IWDG_Prescaler_64, 625);
/*
while部分是我们在项目中具体需要写的代码,这部分的程序可以用独立看门狗来监控,如果我们知道这部分代码的执行时间,比如是500ms,那么我们可以设置独立看门狗的
溢出时间是600ms,比500ms多一点,如果要被监控的程序没有跑飞正常执行的话,那么执行完毕之后就会执行喂狗的程序,如果程序跑飞了那程序就会超时,到达不了喂狗
的程序,此时就会产生系统复位。但是也不排除程序跑飞了又跑回来了,刚好喂狗了,歪打正着。所以要想更精确的监控程序,可以使用窗口看门狗,窗口看门狗规定必须在
规定的窗口时间内喂狗。
*/
while(1)
{
// 这里添加需要被监控的代码,如果有就去掉按键模拟喂狗,把按键扫描程序去掉
if(Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PING) == KEY_ON)
{
// 喂狗,如果不喂狗,系统则会复位,复位后亮红灯,如果在1s
// 时间内准时喂狗的话,则会亮绿灯
IWDG_Feed(); // 喂狗
//喂狗后亮绿灯
LED_GREEN;
}
}
}
主函数中我们初始化好LED和按键相关的配置,设置IWDG 1s超时溢出之后,进入while死循环,通过按键来喂狗,如果喂狗成功, 则亮绿灯,如果喂狗失败的话,系统重启,程序重新执行,当执行到RCC_GetFlagStatus函数的时候,则会检测到是IWDG复位, 然后让红灯亮。如果喂狗一直失败的话,则会一直产生系统复位,加上前面延时的效果,则会看到红灯一直闪烁。
我们这里是通过按键来模拟一个喂狗程序,真正的项目中则不是这样使用。while部分是我们在项目中具体需要写的代码, 这部分的程序可以用独立看门狗来监控,如果我们知道这部分代码的执行时间,比如是500ms,那么我们可以设置独立看门狗的溢出时间是510ms, 比500ms多一点,如果要被监控的程序没有跑飞正常执行的话,那么执行完毕之后就会执行喂狗的程序,如果程序跑飞了那程序就会超时, 到达不了喂狗的程序,此时就会产生系统复位,但是也不排除程序跑飞了又跑回来了,刚好喂狗了,歪打正着。所以要想更精确的监控程序, 可以使用窗口看门狗,窗口看门狗规定必须在规定的窗口时间内喂狗,早了不行,晚了也不行。
3. 小结
看门狗可以理解为一个监控器,我们监控一个地方,如果程序正常不做反应,如出现错误则看门狗复位,我们可以简单回顾一下:
实验目的
- 理解独立看门狗的工作原理。
- 实现一个基本的看门狗定时器程序,确保程序在正常运行时不复位,异常情况下能够复位微控制器。
实验环境
- 开发板:STM32F103
- 开发工具:Keil uVision 或 STM32CubeIDE
- 硬件连接:无特别连接,只需开发板和电脑。
实验步骤
- 初始化IWDG: 配置IWDG的预分频器和重装载值。
- 主程序逻辑: 在主循环中,定期重装载IWDG。
- 故障模拟: 人为制造故障(如进入死循环),观察微控制器复位。
代码示例
#include "stm32f10x.h" // 包含STM32F10x库头文件
void IWDG_Config(void) {
// 使能写访问
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
// 设置预分频器为64
IWDG_SetPrescaler(IWDG_Prescaler_64);
// 设置重装载值
IWDG_SetReload(0xFFF); // 设置为最大值,约12秒超时(根据时钟频率)
// 重装载计数器
IWDG_ReloadCounter();
// 启动IWDG
IWDG_Enable();
}
int main(void) {
// 初始化IWDG
IWDG_Config();
// 主循环
while (1) {
// 模拟正常工作
// 在这里加入你的主程序逻辑
// 定期重装载看门狗
IWDG_ReloadCounter();
// 为了测试故障,模拟一次故障
// 可以注释掉下面这一行以进行正常运行测试
// if (/* some condition to simulate fault */) {
// while (1); // 进入死循环,观察IWDG复位
// }
}
}
说明
- IWDG_Config() 函数:
- 启用写访问,允许配置看门狗。
- 设置预分频器和重装载值。这里设置为最大值,以实现较长的超时。
- 调用
IWDG_ReloadCounter()
以初始化计数器。 - 启动看门狗定时器。
- 主循环:
- 在正常情况下,定期调用
IWDG_ReloadCounter()
以防止复位。 - 你可以通过条件控制模拟一个故障,例如进入一个死循环。
故障测试
- 运行程序,观察在正常情况下微控制器不会复位。
- 注释掉
IWDG_ReloadCounter()
的调用或强制进入死循环,观察微控制器是否复位。
2024.9.19 第一次修订,后期不再维护