看门狗的作用
什么叫看门狗
在我们平时编写程序中,偶尔会因为逻辑方面的错误导致代码卡在某一部分进入一种死循环状态,而看门狗的作用就是用来检测你的程序会不会跑飞,一旦程序跑飞,看门狗便会帮你将程序进行复位。(看门狗帮助程序恢复正常状态)
程序跑飞: 是指系统受到某种干扰后,程序计数器PC的值偏离了给定的唯一变化历程,导致程序运行偏离正常的运行路径.程序跑飞因素及后果往往是不可预计的.在很多情况下,程序跑飞后系统会进入死循环而导致死机。
复位: 使程序重头开始运行。
复位方式:
1.硬件复位:不及时,不方便 – 环境特殊的环境
2.软件复位:程序都会跑飞 – 自动复位的方式进行处理
3.上电复位:不及时
4.看门狗复位:本质是一个递减计数器,这个递减计数器一旦递减到0,看门狗就会将程序进行复位,而如果在正常情况中,用到看门狗可能会造成一直复位的情况,所以需要定时进行喂狗操作,即在计数器递减到0之前,将重装载值加载到计数器中,不让其递减到0,在发生异常时,看门狗未定时进行到喂狗操作便会复位程序。
STM32的看门狗分类
芯片当中具有两个嵌入式看门狗外设,具有安全性高,定时准确及使用灵活的优点。两个看门狗外设(独立看门狗和窗口看门狗)均可用于检测并解决由软件错误导致的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。
独立看门狗 (IWDG) 由其专用低速时钟 (LSI) (内部低速时钟)驱动,因此即便在主时钟发生故障时仍然保持工作状态。窗口看门狗 (WWDG) 时钟由 APB1 时钟经预分频后提供,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。
IWDG(独立看门狗) 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。
WWDG (窗口看门狗)最适合那些要求看门狗在精确计时窗口起作用的应用程序。
独立看门狗
独立看门狗简介
独立看门狗 (IWDG) 由其专用低速时钟 (LSI) 驱动,因此即便在主时钟发生故障时仍然保持工作状态。
独立看门狗框架
要想看门狗能狗正常工作,首先需要时钟源,而独立看门狗的时钟源由其专用低速时钟(LSE)提供,并且需要看门狗计数器计数,就需要配置重装载值,而需要对时钟源频率进行分频和配置重装载值,首先需要取消看门狗的写保护,允许看门狗计数的寄存器能够进行写操作,所以需要向密钥寄存器(IWDG_KR) 写入0x5555,才能够进行写操作,并且写入任意值后启动写保护。
接下来再对相应寄存器进行配置:
1.根据寄存器要求写入相应分频(8种分频)
2.向重载寄存器中写入12位重装载值
3.防止配置期间,看门狗计数完成,先进行一边喂狗操作
4.启动看门狗
相关代码如下:
/*
函 数 名:IWDG_Config
函数功能:独立看门狗复位
返 回 值:无
形 参:无
备 注:
32KHz -- 8分频 -- 4KHz 重装载500ms
由于看门狗进行复位是计数由1到0便会复位,所以这里重装载值不用进行减1
*/
void IWDG_Config(void)
{
IWDG->KR = 0x5555; //取消写保护
IWDG->PR = 0x01; //预分频器 8分频
IWDG->RLR = 2000; //重装载 500ms
IWDG->KR = 0xAAAA; //喂狗
IWDG->KR = 0xCCCC; //启动看门狗
}
相应的喂狗操作,可以选择相应延时喂狗或者时间片任务喂狗来观察程序是否复位。
窗口看门狗
窗口看门狗特征
与独立看门狗一样、本质都是递减计数器、但因为窗口看门狗挂接在APB1总线上,则需要配置时钟。
注: 不过窗口看门狗的喂狗时间有一个范围:
1.重装载值T6位变为0之前喂狗(重装载值和计数器都为7位)
2.递减到窗口值之后喂狗
窗口看门狗框架
根据上面寄存器的介绍来看,可以看出窗口看门狗并没有用作分频比的位,而是通过选择定时器时基来选择计数周期,每隔(4096*2^WDGTB)个周期递减一次。
例:
时钟源频率=42MHz
选择分频器8,WDGTB = 3
计数器值 = 0x7f
窗口值 = 0x6f
计数一次的时间——>4096x2^3/42us =780.190us
从计数器值到窗口值需要计数16次,到0x40需要计数64次
则计算最早喂狗时间 = 12.483ms
最晚喂狗时间 = 49.932ms
代码流程:
- 打开时钟(WWDG)
- 计数器值(喂狗)
- 窗口值
- 分频
- 使能
- 喂狗时间
/*
函 数 名:WWDG_Config
函数功能:窗口看门狗复位
返 回 值:无
形 参:无
备 注:
42MHz 1/42us
分频比 4096*2^3 = 32768
计数一次的时间为:780.190us
到窗口值为12.483ms
到0x40为49.932ms
*/
void WWDG_Config(void)
{
RCC->APB1ENR |= (1<<11); //打开窗口看门狗时钟
WWDG->CR |= (0x7f<<0); //重装载值,计数器值
WWDG->CFR &= ~(0x7f<<0); //窗口值清零
WWDG->CFR |= (0x6f<<0); //设置窗口值
WWDG->CFR |= (0x03<<7); //选择分频器8
WWDG->CR |= (0x01<<7); //使能窗口看门狗
}