看门狗——用于检测单片机程序运行状态的模块或芯片
在由单片机构成的微型计算机系统中
由于外界电磁场的干扰,会造成程序的跑飞,陷入死循环
所以需要看门狗来实时检测单片机运行状态
检测原理
- 向键值寄存器写入 0xcccc,开始启用独立看门狗,此时计时器开始从复位值(oxfff)递减,当尾值达到 0x000 时产生复位信号
- 任何时候,只要在键值寄存器中写入 0xaaaa(喂狗),自动装载寄存器的值就会查询加载到计时器,从而避免看门狗复位
- 如果程序异常,就会无法正常按时喂狗,从而使计时器尾值达到 0x000 产生复位信号,使系统复位
需要解决的问题
- 程序正常运行时,系统不能复位
- 系统跑飞时(程序异常执行),复位系统,重新执行程序
STM32内置两种
- 独立看门狗(IWDG)
由专门的低速时钟(LS I)驱动
即时主时钟发生故障,任然有效
适合需要看门狗作为一个在主程序之外能够完全独立工作,且对时间精度要求低的情况 - 窗口看门狗()
由APB1指针分频后得到的时钟驱动
通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作
适合要求看门狗在精确计时窗口起作用
独立看门狗
IWDG = Internal Watchdog=内部的 看狗
相关的库函数和定义分布在文件 stm32f10x_iwdg.h 和 stm32f10x_iwdg.c 中
操作看门狗要用到的库函数
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);//取消写保护,可以使用寄存器了
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//设置预分频系数,向PR寄存器写入值
void IWDG_SetReload(uint16_t Reload);//设置重装载值,向RLR寄存器写入值
void IWDG_ReloadCounter(void);//喂狗
void IWDG_Enable(void);//使能看门狗
FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);//获取状态
操作步骤
- 取消寄存器写保护
access——通道,机会,权力
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
- 设置独立看门狗的预分频系数,确定时钟
prescaler——预分频器
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
- 设置看门狗的重装载值,确定溢出时间
reload——重新装入
void IWDG_SetReload(uint16_t Reload);
- 使能看门狗
void IWDG_Enable(void);
- 应用程序喂狗
counter——计时器
void IWDG_ReloadCounter(void);
代码
建立好 iwdg.c 和 iwdg.h 后
在 iwdg.h 中
#ifndef __WDG_H
#define __WDG_H
#include "sys.h"//引入其他系统头文件
void IWDG_Init(u8 prer,u16 rlr);
#endif
之后向 FWILB 文件夹中手动 add stm32f10x_iwdg.c (位于scr下)并编译
在 iwdg.c 中
#include "iwdg.h"
//prer:分频数:0~7(只有低 3 位有效!)
//分频因子=4*2^prer.但最大值只能是 256!
//rlr:重装载寄存器值:低 11 位有效.
//复位时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms). 40ms是个估值
//超过复位时间不喂的话, 会复位系统
void IWDG_Init(u8 prer,u16 rlr)//初始化看门狗
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消寄存器写保护
IWDG_SetPrescaler(prer );//该参数要从外部传入
IWDG_SetReload(rlr );//也需要从外部传入
IWDG_ReloadCounter();//没有参数
IWDG_Enable();//也没有参数
}
两个参数
- 设置预分频数
- 设置重装寄存器值
通过计算式 Tout=((4*2^prer)*rlr)/40 (ms) 可知
当复位时间为 1s 时
设置预分频数=4 ,重装寄存器值=625
在 main.c 中
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "iwdg.h"//因为要使用到看门狗,需要引入看门狗的头文件
int main(void)
{
u8 t=0;
delay_init(); //延时函数初始化
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //初始化与按键连接的硬件接口
delay_ms(200);
LED0=0; //点亮LED
IWDG_Init(4,625);//调用看门狗的初始化
/*当到达复位时间后还没有手动按下按键,系统会复位,使LED灯闪烁
一直在1s内按按键时LED灯则会一直灭*/
while(1)//这里设置为了手动按按键来喂狗(便于观察效果),一般是程序执行喂狗操作
{
if(KEY_Scan(0)==WKUP_PRES)//当没有在一秒内按下按键,看门狗就会复位系统
{
IWDG_ReloadCounter();//当检测到按键按下时,进行喂狗操作
}
}
}
其他文件根据需要建立