前言
大家好啊!前几天跟一个朋友聊天时,他说:“我自制了一个家庭烟雾报警系统,然后固定在天花板上,但最近老是出问题,这个小玩意老是时不时崩了,每次我都要去搬个梯子,爬上天花板,将其复位,太折磨人了,有什么好方法吗?”我听完,笑着说:“养条狗啊,让狗帮你复位。”他不解:“啊???”
一、看门狗是什么?
是这个???
答曰:不是!
看门狗本质就是一个定时器 , 每到达一段时间就复位一次,重新开始程序,防止程序卡死。在stm32中,有两条看门狗,分别是独立看门狗 (IWDG) 和窗口看门狗(WWDG),本次我们讲独立看门狗。
二、独立看门狗
2.1、简介
独立看门狗 (IWDG) 由其专用低速时钟 (LSI) 驱动,因此即便在主时钟发生故障时仍然保持工作状态,IWDG 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。
由时钟树可知,LSI低速内部时钟频率为32Khz。但是,LSI低速内部时钟频率及其不稳定,会产生偏振,偏振范围大概为30-60Khz。
2.2、特性
● 自由运行递减计数器 — 计数方向:递减
● 时钟由独立 RC 振荡器提供(可在待机和停止模式下运行-低功耗)—> LSI内部低速时钟:32Khz (30Khz - 60Khz)
● 当递减计数器值达到 0x000 时产生复位(如果看门狗已激活)—> 所以要在计数器减到0之前进行喂狗。
2.3、框图
2.4、喂狗时间
已知:时钟频率LSI:30Khz - 60Khz ,分频数:16 ,重载值:1000
如何计算最长喂狗时间和最短喂狗时间?
使用30Khz计算出最长周期:
T= 重载值 / (30Khz / 分频数)
= 1000 / (30Khz / 16 )
= 533.33ms
需要在533.33ms之前进行喂狗
使用60Khz计算出最短周期:
T=重载值 / (60Khz / 分频数)
=1000 /(60Khz / 16 )
=266.67ms
需要在266.67ms之前进行喂狗
因此:如果想确保喂狗成功的话,在266.67ms之前进行喂狗100%能成功喂上。
三、独立看门狗寄存器
关键字寄存器 (IWDG_KR)
1、写入0xAAAA,①将重载值加载到计数器中,②喂狗操作
2、写入0x5555 可使能对 IWDG_PR 和 IWDG_RLR 寄存器的访问
3、写入0xCCCC 使能看门狗
预分频器寄存器 (IWDG_PR) 设置分频数
位 2:0 PR[2:0]:预分频器 (Prescaler divider)
这些位受写访问保护,请参见第 18.3.2 节。通过软件设置这些位来选择计数器时钟的预分频 因子。若要更改预分频器的分频系数,IWDG_SR 的 PVU 位必须为 0。
000:4 分频
001:8 分频
010:16 分频
011:32 分频
100:64 分频
101:128 分频
110:256 分频
111:256 分频
重载寄存器 (IWDG_RLR)
设置重载值
重载值可在0 - 4095中进行设置,向IWDG_KR写入0xAAAA重载值会加载到计数器中进行递减计数。
四、独立看门狗实验
/*
函数功能:独立看门狗初始化
返回值:void
形参:void
函数说明:
*/
void Iwdg_Init(void)
{
IWDG->KR = 0x5555; //在KR寄存器写入0x5555,解除PR和RLR寄存器写访问保护
IWDG->PR |= 2 << 0; //设置预分频数 16分频
IWDG->RLR = 1000 - 1; //设置重装值
IWDG->KR = 0xAAAA; //在KR寄存器写入0xAAAA,加载重装值
IWDG->KR = 0xCCCC; //使能独立看门狗
}
主函数里,我用毫秒延时函数卡主程序,并在while里进行喂狗。正常情况下,如果喂狗成功,灯只会闪烁一次,如果灯一直闪烁,就说明喂狗失败,看门狗一直在复位程序。
LED1_ON;
delay_ms(100);
LED1_OFF;
delay_ms(100);
while(1)//防止单片机跑飞
{
delay_ms(325);
IWDG->KR = 0xAAAA; //喂狗
}
后续
我把独立看门狗的工作原理告诉了我朋友,他连说:“好狗好狗。”他将烟雾报警系统代码加上看门狗后,再也不用搬梯子去手动复位了,都交给狗办。