首页 > 技术文章 > STM32之窗口看门狗

nwjlq 2020-06-05 08:49 原文

简介:

跟独立看门狗一样,也是用来检测软件可能出现的错误,不一样的是,当独立看门狗计数器的值减到0时会产生复位,在减到0之前喂狗防止复位。

窗口看门狗:在某一值到0x40之间喂狗才不会产生复位,其他情况均会产生复位信号,这个某一个值称之为窗口上限。

计数器数值由看门狗控制寄存器决定

可以看出计数器占7位,最大值为0x7f

功能框图:

1.PCLK1默认为36MHz

2.PCLK1经过分频器分频生成CNT_CK给计数器提供时钟

从图中可以看出CNT_CK=PCLK1/4096/(2^WDGTB)

3.计数器,见最上面第1 2张图,当计数器最高位T6由1变为0时,产生复位

4.设置窗口上限值,见配置寄存器,窗口上限值不得大于计数器最大值,不得小于窗口下限值

 超时时间计算:超时时间指计数器值减到窗口下限下一个数值即0x3f所花时间

最短超时时间在计数器的值为0x40的时候,最长超时时间在计数器值为0x7f的时候

当WDGTB为0时,CNT_CK=36M/4096/1=8789.0625Hz    计数器减一次所花时间为 1/8789.0625(s)  最短超时时间=(0x40-0x3f)*/8789.0625 约等于113us

                                                                                                                                                              最长超时时间=(0x7f-0x3f)/8789.0625  约等于7.28ms

相关函数:

上面中的中断函数使能是当计数器从0x40减到0x3f时产生的,这个中断称为死前中断。

实验:

设置计数器值和窗口上限值都为0x7f

配置死前中断,在中断中喂狗,并且LED2反转

main函数中,LED1一直点亮

原理图:

看门狗头文件和源文件:

#ifndef _WWDG_H
#define _WWDG_H
#include "stm32f10x.h"

void WWDG_Config(void);

#endif
#include "wwdg.h"
static void LED1_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStruct);
    GPIO_SetBits(GPIOC,GPIO_Pin_1);//默认熄灭
}
//中断优先级配置
static void WWDG_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStruct.NVIC_IRQChannel=WWDG_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}
void WWDG_Config(void)
{
    WWDG_NVIC_Config();
    LED1_GPIO_Config();
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);//开启看门狗时钟
    WWDG_SetPrescaler(WWDG_Prescaler_8);//设置分频系数
    WWDG_SetWindowValue(0x7f);//设置窗口上限值 
    WWDG_SetCounter(0x7f);//设置计数器值
    WWDG_EnableIT();//使能中断
    WWDG_Enable(0x7f);//开启看门狗
    
}

void WWDG_IRQHandler(void)
{
    WWDG_ClearFlag();
    WWDG_SetCounter(0x7f);//设置计数器值
    //LED2反转
    if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_1)==SET)
        GPIO_ResetBits(GPIOC,GPIO_Pin_1);
    else
        GPIO_SetBits(GPIOC,GPIO_Pin_1);//默认熄灭
}

 

mian文件:

#include "stm32f10x.h"
#include "wwdg.h"
static void LED0_GPIO_Config(void);
int main(void)
{
    LED0_GPIO_Config();
    WWDG_Config();
    
    while(1);
}

static void LED0_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStruct);
    GPIO_ResetBits(GPIOC,GPIO_Pin_0);//默认点亮
}

 

推荐阅读