第十二章 窗口门狗(WWDG)实验
[mw_shl_code=c,true]1.硬件平台:正点原子探索者STM32F407开发板
2.软件平台:MDK5.1
3.固件库版本:V1.4.0
[/mw_shl_code]
这一章,我们将向大家介绍如何使用
STM32F4的另外一个看门狗,窗口看门狗(以下简称
WWDG)。在本章中,我们将使用窗口看门狗的中断功能来喂狗,通过
DS0和
DS1提示程序的运行状态。本章分为如下几个部分:
12.1 STM32F4窗口看门狗简介
12.2 硬件设计
12.3 软件设计
12.4 下载验证
12.1 STM32F4窗口看门狗简介
窗口看门狗(
WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在
T6位(
WWDG->CR的第六位)变成
0前被刷新,看门狗电路在达到预置的时间周期时,会产生一个
MCU复位。在递减计数器达到窗口配置寄存器
(WWDG->CFR)数值之前,如果
7位的递减计数器数值
(在控制寄存器中
)被刷新,
那么也将产生一个
MCU复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。他们的关系可以用图
12.1.1来说明:
图
12.1.1 窗口看门狗工作示意图
图
12.1.1中,
T[6:0]就是
WWDG_CR的低七位,
W[6:0]即是
WWDG->CFR的低七位。
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位
根据上面的公式,假设
Fpclk1=42Mhz,那么可以得到最小
-最大超时时间表如表
12.1.1所示:
表
12.1.1 42M时钟下窗口看门狗的最小最大超时表
接下来,我们介绍窗口看门狗的
3个寄存器。首先介绍控制寄存器(
WWDG_CR),该寄存器的各位描述如图
12.1.2所示:
图
12.1.2 WWDG_CR寄存器各位描述
可以看出,这里我们的
WWDG_CR只有低八位有效,
T[6:
0]用来存储看门狗的计数器值,随时更新的,每个窗口看门狗计数周期(4096×
2^ WDGTB)减
1。当该计数器的值从
0X40变为
0X3F的时候,将产生看门狗复位。
WDGA位则是看门狗的激活位,该位由软件置
1,以启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了。
窗口看门狗的第二个寄存器是配置寄存器(
WWDG_CFR),该寄存器的各位及其描述如图
12.1.3所示:
图
12.1.3 WWDG_ CFR寄存器各位描述
该位中的
EWI是提前唤醒中断,也就是在快要产生复位的前一段时间(
T[6:0]=0X40)来提醒我们,需要进行喂狗了,否则将复位!因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到
0X40的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向
WWDG_CR重新写入计数器的值,来达到喂狗的目的。注意这里在进入中断后,必须在不大于
1个窗口看门狗计数周期的时间(在
PCLK1频率为
42M且
WDGTB为
0的条件下,该时间为
97.52us)内重新写
WWDG_CR,否则,看门狗将产生复位!
最后我们要介绍的是状态寄存器(
WWDG_SR),该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位
0有效,其他都是保留位。当计数器值达到
40h时,此位由硬件置
1。它必须通过软件写
0来清除。对此位写
1无效。即使中断未被使能,在计数器的值达到
0X40的时候,此位也会被置
1。
在介绍完了窗口看门狗的寄存器之后,我们介绍要如何启用
STM32F4的窗口看门狗。这里我们介绍库函数中用中断的方式来喂狗的方法,窗口看门狗库函数相关源码和定义分布在文件
stm32f4xx_wwdg.c文件和头文件
stm32f4xx_wwdg.h中。步骤如下:
1)使能WWDG时钟
WWDG不同于
IWDG,
IWDG有自己独立的
32Khz时钟,不存在使能问题。而
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);
该函数既设置了计数器初始值,同时使能了窗口看门狗。
这里还需要说明一下,库函数还提供了一个独立的设置计数器值的函数为:
void WWDG_SetCounter(uint8_t Counter);
5)编写中断服务函数
在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当窗口看门狗计数器值减到
0X3F的时候,就会引起软复位了。在中断服务函数里面也要将状态寄存器的
EWIF位清空。
完成了以上
4个步骤之后,我们就可以使用
STM32F4的窗口看门狗了。这一章的实验,我们将通过
DS0来指示
STM32F4是否被复位了,如果被复位了就会点亮
300ms。
DS1用来指示中断喂狗,每次中断喂狗翻转一次。
12.2 硬件设计
本实验用到的硬件资源有:
1) 指示灯
DS0和
DS1
2) 窗口看门狗
其中指示灯前面介绍过了,窗口看门狗属于
STM32F4的内部资源,只需要软件设置好即可正常工作。我们通过
DS0和
DS1来指示
STM32F4的复位情况和窗口看门狗的喂狗情况。
12.3 软件设计
打开我们的窗口看门狗实验可以看到,我们增加了窗口看门狗相关的库函数支持文件
stm32f4xx_wwdg.c和
stm32f4xx_wwdg.h,同时新建
wwdg.c和对应的头文件
wwdg.h用来编写窗口看门狗相关的函数代码。
接下来我们看看
wwdg.c文件内容:
u8 WWDG_CNT=0X7F;
//初始化窗口看门狗
//tr :T[6:0],计数器值
wr
:W[6:0],窗口值
//fprer:分频系数(
WDGTB)
,仅最低
2位有效
//Fwwdg=PCLK1/(4096*2^fprer). 一般
PCLK1=42Mhz
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
NVIC_InitTypeDef
NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//使能窗口看门狗时钟
WWDG_CNT=tr&WWDG_CNT; //初始化
WWDG_CNT.
WWDG_SetPrescaler(fprer);
//设置分频值
WWDG_SetWindowValue(wr);
//设置窗口值
WWDG_SetCounter(WWDG_CNT);//设置计数值
WWDG_Enable(WWDG_CNT); //开启看门狗
NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn; //窗口看门狗中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
//抢占优先级为
2
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //响应优先级为
3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能窗口看门狗
NVIC_Init(&NVIC_InitStructure);
WWDG_ClearFlag();//清除提前唤醒中断标志位
WWDG_EnableIT();//开启提前唤醒中断
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{
WWDG_SetCounter
(WWDG_CNT); //重设窗口看门狗值
WWDG_ClearFlag();//清除提前唤醒中断标志位
LED1=!LED1;
}
wwdg.c文件一共包含两个函数。第一个函数
void WWDG_Init(u8 tr,
u8 wr,
u8 fprer)用来设置
WWDG的初始化值。包括看门狗计数器的值和看门狗比较值等。该函数就是按照我们上面
5个步骤的思路设计出来的代码。注意到这里有个全局变量
WWDG_CNT,该变量用来保存最初设置
WWDG_CR计数器的值。在后续的中断服务函数里面,就又通过
WWDG_SetCounter函数把该数值放回到
WWDG_CR上。
最后在中断服务函数里面,先重设窗口看门狗的计数器值,然后清除提前唤醒中断标志。最后对
LED1(
DS1)取反,来监测中断服务函数的执行状况。
wwdg.h头文件内容比较简单,这里我们就不做过多讲解。
在完成了以上部分之后,我们就回到主函数,代码如下:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组
2
delay_init(168);
//初始化延时函数
LED_Init(); //初始化
LED端口
KEY_Init();
//初始化按键
LED0=0;
//点亮
LED0
delay_ms(300);
WWDG_Init(0x7F,0X5F,WWDG_Prescaler_8);
//计数器值为
7f,窗口寄存器为
5f,分频数为
8
while(1)
{
LED0=1; //熄灭
LED灯
}
}
该函数通过
LED0(DS0)来指示是否正在初始化。而
LED1(DS1)用来指示是否发生了中断。我们先让
LED0亮
300ms,然后关闭以用于判断是否有复位发生了。在初始化
WWDG之后,我们回到死循环,关闭
LED1,并等待看门狗中断的触发
/复位。
在编译完成之后,我们就可以下载这个程序到探索者
STM32F4开发板上,看看结果是不是和我们设计的一样。
12.4 下载验证
将代码下载到探索者
STM32F4后,可以看到
DS0亮一下之后熄灭,紧接着
DS1开始不停的闪烁。每秒钟闪烁
20次左右,和我们预期的一致,说明我们的实验是成功的。
实验详细手册和源码下载地址:http://www.openedv.com/posts/list/41586.htm
正点原子探索者STM32F407开发板购买地址:http://item.taobao.com/item.htm?id=41855882779
一周热门 更多>