本篇文章将讲述窗口看门狗实验,小白总结,如有错误,请大神指教。
目录
一、窗口看门狗的简介
窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在 T6 位(WWDG->CR 的第六位)变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU 复位。在递减计数器达到窗口配置寄存器(WWDG->CFR)数值之前,如果 7 位的递减计数器数值(在控制寄存器中)被刷新,那么也将产生一个 MCU 复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。
T[6:0]就是窗口看门狗的计数器,而 W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于 0X40,否则窗口就不存在了。
窗口看门狗的超时公式如下:
Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /Fpclk1;
其中:
Twwdg:WWDG 超时时间(单位为 ms)
Fpclk1:APB1 的时钟频率(单位为 Khz)
WDGTB:WWDG 的预分频系数
T[5:0]:窗口看门狗的计数器低 6 位
根据上边的公式,就能算出此表中的最大/最小超时值
二、写窗口看门狗的思路
1)使能 WWDG 时钟
WWDG 不同于 IWDG,IWDG 有自己独立的 40Khz 时钟,不存在使能问题。而 WWDG
使用的是 PCLK1 的时钟,需要先使能时钟。方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
2)设置窗口值和分频数
设置窗口值的函数是:
void WWDG_SetWindowValue(uint8_t WindowValue);
这个函数就一个入口参数为窗口值,很容易理解。
设置分频数的函数是:
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
这个函数同样只有一个入口参数就是分频值。
3)开启 WWDG 中断并分组
开启 WWDG 中断的函数为:
WWDG_EnableIT(); //开启窗口看门狗中断
接下来是进行中断优先级配置,这里就不重复了,使用 NVIC_Init()函数即可。
4)设置计数器初始值并使能看门狗
这一步在库函数里面是通过一个函数实现的:
void WWDG_Enable(uint8_t Counter);
该函数既设置了计数器初始值,同时使能了窗口看门狗。
5)编写中断服务函数
在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当
窗口看门狗计数器值减到 0X3F 的时候,就会引起软复位了。在中断服务函数里面也要将状态
寄存器的 EWIF 位清空。
完成了以上 5 个步骤之后,我们就可以使用 STM32 的窗口看门狗了。这一章的实验,我
们将通过 DS0 来指示 STM32 是否被复位了,如果被复位了就会点亮 300ms。DS1 用来指示中
断喂狗,每次中断喂狗翻转一次。
三、独立看门狗实验
工程文件如下:
tect.c文件如下:
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "wdg.h"
int main(void)
{
Stm32_Clock_Init(9);
delay_init(72);
uart_init(72,9600);
LED_Init();
KEY_Init();
delay_ms(300);
IWDG_Init(4,625);
LED0=0;
while(1)
{
if(KEY_Scan(0)==WKUP_PRES)IWDG_Feed();
delay_ms(10);
};
}
wdg.c文件如下:
#include "wdg.h"
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG->KR=0X5555;
IWDG->PR=prer;
IWDG->RLR=rlr;
IWDG->KR=0XAAAA;
IWDG->KR=0XCCCC;
}
void IWDG_Feed(void)
{
IWDG->KR=0XAAAA;
}
led.c文件如下:
#include "sys.h"
#include "led.h"
void LED_Init(void)
{
RCC->APB2ENR|=1<<2;
RCC->APB2ENR|=1<<5;
GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;
GPIOA->ODR|=1<<8;
GPIOD->CRL&=0XFFFFF0FF;
GPIOD->CRL|=0X00000300;
GPIOD->ODR|=1<<2;
}
key.c的文件如下:
#include "key.h"
#include "delay.h"
void KEY_Init(void)
{
RCC->APB2ENR|=1<<2;
RCC->APB2ENR|=1<<4;
JTAG_Set(SWD_ENABLE);
GPIOA->CRL&=0XFFFFFFF0;
GPIOA->CRL|=0X00000008;
GPIOA->CRH&=0X0FFFFFFF;
GPIOA->CRH|=0X80000000;
GPIOA->ODR|=1<<15;
GPIOC->CRL&=0XFF0FFFFF;
GPIOC->CRL|=0X00800000;
GPIOC->ODR|=1<<5;
}
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;
if(mode)key_up=1;
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10);
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(WK_UP==1)return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;
return 0;
}
还有什么问题,欢迎随时联系我