STM32的看门狗分为独立看门狗和窗口看门狗。
第一部分 独立看门狗
独立看门狗由内部专门的40KHz的低速时钟驱动,即使主时钟发生了故障也仍然有效。需要注意的是看门狗的时钟是一个内部的RC时钟,并不是准确的40KHz,而是30Hz-60KHz之间的一个可变化的时钟,只是在估算的时候使用40KHz的频率来进行计算,因此看门狗的时间并不是很准确时钟有一定的偏差。
使用看门狗的原因是单片机系统在外接的干扰下会出现程序跑飞的现象导致出现死循环,看门狗就是为了处理这种现象发生。
几个常用函数:
- 取消寄存器写保护 – 使能/失能写权限
1 |
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); |
- 设置独立的看门狗预分频系数和重装在值
设置IWDO预分频系数
1 |
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值 |
设置看门狗重装载值
1 |
void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值 |
设置好之后就可以知道看门狗的喂狗时间了,该时间的计算方式为:Tout=((4×2^prer) ×rlr) /40 其中 prer为看门狗时钟的分频值单位是0-7 rlr是重装载值(IWDG_RLR的值)
比如我们设定 prer 值为 4,rlr 值为 625,那么就可以得到 Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是 1s。
- 重载计数值喂狗(向 IWDG_KR 写入 0XAAAA)
库函数里面重载计数值的函数是:
1 |
IWDG_ReloadCounter(); //按照 IWDG 重装载寄存器的值重装载 IWDG 计数器 |
通过这句,将使 STM32 重新加载 IWDG_RLR 的值到看门狗计数器里面。即实现独立看门狗的喂狗操作。
- 启动看门狗(向 IWDG_KR 写入 0XCCCC)
1 |
IWDG_Enable(); //使能 IWDG |
实现代码
wdg.h
1 2 3 4 5 6 7 8 |
#ifndef __WDG_H #define __WDG_H #include "sys.h" void IWDG_Init(u8 prer,u16 rlr); void IWDG_Feed(void); #endif |
wdg.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include "wdg.h" //初始化独立看门狗 //prer:分频数:0~7(只有低3位有效!) //分频因子=4*2^prer.但最大值只能是256! //rlr:重装载寄存器值:低11位有效. //时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms). void IWDG_Init(u8 prer,u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作 IWDG_SetPrescaler(prer); //设置IWDG预分频值:设置IWDG预分频值为64 IWDG_SetReload(rlr); //设置IWDG重装载值 IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器 IWDG_Enable(); //使能IWDG } //喂独立看门狗 void IWDG_Feed(void) { IWDG_ReloadCounter();//reload } |
然后再程序中喂狗即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "wdg.h" IWDG_Init(4,625); //初始化看门狗 分频数为64,重载值为625,溢出时间为1s void led0_task(void *pvParameters) { while(1) { LED0=~LED0; IWDG_Feed(); vTaskDelay(pdMS_TO_TICKS(50)); //0.5秒 } } |