文章归档友情连接照片地图

STM32窗口看门狗(WWDG)

分类:电子设计  作者:rming  时间:2012-07-21
STM32的另外一个看门狗,<strong>窗口看门狗。</strong>

窗口看门狗简介

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

stm32有两个看门狗,独立看门狗和窗口看门狗,其实两者的功能是类似的,只是喂狗的限制时间不同。

  • 独立看门狗是限制喂狗时间在0-x内,x由你的相关寄存器决定。喂狗的时间不能过晚。
  • 窗口看门狗,所以称之为窗口就是因为其喂狗时间是一个有上下限的范围内,你可以通过设定相关寄存器,设定其上限时间和下限时间。喂狗的时间不能过早也不能过晚。

 

T[6:0]就是WWDG_CR的低七位,W[6:0]即是WWDG->CFR的低七位。T[6:0]就是窗口看门狗的计数器,而W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。

上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于0X40,否则窗口就不存在了。

窗口看门狗的3 个寄存器

控制寄存器(WWDG_CR)

WWDG_CR只有低八位有效,T[6:0]用来存储看门狗的计数器值,随时更新的,每个 PCLK1周期(4096 ×2^wdgtb)减 1 。当该计数器的值从 0X40变为0X3F 的时候,将产生看门狗复位

WDGA位则是看门狗的激活位,该位由软件置 1,以启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了。

配置寄存器(WWDG_CFR)

EWI 是提前唤醒中断,也就是在快要产生复位的前一段时间来提醒我们,需要进行喂狗了,否则将复位!

一般用该位来设置中断,当窗口看门狗的计数器值减到0X40的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面想 WWDG_CR 重新写入计数器的值来达到喂狗的目的。

注意:这里你在进入中断后,你得在不大于113us 的时间(PCLK1为36M 的条件下)内重新写 WWDG_CR,否则,看门狗将产生复位。

状态寄存器(WWDG_SR)

该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位 0 有效,其他都是保留位。当计数器值达到 40h 时,此位由硬件置 1 。它必须通过软件写’0’来清除(中断服务程序中)。对此位写’1’无效。若中断未被使能,此位也会被置’1’。

寄存器操作步骤

1 )使能WWDG时钟

WWDG不同于IWDG ,IWDG 有自己独立的40Khz 时钟,不存在使能问题。而WWDG使用的是PCLK1的时钟,需要先使能时钟

2 )设置WWDG_CFR和WWDG_CR两个寄存器

在时钟使能完后,我们设置WWDG的CFR 和CR两个寄存器,对WWDG进行配置。包括使能窗口看门狗开启中断设置计数器的初始值设置窗口值设置分频数WDGTB等。

3 )开启WWDG中断并分组

在设置完了WWDG后,需要配置该中断的分组及使能。这点通过我们之前所编写的MY_NVIC_Init函数实现就可以了。

4 )编写中断服务函数

在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当窗口看门狗计数器值减到0X3F 的时候,就会引起软复位了。在终端服务函数里面也要将状态寄存器的EWIF 位清空

程序设计

//MAIN.C

#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdg.h"
//窗口看门狗实验
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);	//延时初始化
uart_init(72,9600); //串口初始化
led_init();	//初始化与LED连接的硬件接口
LED0=0;
delay_ms(300);
wwdg_init(0X7F,0X5F,3);//计数器值为7f,窗口寄存器为5f,分频数为8
while(1)
{
LED0=1;
}
}

//WDG.C

#include "wdg.h"
#include "led.h"
//看门狗驱动代码
//初始化独立看门狗
//prer:分频数:0~7(只有低3位有效!)
//分频银子=4*2^prer最大值为256
//rlr: 重装载寄存器值: 低11 位有效.
// 时间计算(大概):Tout=((4×2^prer) ×rlr)/40 (ms).
void iwdg_init(u8 prer,u16 rlr)
{
IWDG->KR=0X5555;//使能对IWDG->PR和IWDG->RLR的写
IWDG->PR=prer; //设置分频系数
IWDG->RLR=rlr; //从加载寄存器 IWDG->RLR
IWDG->KR=0XAAAA;//reload
IWDG->KR=0XCCCC;//使能看门狗
}
//喂独立看门狗
void iwdg_feed(void)
{
IWDG->KR=0XAAAA;//reload
}
//保存WWDG计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
//初始化窗口看门狗
//tr :T[6:0],用于存储计数器的值
//wr :W[6:0],用于存储窗口值
//fprer:窗口看门狗的实际设置
//低2位有效.Fwwdg=PCLK1/4096/2^fprer.
void wwdg_init(u8 tr,u8 wr,u8 fprer)
{
RCC->APB1ENR|=1<<11;	//使能wwdg时钟
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer
WWDG->CFR|=1<<9; //使能提前唤醒中断
WWDG->CFR&=0XFF80;
WWDG->CFR|=wr;	//设定窗口值
WWDG->CR|=WWDG_CNT|(1<<7); //开启看门狗,设置7位计数器
MY_NVIC_Init(2,3,WWDG_IRQChannel,2);//抢占2,子优先级3,组2
}
//重设置WWDG计数器的值
void wwdg_set_counter(u8 cnt)
{
WWDG->CR|=(cnt&0x7F);//重设置7位计数器
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{
u8 wr,tr;
wr=WWDG->CFR&0X7F;
tr=WWDG->CR&0X7F;
if(tr<wr)wwdg_set_counter(WWDG_CNT);//只有当计数器的值,小于窗口寄存器的值才能写CR!!
WWDG->SR=0X00;//清除提前唤醒中断标志位
LED1=!LED1;
}

//WDG.H

#ifndef __WDG_H
#define __WDG_H
#include "sys.h"
//看门狗 驱动代码
void iwdg_init(u8 prer,u16 rlr);	//初始化IWDG
void iwdg_feed(void);	//IWDG喂狗
void wwdg_init(u8 tr,u8 wr,u8 fprer);//初始化WWDG
void wwdg_set_counter(u8 cnt); //设置WWDG的计数器
#endif


提交评论