一、引言
在嵌入式系统中,看门狗定时器(Watchdog Timer, WDT)是一种用于监控系统运行状态的硬件或软件定时器。如果系统因为软件错误或其他原因陷入死循环或长时间无响应,看门狗定时器会触发系统复位,以确保系统能够自动恢复运行。
本次作业用到独立看门狗,独立看门狗(Independent Watchdog, IWDG)是 STM32 微控制器中的一种硬件定时器,用于在系统出现故障(如陷入死循环或长时间无响应)时自动复位系统。它独立于主系统时钟运行,通常使用内部低速时钟(LSI)作为时钟源,这使得它即使在主系统时钟出现故障时也能正常工作。
喂狗(Feeding the Watchdog)
“喂狗”是指在看门狗定时器溢出之前,通过软件重置看门狗定时器的计数器。通常,这是在主程序正常执行时定期进行的操作。通过“喂狗”,可以告诉看门狗系统正在正常运行,不需要复位。典型地,这通过调用一个特定的函数(如 IWDG_Feed()
)来完成。
不喂狗(Not Feeding the Watchdog)
“不喂狗”是指看门狗定时器在预设的时间内没有被重置。这通常意味着系统出现了问题,例如程序陷入死循环、无响应或者长时间执行某个任务未完成。在这种情况下,看门狗定时器会溢出并触发系统复位。
二、代码
1.main.c
IWDG_Config(IWDG_Prescaler_64 ,625); 用来配置看门狗定时器,使其在1秒后超时
主循环则用来检测按键是否按下:
1s内如按下则喂狗,将调用 IWDG_Feed()
重置看门狗定时器,LED常亮
若未按下则不喂狗,1s后看门狗定时器超时,系统会自动复位,所有外设和 GPIO 将重新初始化,LED熄灭;系统复位后,程序会重新从 main()
函数开始执行,LED1_ON()使LED再次变亮,如此循环往复,达到1s亮1s灭的效果
#include "stm32f10x.h"
#include "LED.h"
#include "KEY.h"
#include "iwdg.h"
static void delay(uint32_t time);
uint8_t KeyNum;
int main(void)
{
LED_Init();
KEY_Init();
delay(1000);
/* IWDG 1s 超时溢出 */
IWDG_Config(IWDG_Prescaler_64 ,625);
LED1_ON();
while(1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
/*喂狗,如果不喂狗,系统则会复位,LED1则会灭一次,如果在1s
时间内准时喂狗的话,则LED1会常亮 */
IWDG_Feed();
}
}
}
static void delay(uint32_t time)
{
uint32_t i,j;
for(i=0;i<time;++i)
{
for(j=0;j<10000;++j)
{
//空循环,什么都不做
}
}
}
2.iwdg.c
IWDG_Config
()用于配置看门狗定时器,包括设置预分频值和重装载值。预分频值决定了计数器的时钟频率,重装载值决定了计数器的初始值。配置完成后,计数器开始从重装载值开始倒计时。
IWDG_Feed
()用于在计数器倒计时至零之前重置计数器。这相当于“喂狗”,防止看门狗触发系统复位。如果在看门狗超时前未调用 IWDG_Feed()
,计数器将倒计时至零,触发系统复位。
具体请见代码旁的注释
#include "stm32f10x.h"
#include "iwdg.h"
void IWDG_Config(uint8_t prv ,uint16_t rlv)
{
/* 使能 预分频寄存器PR和重装载寄存器RLR可写 */
IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );
/* 设置预分频器值,prv 决定了计数器的分频比,从而影响超时时间 */
IWDG_SetPrescaler( prv );
/* 设置重装载寄存器值,rlv 决定了计数器的初始值,结合预分频器值一起决定了超时时间 */
IWDG_SetReload( rlv );
/* 把重装载寄存器的值放到计数器中,立即重置计数器的值 */
IWDG_ReloadCounter();
/* 使能IWDG,开始倒计时 */
IWDG_Enable();
}
/**
* 函数功能: 喂狗
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void IWDG_Feed(void)
{
/* 把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
当计数器的值减到0的时候会产生系统复位 */
IWDG_ReloadCounter();
}
3.iwdg.h
#ifndef __IWDG_H__
#define __IWDG_H__
#include <stm32f10x.h>
void IWDG_Feed(void);
void IWDG_Config(uint8_t prv ,uint16_t rlv);
#endif
4.其他
KEY和LED的代码和之前一样不用改
三、实验结果
一开始按了按键喂狗所以LED常亮,后来不按了不喂狗所以LED开始1s亮1s灭
作业七
四、总结
这次作业让我更好地了解了看门狗,在老师给的代码基础上进行修改,顺利完成了本次作业,锻炼了我的动手实践能力,拓展了专业知识,令我受益匪浅