cortex_m3_stm32嵌入式学习笔记(六):窗口看门狗实验(WWDG)

ARM 200浏览

窗口看门狗( WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障

简单来说,和IWDG的区别就是IWDG要靠手动去喂狗,而WWDG有内置中断,所以可以利用设置中断服务函数去喂狗

首先还是设置WWDG (记得往工程里面添加头文件)大致设置步骤如下:

1)使能 WWDG 时钟(系统内部时钟)

2)设置窗口值和分频数

3)开启 WWDG 中断并分组

4) 设置计数器初始值并使能看门狗

5) 编写中断服务函数

wwdg.c


#include "led.h" #include "wwdg.h" //保存 WWDG 计数器的设置值,默认为最大. u8 WWDG_CNT=0x7f; void WWDG_Init(u8 tr,u8 wr,u32 fprer) { 	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); 	WWDG_SetPrescaler(fprer);////设置 IWDG 预分频值         WWDG_SetWindowValue(wr);//设置窗口值 	WWDG_Enable(tr); //使能看门狗 , 设置 counter . 	WWDG_ClearFlag(); 	WWDG_NVIC_Init();//初始化窗口看门狗 NVIC         WWDG_EnableIT(); //开启窗口看门狗中断 } void WWDG_NVIC_Init(void) { 	NVIC_InitTypeDef NVIC_ist; 	NVIC_ist.NVIC_IRQChannel=WWDG_IRQn; 	NVIC_ist.NVIC_IRQChannelPreemptionPriority=2; 	NVIC_ist.NVIC_IRQChannelSubPriority=3; 	NVIC_ist.NVIC_IRQChannelCmd=ENABLE; 	NVIC_Init(&NVIC_ist); } void WWDG_IRQHandler(void) { 	WWDG_SetCounter(0x7f);//喂狗 	WWDG_ClearFlag();//清除提前唤醒标志 	LED1=!LED1;//检测中断函数是否工作了 } 

wwdg.h

#ifndef _WWDG_H #define _WWDG_H #include "sys.h" void WWDG_Init(u8 tr,u8 wr,u32 fprer); void WWDG_NVIC_Init(void); void WWDG_IRQHandler(void); #endif

其中有一个地方一开始写错了。。WWDG_Init()的第三个参数 写成了u8 ..结果灯闪的超级快,后来找了一会才找到这错了。。估计参数穿进去溢出了

主函数

#include "led.h" #include "sys.h" #include "delay.h" #include "wwdg.h" #include "usart.h" void init(void) { 	delay_init(); 	uart_init(9600); 	LED_Init(); 	NVIC_Configuration(); 	LED0=0; 	delay_ms(300); 	WWDG_Init(0x7f,0x5f,WWDG_Prescaler_8); } int main(void) { 	init(); 	while(1) 	{ 		LED0=1; 	} 	 }

主函数就是实现让LED0先亮一下,然后WWDG就会工作(不让程序复位),然后中断函数就会工作,具体现象是LED1一直闪,一开始不明白中断是如何触发的,回头翻了一下手册,书上是这样说的:窗口看门狗的第二个寄存器是配置寄存器( WWDG_CFR),该位中的 EWI 是提前唤醒中断,也就是在快要产生复位的前一段时间( T[6:0]=0X40) 来提醒我们,需要进行喂狗了,否则将复位!因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。

简单来讲(只是个人愚见)就是WWDG是一个递减的计数器,从最大值递减到0,到0的时候如果没喂狗(就是重置计数器,比如说将它重置为最大值)就会复位,但中断触发是在中途进行的,就是当递减到0x40的时候就会触发中断,这时候会转到我们写的中断服务函数里面去,只要我们在中断服务函数里面写喂狗函数就可以一直喂狗了