stm32 学习笔记(8)看门狗

一、简介

STM32系列微控制器的看门狗是一种硬件机制,用于监控系统的运行状态,并在程序出现异常或进入死循环时自动复位系统。通过使用看门狗,开发者可以在一定程度上确保系统在面对不确定因素或异常情况下依然能够稳定运行,减少了系统崩溃或挂起的风险。这对于那些要求高可靠性、长时间稳定运行的嵌入式设备尤其重要。

STM32提供了两种类型的看门狗:

独立看门狗(IWDG)和窗口看门狗(WWDG),接下来分别先介绍一下两种看门狗。

二、独立看门狗

STM32 的独立看门狗由内部专门的40Khz低速时钟驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部RC时钟,所以并不是准确的40Khz,而是 在30~60Khz 之间的一个可变化的时钟,只是我们在估算的时候,以40Khz的频率来计算,看 门狗对时间的要求不是很精确,所以,时钟有些偏差,都是可以接受的。

接下来来认识几个相关的寄存器。(具体配置参考stm32中文手册独立看门狗)

IWDG_KR:启动IWDG和访问寄存器的控制。

IWDG_PR:设置预分频器的值,控制计时器的时钟频率。

IWDG_RLR:设置重载值,控制计时器倒计时的周期。

IWDG_SR:查看看门狗状态。

通过配置这些寄存器,就可以实现看门狗的功能了。那如何实现呢?

1)向IWDG_KR写入0X5555。 通过这步,我们取消IWDG_PR和IWDG_RLR的写保护,使后面可以操作这两个寄存器。 设置IWDG_PR和IWDG_RLR的值。 这两步设置看门狗的分频系数,和重装载的值。由此,就可以知道看门狗的喂狗时间(也 就是看门狗溢出时间),该时间的计算方式为: Tout=((4×2^prer) ×rlr) /40 其中Tout 为看门狗溢出时间(单位为ms);prer为看门狗时钟预分频值(IWDG_PR值), 范围为0~7;rlr为看门狗的重装载值(IWDG_RLR的值); 比如我们设定prer值为4,rlr值为625,那么就可以得到Tout=64×625/40=1000ms,这样, 看门狗的溢出时间就是1s,只要你在一秒钟之内,有一次写入0XAAAA到IWDG_KR,就不 会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。

2)向IWDG_KR写入0XAAAA。 通过这句,将使STM32重新加载IWDG_RLR的值到看门狗计数器里面。即实现独立看门 狗的喂狗操作。

3)向IWDG_KR写入0XCCCC.通过这句,来启动STM32的看门狗.注意IWDG在一旦启用,就不能再被关闭!想要关 闭,只能重启,并且重启之后不能打开IWDG,否则问题依旧,所以在这里提醒大家,如果不用IWDG的话,就不要去打开它,免得麻烦。

通过上面3个步骤,我们就可以启动STM32的看门狗了,使能了看门狗,在程序里面就 必须间隔一定时间喂狗,否则将导致程序复位。

代码示例

 
//初始化独立看门狗 
//prer:分频数:0~7(只有低 3 位有效!) 
//分频因子=4*2^prer.但最大值只能是256! 
//rlr:重装载寄存器值:低11 位有效. 
void IWDG_Init(u8 prer,u16 rlr)  
{ 
IWDG->KR=0X5555;//使能对 IWDG->PR 和 IWDG->RLR 的写   
IWDG->PR=prer;  //设置分频系数    
IWDG->RLR=rlr;  //从加载寄存器 IWDG->RLR   
IWDG->KR=0XAAAA;//reload               
IWDG->KR=0XCCCC;//使能看门狗  
} 
//喂独立看门狗 
void IWDG_Feed(void) 
{ 
IWDG->KR=0XAAAA;//reload  
}

三、窗口看门狗

STM32的窗口看门狗是一种具有窗口机制的看门狗,它要求在特定的时间窗口内喂狗(重新加载计数器),如果在窗口外进行喂狗,系统会复位。与独立看门狗相比,窗口看门狗在喂狗操作上有更严格的时序要求,提供了更高的时间控制精度。窗口看门狗通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序 背离正常的运行序列而产生的软件故障。

STM32的窗口看门狗主要涉及以下寄存器,它们用于配置看门狗的预分频、计数器、窗口值以及状态等。

WWDG_CR:启动看门狗并设置计数器初值。

WWDG_CFR:配置窗口值和预分频器。

WWDG_SR:查看看门狗状态。

实现功能(这里用的是中断的办法)

1)使能WWDG时钟。WWDG 不同于 IWDG,IWDG 有自己独立的 40Khz 时钟,不存在使能问题。而 WWDG 使用的是PCLK1的时钟,需要先使能时钟。

2)设置WWDG_CFR和WWDG_CR两个寄存器。在时钟使能完后,我们设置WWDG的CFR和CR两个寄存器,对WWDG进行配置。包 括使能窗口看门狗、开启中断、设置计数器的初始值、设置窗口值并设置分频数WDGTB等。

3)开启WWDG中断并分组 。在设置完了 WWDG 后,需要配置该中断的分组及使能。这点通过我们之前所编写的 MY_NVIC_Init 函数实现就可以了。

4)编写中断服务函数

。在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当 窗口看门狗计数器值减到0X3F 的时候,就会引起软复位了。在中断服务函数里面也要将状态 寄存器的EWIF位清空。

代码示例

//保存WWDG计数器的设置值,默认为最大.  
u8 WWDG_CNT=0x7f;  
//初始化窗口看门狗   
//tr   
:T[6:0],计数器值  
//wr   
:W[6:0],窗口值  
//fprer:分频系数(WDGTB),仅最低2位有效  
//Fwwdg=PCLK1/(4096*2^fprer).  
void WWDG_Init(u8 tr,u8 wr,u8 fprer)  
{     
RCC->APB1ENR|=1<<11;      
//使能wwdg时钟  
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.      
WWDG->CFR|=fprer<<7;       
//PCLK1/4096 再除 2^fprer 
WWDG->CFR&=0XFF80;       
 WWDG->CFR|=wr;        //设定窗口值       
 WWDG->CR|=WWDG_CNT;   //设定计数器值  
 WWDG->CR|=1<<7;         //开启看门狗       
 MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2      
 WWDG->SR=0X00;     //清除提前唤醒中断标志位  
 WWDG->CFR|=1<<9;          //使能提前唤醒中断  
}  
//重设置WWDG计数器的值  
void WWDG_Set_Counter(u8 cnt)  
{  
 WWDG->CR =(cnt&0x7F);//重设置7位计数器  
}  
//窗口看门狗中断服务程序  
void WWDG_IRQHandler(void)  
{       
 WWDG_Set_Counter(WWDG_CNT);//重设窗口看门狗的值!          
 WWDG->SR=0X00;//清除提前唤醒中断标志位   
} 

在实际运用中我们要根据具体情况使用这两种看门狗,独立看门狗的优点是不依赖主时钟和系统时钟,可靠性较高。窗口看门狗在时序上更严格,精度更高。

作者:大家瑟

物联沃分享整理
物联沃-IOTWORD物联网 » stm32 学习笔记(8)看门狗

发表回复