STM32 WWDG窗口看门狗

发布于: 2018年05月15日 21:40:56 | 分类: STM32 | 浏览: 182

STM32 窗口看门狗简介

    窗口看门狗(WWDG)通常被用来监测由外部干扰不可预见的逻辑条件造成的应用程序正常的运行序列而产生的软件故障。除非递减计数器的值在WWDG->CR 的第六位变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU 复位。在递减计数达到窗口配置寄存器(WWDG->CFR)数值之前,如果 7 位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个 MCU 复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。

    STM32有两个看门狗,一个是独立看门狗(IWDG)之前写过《STM32 IWDG独立看门狗》,另一个是窗口看门狗(WWDG)。我们知道独立看门狗的工作原理就是一个键值寄存器(IWDG_KR)低16位寄存器。软件必须每隔一定时间写入0xAAAA,否则,当计数器减到0时,程序会自动复位。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值 0X40 时还不喂狗的话,就会产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。

CNT

    上窗口值(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 位

窗口看门狗的超时公式

    现在假设FPCLK1 = 36 MHZ,那么就可以得到最小到最大超时时间表如下:

WDGTB最小超时时间最大超时时间
0113微7.28毫秒
1227微秒14.56毫秒
2455微29.12毫秒
3910微秒58.25毫秒

窗口看门狗3个重要的寄存器

    WWDG的第一个寄存器是控制寄存器(WWDG_CR)

WWDG_CR

    它只有低八位有效, T[6: 0]用来存储看门狗的计数器值,随时更新的,每个窗口看门狗计数周期(4096×2^ WDGTB)减 1。当该计数器的值从 0X40 变为 0X3F 的时候,将产生看门狗复位。WDGA 位则是看门狗的激活位,该位由软件置 1,以启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了 。

    WWDG的第二个寄存器是配置寄存器(WWDG_CFR)

    WWDG_CFR中的 EWI 是提前唤醒中断,也就是在快要产生复位的前一段时间(T[6:0]=0X40) 来提醒我们,需要进行喂狗了,否则将复位!因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR重新写入计数器的值,来达到喂狗的目的。注意这里在进入中断后, 必须在不大于1个窗口看门狗计数周期的时间(在 PCLK1 频率为 36M WDGTB 0的条件下,该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产生复位

    WWDG的最后一个寄存器是状态寄存器(WWDG_SR)该寄存器是用来记录当前是否有唤醒的标志。该寄存器仅有第0(从0开始计算)有效,其他都是保留位,当计数器值达到0x40时,此位由硬件置1。它必须通过软件写0来清除。对此位写1无效。 即使中断未被使能, 在计数器的值达到0X40的时候, 此位也会被置 1。

    在介绍完了窗口看门狗的寄存器之后,我们介绍要如何启用STM32的窗口看门狗。 这里我们介绍库函数中用中断的方式来喂狗的方法,WWDG库函数相关源码和定义分布在源文件stm32f10x_wwdg.c文件和头文件 stm32f10x_wwdg.h

1)使能 WWDG 时钟
2)设置窗口值和分频数

3)开启 WWDG 中断并分组

4)设置计数器初始值并使能看门狗
5)编写中断服务函数 

一般步骤

硬件设计

    指示灯 DS0DS1,通过 DS0 DS1 来指示 STM32 的复位情况和窗口看门狗的喂狗情况。

软件设计

wwdg.h

#ifndef __WDG_H
#define __WDG_H

#include <stm32f10x.h>

void WWDG_Init(u8 tr,u8 wr,u32 fprer);//初始化WWDG
void WWDG_Set_Counter(u8 cnt);       //设置WWDG的计数器
void WWDG_NVIC_Init(void);                

#endif

wwdg.c

#include "wwdg.h"

#include <misc.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_wwdg.h>
#include "../led/led.h"

u8 WWDG_CNT = 0x7f;

void WWDG_Init(u8 tr, u8 wr, u32 fprer) {

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //   WWDG时钟使能

	WWDG_SetPrescaler(fprer);  //设置IWDG预分频值
	WWDG_SetWindowValue(wr);  //设置窗口值
	WWDG_Enable(tr);	 //使能看门狗 ,	设置 counter .
	WWDG_ClearFlag();
	WWDG_NVIC_Init();	 //初始化窗口看门狗 NVIC
	WWDG_EnableIT(); //开启窗口看门狗中断
}

//窗口看门狗中断服务程序
void WWDG_NVIC_Init() {

	NVIC_InitTypeDef NVIC_InitTypeDef;

	NVIC_InitTypeDef.NVIC_IRQChannel 						= WWDG_IRQn;    //WWDG中断
	NVIC_InitTypeDef.NVIC_IRQChannelPreemptionPriority 		= 2;   			//抢占2,子优先级3,组2
	NVIC_InitTypeDef.NVIC_IRQChannelSubPriority 			= 3;	 		//抢占2,子优先级3,组2
	NVIC_InitTypeDef.NVIC_IRQChannelCmd 					= ENABLE;

	NVIC_Init(&NVIC_InitTypeDef);	 										//NVIC初始化

}

void WWDG_IRQHandler(void) {
	WWDG_SetCounter(0x7F);	  //当禁掉此句后,窗口看门狗将产生复位
	WWDG_ClearFlag();	  //清除提前唤醒中断标志位
	LED1=!LED1;
}

main.c

#include <misc.h>
#include <stm32f10x_wwdg.h>

#include "delay/delay.h"
#include "led/led.h"
#include "wwdg/wwdg.h"

int main(int argc, char **argv) {

	delay_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断优先级分组2
	LED_Init();
	LED0 = 0;
	WWDG_Init(0X7F, 0X5F, WWDG_Prescaler_8);
	while (1) {
		LED0 = !LED0;
		delay_ms(1000);
	}
}

效果

    系统上电后LED0每隔1000ms闪烁一次,LED1会在喂狗时闪烁。


标签: 编程 C STM32 大学
本文为作者原创文章,转载时请务必声明出处并添加指向此页面的链接。
分享:
发表评论

目前您尚未登录,请 登录 后进行评论

评论信息