关于本博文的介绍:
一 什么是看门狗?
单片机系统在正常执行程序时,当收到外界各种物理干扰或其他原因出现程序跑飞或者陷入死循环的现象,而使得正常的程序无法正常运行,导致MCU挂掉,看门狗就是为了解决这么个问题而出现的;
二 工作原理
在一定时间内(时间由看门狗定时计数器决定)没有接收到喂狗信号(表示MCU挂了),便实现处理器自动复位重启(发出复位信号);
** IWDG和WWDG的时钟源 **
从图中可以看出:
1.独立看门狗IWDG有自己独立的时钟源——LSI
2. 窗口看门狗WWDG的时钟源——PCLK1
由此图可以看出:在编程时,IWDG不需要使能时钟源,而WWDG需要;所以IWDG的操作会比较简单一些;
一 相关寄存器以及功能
(1)键值寄存器IWDG_KR
功能和使用方法:
(2)预分频寄存器IWDG_PR
功能和使用:
对照着对[2:0]位的介绍选择分频因子;
(3)重载寄存器IWDG_RLR
功能和使用方法:看方框中吧;
(4)状态寄存器IWDG_SR
功能和使用方法:看方框中吧;
二 编程步骤
取消寄存器写保护(也即是先IWDG_KR中写入0x5555)
目的:取消PR和RLR寄存器写保护,从而可以操作这两个寄存器
库函数:
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
设置预分频系数和重装载值
库函数:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
void IWDG_SetReload(uint16_t Reload);
这里要明白一个重要的概念:
Tout(ms) = ((4*2^prer) * rlr)/40;
Tout:要设置的溢出时间,也就是多久初始化一次MCU,单位是ms
prer :分频系数
rlr :重载值;
比如:prer = 4,rlr = 625时,Tout = 1000ms
重载计数值喂狗(向IWDG_KR写入0xAAAA)
库函数:
void IWDG_ReloadCounter(void);
启动看门狗(向IWDG_KR 写入0xCCCC)
库函数:
void IWDG_Enable(void);
自此,整个程序就完成了;比较简单;
“窗口”的原因:
因为喂狗的时间有一个时间上的限制,必须在一定时间范围内(窗口);这个时间范围(窗口)上限是相关寄存器配置;下限时间是0x40;在这段时间内要完成喂狗,否则将会发生MCU复位;
一 WWDG发出复位信号的条件
注意: 上面第二点需要特别注意,在后面进行编程的时候,我们会发现有两个喂狗函数:
1.看门狗设置计数器(喂狗)函数WWDG_SetCounter(0xXX),这是一个经常放在WWDG中断函数中的一个专门又来喂狗的函数,0XX被送往CR寄存器;
2.看门狗启动函数**WWDG_Enable(0xXX)**的这个括号里有一个0xXX值,也同样被送到CR函数执行了一次喂狗操作;
所以一定要注意一个原则:这两个函数的实参都不能是大于窗口值,否则就直接发生复位了;
**二 WWDG的特点 **
当MCU受到外界干扰或者内部干扰时候,导致程序出现跑飞或者死循环现象的时候,有一种情况是:程序在死循环的时候同时执行了喂狗程序,这就尴尬了,看门狗就无法起到了作用;
如果使用窗口看门狗,程序员可以根据程序执行的时间设置刷新看门狗的一个时间窗口,保证不会提前刷新看门狗或滞后刷新看门狗,这样可以检测出程序有没有正常的执行程序;
三 相关寄存器功能
先总结一下:
控制寄存器——WWDG_CR——使能WWDG,WWDG倒计数计时器;
配置寄存器——WWDG_CFG——设置唤醒中断标志位,设置分频因子,设置上窗口的值;
状态寄存器——WWDG_SR——唤醒中断位中断标志;
2.配置寄存器WWDG_CFG
[9] : EWI提前唤醒中断,说白了此位置1会开启WWDG中断,调用相应中断相应函数;
[8:7]:设置分频因子;经过此处分频后,即可得到CR寄存器中的递减周期;
[6:0]:窗口值,是可以喂狗和不可以喂狗的临界点,当此处的值大于计数器的值时方可喂狗,否则不可喂狗;
3.状态寄存器WWDG_SR
当EWIF位被置1,说明程序正在执行中断函数或并没有开启WWDG中断
四 窗口看门狗WWDG关于周期的计算:
《STM32f103使用手册》中给出了下面这个超时公式,但是我觉得实在是有些无厘头的计算,为什么要给一个T[5:0]的计算,并且我也没搞懂所谓的超时公式这个“超时”到底超的是谁;所以我觉得要正确的配置窗口值和喂狗的值只要对计数器T[6:0]的递减周期足够理解就好了;
所以我总结如下:
一,计数器T[6:0]的递减周期:T1 = (4096*2^WDGTB)/PCLK1;
PCLK1:APB1上的时钟频率,在库函数提供的默认配置下,PCLK1默认为36MHz;
WDGTB:分频系数(1,2,4,8);
二,在配置窗口值,喂狗值时要遵循的规则:
五 编程步骤
一定要切记这个步骤,不然因为对EWIF位的不理解导致错误
(1) 开启WWDG时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
(2)设置窗口值和分频系数值(配置WWDG_CFG)
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);//设置分频因子
void WWDG_SetWindowValue(uint8_t WindowValue);//设置窗口值
(3)使能WWDG,并加载初值
void WWDG_Enable(uint8_t Counter);
这里需要特别注意:如果说Counter的值为0x7F(MAX),会使得WWDG_SR寄存器中的EWIF位(提醒中断标志位)。
(4)配置WWDG的中断NVIC
(5)开启WWDG中断并清除提醒中断标志位EWIF;
void WWDG_EnableIT(void); /
void WWDG_ClearFlag(void); //WWDG_SR的EWIF清零,如果不清零会使得程序无法进入到WWDG中断函数;
(6)中断函数
void WWDG_IRQHandler(void)
{
if(WWDG_GetFlagStatus())
{
WWDG_SetCounter(喂狗值);
//逻辑代码;
}
WWDG_ClearFlag();
}