赞
踩
顾名思义,看门狗可理解为看门(看程序),一切正常就不会叫,一旦出现异常,就会叫,从而将信息反馈给我们。因此,他是用来监测单片机运行状态和解决程序引起的故障的模块。
看门狗的作用:程序运行的保障措施。在程序中定期喂狗,在程序卡死的情况下,自动帮我们复位,看门狗就是一个自动复位电路,防止程序长时间卡死。其本质就是一个定时器,定时器溢出,产生复位信号。
看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性。看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号。
看门狗主要分为:1.独立看门狗;2.窗口看门狗
独立工作,对时间精度要求较低,这里独立工作指的是独立看门狗的时钟是专用的LSI(内部低速时钟),即使主时钟出现问题,看门狗也能正常工作。
独立看门狗的工作流程:
1.内部低速时钟LSI通过预分频后得到了分频后的时钟信号(橙色箭头);
2.该时钟信号驱动递减计数器,每来一个时钟,自减一个数,当自减到0后产生IWDG复位(绿色箭头);
3.正常运行时,为了避免复位,可提前在重装寄存器写一个值,IWDG_RLR与定时器的ARR是一样的,当预先写好值之后,在运行过程中,在键寄存器里,写入一个特定的数据,控制电路进行喂狗,这时重装值就会复制到当前的计数器中,这样计数器就会回到重装值,重新自减运行了(红色箭头)。
那么什么是键寄存器呢?
键寄存器本质上是控制寄存器,用于控制硬件电路的工作在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率。具体的键寄存器值对应的作用如下表示:
注:看门狗功能处于VDD供电区,即在停机与待机模式下仍能正常工作。
超时时间:T_IWDG = T_LSI × PR × (RL + 1);
其中: T_LSI=1/F_LSI,PR是预分频系数;RL+1是重装值
对应的预分频系数PR,如PR=0为4分频,PR=1为8分频,以此类推。
窗口看门狗要求看门狗在精确计时窗口起作用,设定一个时间窗口,喂早了、喂晚了都会复位。窗口看门狗使用的是APB1的时钟,没有专有的时钟。窗口看门狗对喂狗时间更严格,他有一个喂狗时间窗口,必须在该窗口内喂狗,过早过晚喂狗都不行。
窗口看门狗的工作流程与独立看门狗类似:
1.首先是来自RCC的时钟(PCLK1),PCLK1时钟进来之后,会先执行一个固定的4096分频,再进入与分频器进行分频;
2.分频之后的时钟,驱动这个计数器进行计数,每来一个时钟,计数器自减一次,最高位T6当做溢出标志位。该位为1:计数器未溢出;该位为0:计数器溢出。
3.当T6位为0时,会通过下面的线路产生复位信号(红色箭头)。
以上是超时时间产生的复位。
4.绿色框是看门狗配置寄存器,这里写最早的时间界限,这些值写入之后是固定不变的。一旦执行写入CR操作,与门开关就会打开,写入CR,也就是喂狗,在喂狗时,比较器开始工作,一旦发现当前的计数器T6:0>窗口值W6:0(过早喂狗),比较结果就=1,通过或门也能申请复位。这就是喂狗最早时间窗口实现的流程。这个过程就是在喂狗时,把当前计数值与预设的窗口值进行比较。
以上是窗口时间未到产生的复位
超时时间:T_WWDG=T_PCLK1 x 4096 x WDGTB预分频系数× (T[5:0] + 1)
窗口时间:T_WIN = T_PCLK1 x 4096 x WDGTB预分频系数× (T[5:0] - W[5:0])
注: TPCLK1 =1 / FPCLK1=1/36Mhz;PCLK1时钟进来之后,其先执行了一个固定的4096分频;WDGTB:预分频;T[5:0] - W[5:0]指的是计数器减到窗口值的时间。
WDGTB就是预分频,如WDGTB=0就是2的0次方,就是1分频;WDGTB=1就是2的1次方,就是2分频,以此类推。
- #include "stm32f10x.h" // Device header
- #include "OLED.h"
- #include "Delay.h"
- #include "Key.h"
-
- uint8_t KeyNum;
-
- int main(void)
- {
- OLED_Init();
- Key_Init();
-
-
- /*
- 看门狗--代码流程
-
- 第一步:开启时钟
- 开始LSI的时钟由硬件自动开启(开启看门狗之后,LSI会强制开启)
- 第二步:解除写保护
- 在写入这两个寄存器之前,要先解除写保护
- 第三步:写预分频寄存器与重装寄存器值
- 第四步:启动看门狗
- 第五步:不断喂狗
- **/
-
- OLED_ShowString(1,1,"IWDG_TEST");
-
- if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) ==SET)
- {
- OLED_ShowString(2,1,"IWDGRSET");
- Delay_ms(500);
- OLED_ShowString(2,1," ");
- Delay_ms(100);
-
- RCC_ClearFlag();
- }
- else
- {
- OLED_ShowString(3,1,"SET");
- Delay_ms(500);
- OLED_ShowString(3,1," ");
- Delay_ms(100);
- }
-
- //解除写保护
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
- //配置预分频与重装值
- IWDG_SetPrescaler(IWDG_Prescaler_16);
- IWDG_SetReload(2499); //喂狗时间设置为:1000ms
- //喂狗
- IWDG_ReloadCounter(); //重装的值就是2499
- //启动看门狗
- IWDG_Enable();
-
- while(1)
- {
- Key_GetNum();
- //喂狗
- IWDG_ReloadCounter(); //重装的值就是2499
-
- OLED_ShowString(4,1,"FEED");
- Delay_ms(200);
- OLED_ShowString(4,1," ");
- Delay_ms(600);
- }
- }
- #include "stm32f10x.h" // Device header
- #include "OLED.h"
- #include "Delay.h"
- #include "Key.h"
-
- uint8_t KeyNum;
-
- int main(void)
- {
- OLED_Init();
- Key_Init();
-
-
- /*
- 看门狗--代码流程
-
- 第一步:开启时钟
- 开始LSI的时钟由硬件自动开启(开启看门狗之后,LSI会强制开启)
- 第二步:解除写保护
- 在写入这两个寄存器之前,要先解除写保护
- 第三步:写预分频寄存器与重装寄存器值
- 第四步:启动看门狗
- 第五步:不断喂狗
- **/
-
- OLED_ShowString(1,1,"WWDG_TEST");
-
- if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) ==SET)
- {
- OLED_ShowString(2,1,"WWDGRSET");
- Delay_ms(500);
- OLED_ShowString(2,1," ");
- Delay_ms(100);
-
- RCC_ClearFlag();
- }
- else
- {
- OLED_ShowString(3,1,"SET");
- Delay_ms(500);
- OLED_ShowString(3,1," ");
- Delay_ms(100);
- }
-
-
- //窗口看门狗初始化
- //第一步:开启时钟
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
-
- //第二步:配置预分频器与窗口值
- WWDG_SetPrescaler(WWDG_Prescaler_8);
- WWDG_SetWindowValue(0x40|21); //30~50ms
- //第三步:写入控制器CR,控制寄存器包括:看门狗使能位、计数器溢出位、计数器有效位。
- WWDG_Enable(0x40|54);//或上0x40
-
- while(1)
- {
- Key_GetNum();
-
- // OLED_ShowString(4,1,"FEED");
- // Delay_ms(5);
- // OLED_ShowString(4,1," ");
- Delay_ms(49);
- WWDG_SetCounter(0x40|54); //喂狗
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。