首页>>科技 >>内容

一篇文章了解STM32的独立看门狗/窗口看门狗原理

发布时间:2024-01-02 22:20:12编辑:温柔的背包来源:

很多朋友对一篇文章了解STM32的独立看门狗/窗口看门狗原理不是很了解,每日小编刚好整理了这方面的知识,今天就来带大家一探究竟。

一篇文章了解STM32的独立看门狗/窗口看门狗原理

一、独立看门狗STM32的独立看门狗是由一个特殊的内部低速时钟40Khz驱动的,即使主时钟失效仍然有效。

看门狗原理:单片机系统在外界干扰下会脱离程序运行,产生死循环。看门狗电路就是为了避免这种情况。看门狗的作用是在一定时间内(通过定时器计数器实现)没有收到喂狗信号(表示MCU已经挂断)的情况下,自动复位并重启处理器(发送复位信号)。

将0xCCCC写入键值寄存器(IWDG_KR)以开始使能独立看门狗;此时,计数器开始从其复位值0xFFF开始递减计数。当计数器计数到0x000结束时,它将产生一个复位信号(IWDG_RESET)。每当0xAAAA被写入密钥寄存器IWDG_KR时,IWDG_RLR中的值将被重新载入计数器,以避免看门狗复位。

IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先将0x5555写入IWDG_KR寄存器。向该寄存器中写入其他值会扰乱操作顺序,寄存器将再次受到保护。重载操作(即写入0xAAAA)也会激活写保护功能。

只要对上述三个寄存器进行相应的设置,我们就可以启动STM32的独立看门狗了。启动过程可以实现如下(独立看门狗相关的库函数和定义分布在文件stm32f10x_iwdg.h和stm32f10x_iwdg.c中):1)取消寄存器写保护(将0X5555写入IWDG_KR)。通过这一步,我们取消IWDG_PR和IWDG。这在库函数中的实现功能是:

IWDG _ writeaccmd(IWDG _ WriteAccess _ Enable);2)设置独立看门狗的预分频系数和重载值。设置看门狗分频系数的函数是:vodiw DG _ setprescaler(uint 8 _ tiw DG _ prescaler);//设置IWDG预分频值和设置看门狗重载值的作用是:void IWDG _ set reload(uint 16 _ tre load);//设置IWDG重载值。设置看门狗的分频系数prer和重载值,就可以知道看门狗的馈电时间(即看门狗溢出时间)。这个时间的计算方法是:

Tout=((4 2 PRER ) RLR)/40,其中Tout为看门狗溢出时间(ms);Prer是看门狗时钟的预分频值(IWDG_PR值),取值范围为0-7;Rlr是看门狗的重载值(IWDG_RLR的值);

例如,如果我们将prer值设为4,rlr值设为625,那么我们可以得到Tout=64625/40=1000ms,那么看门狗的溢出时间为1s。只要在一秒钟内对IWDG_KR写一次0XAAAA,就不会导致看门狗复位(当然也有可能写多次)。这里需要提醒的是,看门狗时钟在40Khz并不准确,喂狗时最好不要太晚,否则可能会发生看门狗复位。3)用过载计数值喂狗(将0XAAAA写入IWDG_KR)

库函数中重载计数值的作用是:IWDG _ reload counter();//根据IWDG重载寄存器的值重载IWDG计数器。传递这句话将导致STM32将IWDG_RLR的值重新载入看门狗计数器。即实现了独立看门狗的喂狗操作。4)启动看门狗(将0XCCCC写入IWDG_KR)库函数中启动独立看门狗的作用是:IWDG _ Enable();//启用IWDG

通过这句话启动STM32的看门狗。注意,IWDG一旦启用,就不能关闭!如果要关闭,只能重启,重启后不能打开IWDG,否则问题依然存在,所以在这里提醒大家,如果不使用IWDG,就不要打开,以免麻烦。/* * *初始化独立看门狗*prer:分频数:0~7(只有低3位有效!)*分频系数=4 * 2 PRER。但是最大值只能是256!*rlr:重载寄存器值:低11位有效。

*时间计算(近似):tout=((4 * 2 PRER) * RLR)/40(毫秒)。*/voidIWDG_Init(u8prer,u 16 rlr){ IWDG _ writeaccmd(IWDG _ write access _ Enable);IWDG _ SetPrescaler(prer);IWDG _ Set reload(rlr);IWDG _ reload counter();IWDG_Enable()的值重载IWDG计数器;}/* *独立馈送看门狗*/

void IWDG _ Feed(void){ IWDG _ reload counter();}/* * main函数*/void main(void){ nvic _ configuration();//优先级配置iwdg _ init(4625);//初始化独立看门狗,分频数为64,重载值为625,溢出时间计算为:64 * 625/40=1000 ms=1s while(1){ delay _ ms(500);//每0.5秒喂一次狗IWDG _ Feed();//喂狗}}

二、窗口看门狗窗口看门狗(WWDG)通常用于监控由外部干扰或不可预测的逻辑条件引起的软件故障。除非在T6位(WWDG-》CR的第六位)变为0之前刷新递减计数器的值,否则看门狗电路将在到达预设时间段时产生MCU复位。

如果在递减计数器达到窗口配置寄存器(WWDG-》CFR)的值之前,7位递减计数器值(在控制寄存器中)被刷新,也将产生MCU复位。这表明递减计数器需要在有限的时间窗口内刷新。

总结1、有一个7位向下计数器(WWDG-“Cr”),这个计数器和窗口计数器(WWDG-“CFR)决定什么时候喂狗。如果狗喂得早,重置——“早”体现在计数器值(tr)的窗口值(wr)中,即计数器值没有降低到窗口值以下;2、当0x40“计数器值(tr)”和“窗口值”(wr),这个时候最适合喂狗,也只有这样才适合喂狗;

3、当计数器的值从0x40变为0x3F时,将产生看门狗复位;当然,在复位前一段时间,如果开启了早期唤醒中断,就会进入中断。在中断函数中,我们需要及时喂狗,否则会发生复位。4、根据网上的信息,这种中断期间一般不喂狗,一般是系统死亡前的“遗嘱”,比如存储重要数据。这个需要根据个人需求来设计。

库函数中中断喂狗的方法,窗口看门狗库函数的源代码和定义分布在文件stm32f10x_wwdg.c和头文件stm32f10x _ wwdg.h中.步骤如下:1)使能WWDG时钟WWDG使用PCLK1的时钟,需要先使能PCL k1的时钟。方法是:RCC _ AP B1 periphclock cmd(RCC _ AP B1 Periph _ WWDG,使能);//WWDG时钟使能2)设置窗口值和分频数设置窗口值的函数为:Voidwwdg _ setWindowValue(uint 8 _ TwindowValue);

这个函数以一个入口参数作为窗口值,很容易理解。设置分频数的作用是:Voidwwdg _ set prescaler(uint 32 _ tww DG _ prescaler);这个函数也只有一个入口参数,就是分频值。3)打开WWDG中断和分组WWDG中断的函数是:WWDG _ enable it();//打开窗口看门狗中断接下来,配置中断优先级,用NVIC_Init()函数就可以了。4)设置计数器的初始值并启用看门狗。

这一步是通过库函数中的一个函数实现的:void wdg _ enable(uint 8 _ t counter);该功能不仅设置计数器的初始值,还启用窗口看门狗。5)最后写中断服务函数,写窗口看门狗的中断服务函数,通过这个函数快速喂狗,否则当窗口看门狗计数器值减少到0X3F时,会引起软复位。在中断服务功能中,状态寄存器的EWIF位也应清零。

完成以上五个步骤后,我们就可以使用STM32的窗口看门狗了。staticu8WWDG _ CNT=0x7f* * *初始化窗口看门狗* tr: t [6: 0],计数器值* wr: w [6: 0],窗口值*fprer:分频系数(WDGTB),只有最少2位有效* fwwdg=pclk1/(4096 * 2 fprer)。*/voidWWDG_Init(u8tr,u8wr,u 32 fprer){ RCC _ APB 1 periphclockmd(RCC _ APB 1 periph _ WWDG,使能);

WWDG _设置预缩放器(FP rer);WWDG _设置窗口值(wr);WWDG _ CNT=trWWDG _ CNT;WWDG启用(WWDG CNT)clear flag();WWDG _ NVIC _ Init();WWDG _ enable it();*/**Windows看门狗中断服务-program */void wwdg _ NVIC _ Init(void){ NVIC _ InitTypeDefNVIC _ Init structure;

NVIC _初始结构.NVIC _ IRQ channel=WWDG _ IRQnNVIC _初始结构.NVIC _ IRQChannelPreemptionPriority=2;NVIC _初始结构.NVIC _ IRQChannelSubPriority=3;NVIC初始化(NVIC初始化结构)*/**重设关于WWDGDer Wert des zhler/void wwdg _ Set _ Counter(u8 CNT){ WWDG _使能(CNT);*/* *看门狗unterbrechen Service-Prozess/void wwdg _ IRQ handler(void){ WWDG _ Set _ Counter(WWDG _ CNT);

WWDG _清除标志();le D1=~ le D1;}

以上知识分享希望能够帮助到大家!