今天学习了一下独立看门狗,看门狗的主要作用就是防止程序中有死循环或是不知道的bug,而造成在while循环中没有及时喂狗,程序就会控制单片机重启复位,从而不至于影响程序一直不能正常工作。
其实看门狗的应用也不是很复杂,主要分了4步,第一步还不用任何操作。
第一步:开启LSI的时钟(打开看门狗会自动开LSI,所以这一步什么都不做)
第二步:写入0x5555 解除写保护 (IWDG_WriteAccessCmd())
第三步:写入预分频器IWDG_PR和重装寄存器IWDG_RLR 超时时间:Tiwdg= Tlsi * PR预分频 系数 X (RL+1) Tlsi=1/Flsi (喂狗)
IWDG_SetPrescaler()写预分频器
IWDG_SetReload()写重装值
IWDG_ReloadCounter()(喂狗)
第四步:写入0xCCCC 启动独立看门狗
为了验证是不是由看门狗引起的复位,特此调用rcc里面的检查独立看门狗的复位标志位,来显示不同的字符串,就可以看出来到底是手动复位还是看门狗复位了。
下面就是启动看门狗的四步了:
这里就要仔细的看看预分频系数和重装值的计算了:
最后就是在while循环中不停地喂狗了,如果while循环在1秒内能够循环一次,喂一次狗,单片机就不会重启,如果超过了1秒钟还没有喂狗那就有可能程序中有bug需要重启来解决这个问题了。
main.c的源文件:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Delay.h"
int main(void)
{
OLED_Init(); //oled 屏幕初始化
/*
第一步:开启LSI的时钟(打开看门狗会自动开LSI,所以这一步什么都不做)
第二步:写入0x5555 解除写保护 (IWDG_WriteAccessCmd())
第三步:写入预分频器IWDG_PR和重装寄存器IWDG_RLR 超时时间:Tiwdg= Tlsi * PR预分频系数 X (RL+1) Tlsi=1/Flsi (喂狗)
IWDG_SetPrescaler()写预分频器
IWDG_SetReload()写重装值
IWDG_ReloadCounter()(喂狗)
第四步:写入0xCCCC 启动独立看门狗
*/
OLED_ShowString(1,1,"IWDG Reset");
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) //如果(RCC读看门狗复位标志位为1)
{
OLED_ShowString(2,1,"IWDG RST"); // 显示:IWDG RST
Delay_ms(500); // 等待500毫秒
OLED_ShowString(2,1," "); // 显示:空格
Delay_ms(500); // 等待500毫秒
RCC_ClearFlag(); //清除看门狗复位标志位
}
else //否则:
{
OLED_ShowString(3,1,"RST"); // 显示:RST
Delay_ms(500); // 等待500毫秒
OLED_ShowString(3,1," "); // 显示:空格
Delay_ms(500); // 等待500毫秒
}
//第二步:写入0x5555 解除写保护 (IWDG_WriteAccessCmd())
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//第三步:写入预分频器IWDG_PR和重装寄存器IWDG_RLR
//IWDG_SetPrescaler()写预分频器
//IWDG_SetReload()写重装值
//IWDG_ReloadCounter()(喂狗)
IWDG_SetPrescaler(IWDG_Prescaler_16); //比如设置超时时间为1000ms Tlsi=1/40KHz 0.025ms 预分频系数设为16 那重装值=1000/0.025/16-1
IWDG_SetReload(2499);
IWDG_ReloadCounter(); //喂一次狗
IWDG_Enable(); //启动看门狗
while(1)
{
IWDG_ReloadCounter(); //喂一次狗
Delay_ms(1050); //这个延时过长就会触发看门狗复位
}
}
这样编译下载后就能看到程序的最终效果: