WWDG---窗口看门狗

一.简介

窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,必须在一个窗口的上限值(用户定义)和**下限值(0X40,固定不能变)**之间喂狗不会复位,在上限值之前和下限值之后喂狗都会复位。

RLR 是重装载寄存器,用来设置独立看门狗的计数器的值;

TR 是窗口看门狗的计数器的值,由用户独立设置;

WR 是窗口看门狗的上窗口值,由用户独立设置。

二.功能框图

1.窗口看门狗时钟

窗口看门狗时钟来自 PCLK1,PCLK1 最大是 36M,由 RCC 时钟控制器开启。

2.计数器时钟

CNT_CK(计数器的时钟)=PCLK1/4096/(2^WDGTB);

CK 计时器时钟=PCLK1/4096;

分频系数 = (2^WDGTB);

计数器减一个数的时间 T= 1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB)

3.计数器

窗口看门狗的计数器是一个7 位递减计数器。

当递减计数器递减到 0X40 的时候,还不会马上产生复位,如果使能了提前唤醒中断:CFR 位 9EWI 置 1,则产生提前唤醒中断,如果真进入了这个中断的话,就说明程序肯定是出问题了,那么在中断服务程序里面我们就需要做最重要的工作,比如保存重要数据,或者报警等,这个中断我们也叫它死前中断。

4.窗口值(上限值)

配置寄存器CFR 的位 6:0 W[6:0] 设置。

0X7F>上限值>oX40

如果我们要监控的程序段 A 运行的时间为 x,当执行完这段程序之后就要进行喂狗,如果在窗口时间内没有喂狗的话,那程序就肯定是出问题了。一般计数器的值 TR 设置成最大 0X7F,窗口值为 WR,计数器减一个数的时间为 T,那么时间:(TR-WR)*T 应该稍微小于 x 即可,这样就能做到刚执行完程序段 A 之后喂狗,起到监控的作用,这样也就可以算出 WR 的值是多少。

5.超时时间

三.使用案例

**WWDG 一般被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。**比如一个程序段正常运行的时间是 50ms,在运行完这个段程序之后紧接着进行喂狗,如果在规定的时间窗口内还没有喂狗,那就说明我们监控的程序出故障了,跑飞了,那么就会产生系统复位,让程序重新运行。

四.实验

systick.c

cpp 复制代码
#include "systick.h"


// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)

void Delay_Us(uint32_t us)
{
	uint32_t i;
	SysTick_Config(SystemCoreClock/1000000);
	
	for(i=0;i<us;i++)
	{
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1	
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

void Delay_Ms( uint32_t ms)
{
	uint32_t i;	
	SysTick_Config(SystemCoreClock/1000);
	
	for(i=0;i<ms;i++)
	{
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
		// 当置1时,读取该位会清0
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

systick.h

cpp 复制代码
#ifndef	_SYSTICK_H
#define _SYSTICK_H

#include "stm32f10x.h"

void Delay_Us(uint32_t us);
void Delay_Ms(uint32_t ms);

#endif

wwdg.c

cpp 复制代码
#include "wwdg.h"

// WWDG 中断优先级初始化
static void WWDG_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure; 
  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 
  NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/* WWDG 配置函数
 * tr :递减计时器的值, 取值范围为:0x7f~0x40
 * wr :窗口值,取值范围为:0x7f~0x40
 * prv:预分频器值,取值可以是
 *      @arg WWDG_Prescaler_1: WWDG counter clock = (PCLK1(36MHZ)/4096)/1
 *      @arg WWDG_Prescaler_2: WWDG counter clock = (PCLK1(36mhz)/4096)/2
 *      @arg WWDG_Prescaler_4: WWDG counter clock = (PCLK1(36mhz)/4096)/4
 *      @arg WWDG_Prescaler_8: WWDG counter clock = (PCLK1(36mhz)/4096)/8
 */
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
{	
	// 开启 WWDG 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	
	// 设置递减计数器的值
	WWDG_SetCounter(tr);
	
	// 设置预分频器的值
	WWDG_SetPrescaler(prv);
	
	// 设置上窗口值
	WWDG_SetWindowValue(wr);
	
	// 设置计数器的值,使能WWDG
	WWDG_Enable(WWDG_CNT);	
	
	// 清除提前唤醒中断标志位
	WWDG_ClearFlag();	
	// 配置WWDG中断优先级
	WWDG_NVIC_Config();	
	// 开WWDG 中断
	WWDG_EnableIT();
}

// 喂狗
void WWDG_Feed(void)
{
	// 喂狗,刷新递减计数器的值,设置成最大WDG_CNT=0X7F
	WWDG_SetCounter( WWDG_CNT );
}

wwdg.h

cpp 复制代码
#ifndef __BSP_WWDG_H
#define	__BSP_WWDG_H


#include "stm32f10x.h"
// 窗口计数器值,范围为:0x40~0x7f,一般设置成最大0X7F
#define WWDG_CNT	0X7F


void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv);
void WWDG_Feed(void);

#endif 

systick.h

cpp 复制代码
/**
  ******************************************************************************
  * @file    Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c 
  * @author  MCD Application Team
  * @version V3.6.0
  * @date    20-September-2021
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and 
  *          peripherals interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2011 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "led.h"

/** @addtogroup STM32F10x_StdPeriph_Template
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M3 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
  * @brief  This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Memory Manage exception.
  * @param  None
  * @retval None
  */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Bus Fault exception.
  * @param  None
  * @retval None
  */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Usage Fault exception.
  * @param  None
  * @retval None
  */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
void SVC_Handler(void)
{
}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
void PendSV_Handler(void)
{
}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
}

// WWDG 中断复服务程序,如果发生了此中断,表示程序已经出现了故障,
// 这是一个死前中断。在此中断服务程序中应该干最重要的事,
// 比如保存重要的数据等,这个时间具体有多长,要
// 由WDGTB的值决定:
// WDGTB:0   113us
// WDGTB:1   227us
// WDGTB:2   455us
// WDGTB:3   910us
void WWDG_IRQHandler(void)
{
	// 清除中断标志位
	WWDG_ClearFlag();
	
	//LED2亮,点亮LED只是示意性的操作,
	//真正使用的时候,这里应该是做最重要的事情
	LED0(1);
}


/******************************************************************************/
/*                 STM32F10x Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f10x_xx.s).                                            */
/******************************************************************************/

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
/*void PPP_IRQHandler(void)
{
}*/

/**
  * @}
  */ 

main.c

cpp 复制代码
#include "stm32f10x.h"
#include "led.h"
#include "systick.h"
#include "wwdg.h"
#include "key.h"

int main()
{
	uint8_t wwdg_tr, wwdg_wr; 
	
	led_gpio_init();
	
	LED1(1);
	Delay_Ms(1000);
	
// 初始化WWDG:配置计数器初始值,配置上窗口值,启动WWDG,使能提前唤醒中断
	WWDG_Config(0X7F, 0X5F, WWDG_Prescaler_8);
	
	// 窗口值我们在初始化的时候设置成0X5F,这个值不会改变
	wwdg_wr = WWDG->CFR & 0X7F;

	while(1)
	{	
		LED1(0);
		//-----------------------------------------------------
		// 这部分应该写需要被WWDG监控的程序,这段程序运行的时间
		// 决定了窗口值应该设置成多大。
		//-----------------------------------------------------
		
		// 计时器值,初始化成最大0X7F,当开启WWDG时候,这个值会不断减小
		// 当计数器的值大于窗口值时喂狗的话,会复位,当计数器减少到0X40
		// 还没有喂狗的话就非常非常危险了,计数器再减一次到了0X3F时就复位
		// 所以要当计数器的值在窗口值和0X40之间的时候喂狗,其中0X40是固定的。
		wwdg_tr = WWDG->CR & 0X7F;
		
		if( wwdg_tr < wwdg_wr )
		{
			// 喂狗,重新设置计数器的值为最大0X7F
			WWDG_Feed();
		}
	}
}
相关推荐
云伴枫轻舞4 分钟前
我对 OTA 的理解随记,附GD32/STM32例程
stm32·单片机·嵌入式硬件
Aczone2844 分钟前
硬件(五) 存储、ARM 架构与指令系统
arm开发·嵌入式硬件·架构
LS·Cui1 小时前
单片机按键示例功能
单片机
【ql君】qlexcel1 小时前
MCU上电到运行的全过程
单片机·嵌入式硬件·mcu·启动过程
搞一搞汽车电子2 小时前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
pQAQqa2 小时前
FreeRTOS项目(2)摇杆按键检测
stm32·单片机·嵌入式硬件·freertos
小莞尔3 小时前
【51单片机】【protues仿真】基于51单片机停车场的车位管理系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
一川月白7094 小时前
51单片机---硬件学习(跑马灯、数码管、外部中断、按键、蜂鸣器)
单片机·学习·51单片机·外部中断·蜂鸣器·数码管·跑马灯
月阳羊5 小时前
【硬件-笔试面试题-69】硬件/电子工程师,笔试面试题(知识点:电机驱动电路的反馈电路)
java·经验分享·嵌入式硬件·面试
weixin_468466857 小时前
树莓派32位与64位系统安装teamviewer远程软件
linux·单片机·自动化·树莓派·远程控制·vnc·teamviewer