基于STM32F103ZET6实现看门狗(独立与窗口)

STM32开发板自带独立(IWDG)与窗口(WWDG)看门狗
1(独立看门狗):实现按键喂狗,LED来指示复位状态!
2(窗口看门狗):使用看门狗中断喂狗,LDE指示状态!

1(独立看门狗)

独立看门狗有内部专门的低速时钟提供时钟驱动,大概40KHz,范围大概在30~60KHz范围内,单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示 MCU 已经挂了),便实现处理器的自动复位重启(发送复位信号)。
IWDG_KR 写入 0X5555可以使能写权限,否则无法修改寄存器值分频值重装载值,具体操作为:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
设置独立看门狗的预分频系数重装载值可通过这两个函数写入:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//预分频
void IWDG_SetReload(uint16_t Reload);//重装载值
独立看门狗的溢出时间我们可以通过这个公式计算:
T=((4×2^Prescaler) ×Reload) /40
便捷:定时1s,Prescaler值:4,Reload值:625
解释:也就是说,在1s内喂狗,就可以实现不复位!

注意:

这里需要提醒大家的是,看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。

重载计数值喂狗(向 IWDG_KR 寄存器写入 0XAAAA)
IWDG_ReloadCounter()
大家可能会混淆两个概念!
设定重装载值:设定一个值作为重装载值的大小
重载计数值喂狗:让STM32开发板中的重装载值重新写到计数器中,从而实现计数器值更新,达到喂狗目的!
启动看门狗(向 IWDG_KR 写入 0XCCCC):
IWDG_Enable();
如果不用独立看门狗的话,就不要去打开它,免得麻烦。
独立看门狗头文件iwdg.h
#ifndef IWDG_H
#define IWDG_H
void iwdg_init(void);
void feed_dog(void);
#endif
独立看门狗源文件iwdg.c
#include “iwdg.h”
#include “sys.h”
void iwdg_init(void)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(4);
IWDG_SetReload(625);
IWDG_ReloadCounter();
IWDG_Enable();
}
void feed_dog(void)
{
IWDG_ReloadCounter();
}
独立看门狗主函数源文件main.c
#include “led.h”
#include “delay.h”
#include “key.h”
#include “sys.h”
#include “iwdg.h”
int main(void)
{
delay_init();
KEY_Init();
LED_Init();
iwdg_init();
delay_ms(500);
LED0=0;
while(1)
{
if(KEY_Scan(0)==KEY0_PRES)
{
feed_dog();
}
delay_ms(10);
}
}
都比较简单就不赘述了!
实验现象:只要按键及时喂狗,led将保持常亮!

2(窗口看门狗)

窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。比独立看门狗更加精准!
我们以图在说明该配置哪些:
在这里插入图片描述
所谓窗口看门狗,就是有个窗口一样的上下限,我们必须在上下线值之间进行喂狗才不会导致复位!
图中T[6:0]就是 WWDG_CR寄存器 的低七位,W[6:0]即是 寄存器WWDG->CFR 的低七位。T[6:0]就是窗口看门狗的计数器,而 W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。
其中W[6:0]是可以用户自行定义的。但是一定要确保窗口值大于 0X40,否则窗口就不存在了。
超时的最大时间计算公式为:
Twwdg=(4096×2^预分频数×(T[5:0]+1))/APB1时钟频率;
例子:如果说我们的APB1时钟为36M,可以通过预分频数得知超时时间:
在这里插入图片描述
复位的两种情况:
(1)当窗口看门狗的计数器在上窗口值之外被刷新。
(2)低于下窗口值会产生复位。
那么如何设置值呢?
控制寄存器
在这里插入图片描述
低八位有效,0-6控制T6值,当值从 0X40 变 为 0X3F 的时候,将产生看门狗复位。第八位是控制看门狗的激活位。
配置寄存器:
在这里插入图片描述
低十位有效,第十位为提前唤醒中断标志位,注意这里在进入中断后,必 须在不大于 1 个窗口看门狗计数周期的时间(在 APB1频率为 36M 且 预分频为 0 的条件下,该时间为 113us)内重新写控制寄存器,否则,看门狗将产生复位!W6用户写入数据位。
状态寄存器
该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位 0 有效,其他都是保留位。当计数器值达到 40h 时,此位由硬件置 1。它必须通过软件写 0 来清除。对此位写 1 无效。即使中断未被使能,在计数器的值达到 0X40的时候,此位也会被置 1。
重要的三个寄存器配置项就只有这些
(1)使能 WWDG 时钟
窗口看门狗使用的是PCLOCK1内部时钟,所以需要使能时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
(2)设置窗口值和分频数
窗口值设置:void WWDG_SetWindowValue(uint8_t WindowValue);
分频数设置:void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
(3)开启 WWDG 中断并分组
开启WWDG_EnableIT();中断从初始化NVIC_Init();
(4)设置计数器初始值并使能看门狗
**void WWDG_Enable(uint8_t Counter);**这个函数及设置了计数器初值,又完成了看门狗使能
(5)中断服务函数
**void WWDG_IRQHandler(void);**不可更改函数名
窗口看门狗头文件wwdg.h
#ifndef WWDG_H
#define WWDG_H
#include “sys.h”
extern void wwdg_init(u32,u8,u8);
#endif
窗口看门狗源文件wwdg.c
#include “wwdg.h”
#include “sys.h”
#include “led.h”
void wwdg_init(u32 prer,u8 value,u8 in)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
WWDG_SetPrescaler( prer);
WWDG_SetWindowValue(value);
WWDG_Enable(in);
WWDG_ClearFlag();
WWDG_EnableIT();
}
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7F);
WWDG_ClearFlag();
LED1=!LED1;
}
窗口看门狗主函数main.c
#include “led.h”
#include “delay.h”
#include “sys.h”
#include “wwdg.h”
int main(void)
{
delay_init();
LED_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED0=0;
delay_ms(300);
wwdg_init(WWDG_Prescaler_8,0x5F,0x7F);
while(1)
{
LED0=1;
}
}

总结

本章主要是熟悉配置流程,有些细节问题就是初始化函数的配置顺序,主函数的开门狗初始化应该是在哪个位置都是我们需要考虑的,为什么会出现这样的顺序,这些问题想明白了,以后自己写程序的时候便得心应手!
小编第一次写的时候出现了初始化地方不合适,导致实验结果千差万别,一直没找到原因。
只有努力与实践共存,才能进步!希望这篇文章对大家有所帮助!

发布了6 篇原创文章 · 获赞 9 · 访问量 3119

猜你喜欢

转载自blog.csdn.net/weixin_42271802/article/details/104500551