STM32学习日记(七)窗口看门狗实验

  一,窗口看门狗简介

      独立看门狗虽然方便,但时钟精度不够,如果故障在独立看门狗要复位时恢复正常,则喂狗正常执行,无法检测故障的发生。如果我们要精确检测某一时间端是否有故障产生,就需要用到窗口看门狗。

      窗口看门狗,顾名思义,看住的是窗口内的情况,要在窗口期执行喂狗操作(刷新递减计数器),提前执行或延后执行都会引起复位。

      这是窗口看门狗的工作原理图

 T[6:0]就是 WWDG_CR 的低七位,W[6:0]即是 WWDG->CFR 的低七位。T[6:0] 就是窗口看门狗的计数器,而 W[6:0]则是窗口看门狗的上窗口,由我们自己设定,下窗口值是固定的(0X40)。达到0x3F即发生复位,在达到上窗口值前不允许刷新,在上下窗口间刷新。 

窗口看门狗的超时公式如下: Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /Fpclk1;

其中: Twwdg:WWDG 超时时间(单位为 ms)

Fpclk1:APB1 的时钟频率(单位为 Khz)

WDGTB:WWDG 的预分频系数

T[5:0]:窗口看门狗的计数器低 6 位

二,寄存器介绍

首先是控制寄存器(WWDG_CR),也是计数寄存器。

该寄存器低八位有效,其余为保留位,T[6:0]用来存储看门狗的计数器值,计数器值减到0x3F时复位。WDGA 位则是看门狗的激活位,该位由软件置 1,以启动看门狗,并且一定要注意的是该 位一旦设置,就只能在硬件复位后才能清零了。

之后是配置寄存器(WWDG_CFR),

 

该寄存器有10位有效,其他位保留,W[6:0]用来保留窗口值,8,9位用来保存设置的预分频系数。

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

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

三,配置步骤

1)使能 WWDG 时钟 

与独立看门狗不同, 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)编写中断服务函数

在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗。

四,硬件设计

本实验用到的硬件资源有:

1) 指示灯 DS0 和 DS1

2) 窗口看门狗

窗口看门狗为stm32内部资源,两个指示灯前面已经多次使用。最后现象与独立看门狗相同。

五,软件设计

      窗口看门狗相较于独立看门狗只增加了固件库中的stm32f10x_wwdg.c及其头文件,以及wwdg.c和wwdg.h。

      wwdg.c代码如下

#include "led.h"
#include "wwdg.h"
u8 WWDG_CNT=0x7f;
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{ 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); 
// WWDG 时钟使能
WWDG_SetPrescaler(fprer);设置 WWDG 预分频值
WWDG_SetWindowValue(wr);//设置窗口值
WWDG_Enable(tr); //使能看门狗 , 设置 counter . 
WWDG_ClearFlag();
WWDG_NVIC_Init();//初始化窗口看门狗 NVIC
WWDG_EnableIT(); //开启窗口看门狗中断
} 
//重设置 WWDG 计数器的值
void WWDG_Set_Counter(u8 cnt)
{
 WWDG_Enable(cnt);
}
//窗口看门狗中断服务程序
void WWDG_NVIC_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占 2 子优先级 3 组 2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占 2,子优先级 3,组 2
NVIC_Init(&NVIC_InitStructure);//NVIC 初始化
}
void WWDG_IRQHandler(void)
{
// Update WWDG counter
WWDG_SetCounter(0x7F); //当禁掉此句后,窗口看门狗将产生复位
// Clear EWI flag */
WWDG_ClearFlag(); //清除提前唤醒中断标志位
// Toggle GPIO_Led pin 7 */
LED1=!LED1;
}

本函数的思路是先初始化wwdg,其中第一个参数是设置计数器初始值,第二个参数设置上窗口值,第三个参数设置预分频值。注意到这里有个全局变量 WWDG_CNT,该变量用来保存 最初设置 WWDG_CR 计数器的值。

之后的WWDG_Set_Counter 函数就是把CNT中储存的数值放到计数器上。

最后在中断服务函数里面,先重设窗口看门狗的计数器值,然后清除提前唤醒中断标志。 最后对 LED1(DS1)取反,来监测中断服务函数的执行状况。

之后是主函数main.c
 

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

本函数用DS0指示是否正在初始化,用DS1指示是否发生复位,每次复位DS1会变化亮灭。我们先让 LED0 亮 300ms,然后关闭以用于判断是否有复位发生了。在初始化 WWDG 之后, 我们回到死循环,关闭 LED0,并等待看门狗中断的触发/复位。

检查无误后下载验证,现象为DS0亮一下后熄灭,之后DS1不断闪烁。
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值