1.看门狗简介
1.1 看门狗
stm32芯片内部有2个看门狗外设,分别为独立看门狗(IWDG)和窗口看门狗(WWDG),用于检测并解决软件错误导致的故障。
1.2 IWDG
IWDG:12位递减计数器。如果计数器从某个值递减到0时,系统会产生一次复位。如果在计数器递减到0之前刷新了计数器(喂狗),就不会产生复位。
1.3 WWDG
WWDG:7位递减计数器。当计数器减到一个固定值0X40时还不喂狗,会产生一个MCU复位,称为窗口的下限。同时,用户可以设置一个上限值(窗口的上限),当计数器减到上限值之前时也会产生复位。只有在上窗口和下窗口之间时,才能刷新(喂狗)。
2.看门狗配置
2.1 IWDG配置
(1)添加头文件:stm32f10x_iwdg.c 和 stm32f10x_iwdg.h
(2)开启寄存器访问(给 IWDG_KR 寄存器写入 0X5555)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
(3)设置 IWDG 预分频系数和重装载值
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
void IWDG_SetReload(uint16_t Reload); Tout = (4*2^pre) / 40 * rlr
(4)重载计数器值(喂狗)(给 IWDG_KR 寄存器写入 0XAAAA)
IWDG_ReloadCounter();
(5)开启 IWDG(给 IWDG_KR 寄存器写入 0XCCCC) IWDG_Enable();
2.2 WWDG配置
(1)添加头文件:stm32f10x_wwdg.c 和 stm32f10x_wwdg.h
(2)使能 WWDG 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
(3)设置 WWDG 窗口值、分频数
void WWDG_SetWindowValue(uint8_t WindowValue);
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
(4)开启 WWDG 中断并分组
WWDG_ClearFlag();
WWDG_EnableIT();
(5)设置计数器初始值并使能WWDG
void WWDG_Enable(uint8_t Counter);
void WWDG_SetCounter(uint8_t Counter); //喂狗函数
(6)编写 WWDG 中断服务函数
WWDG_IRQHandler
3.硬件设计
4.软件设计
4.1 功能描述
4.1.1 IWDG功能描述
4.2.1 WWDG功能描述
本章所要实现的功能是:系统开启时 DS0 指示灯点亮 500ms 时间,然后熄灭。 DS1 指示灯不断闪烁表示正在喂狗。如果喂狗超时将重启系统,DS0 指示灯点亮 500ms,然后熄灭,继续喂狗。
4.2 软件实现
4.2.1 IWDG软件实现
(1)初始化IWDG
#include "IWDG.h"
// -----------------------------1.IWDG初始化-------------------------------------
/* ---------------------------------函数声明-------------------------------------
*函数名称:void IWDG_Iint(u8 pre, u16 rlr)
*输入参数:u8 pre, u16 rlr
*返回参数:无
*功 能:IWDG初始化
*作 者:lph
*日 期:2024/03/28
------------------------------------------------------------------------------ */
void IWDG_Iint(u8 pre, u16 rlr)
{
//(1)开启寄存器访问(给 IWDG_KR 寄存器写入 0X5555)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//(2)设置 IWDG 预分频系数和重装载值:Tout = (4*2^pre) / 40 * rlr
IWDG_SetPrescaler(pre);
IWDG_SetReload(rlr);
//(3)重载计数器值(喂狗)(给 IWDG_KR 寄存器写入 0XAAAA)
IWDG_ReloadCounter();
//(4)开启 IWDG(给 IWDG_KR 寄存器写入 0XCCCC)
IWDG_Enable();
}
/* ---------------------------------函数声明-------------------------------------
*函数名称:void IWDG_FeedDog(void)
*输入参数:无
*返回参数:无
*功 能:IWDG喂狗
*作 者:lph
*日 期:2024/03/28
------------------------------------------------------------------------------ */
void IWDG_FeedDog(void)
{
IWDG_ReloadCounter();
}
(2)主函数
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "system.h"
#include "LED.h"
#include "KEY.h"
#include "SysTick.h"
#include "USART.h"
#include "IWDG.h"
/* 主函数main() --------------------------------------------------------------*/
int main()
{
// 自定义变量
u8 i=0;
// 初始化
SysTick_Iint(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断分组
LED_Init();
KEY_Iint();
USART1_Iint(115200);
IWDG_Iint(4, 800); //1280ms
LED1 = 1;
printf("系统复位\r\n");
while(1)
{
if(KEY_Scan(0)==KEY_UP_PRESS)
{
IWDG_FeedDog();
LED0 = 0;
printf("喂狗\r\n");
}
i++;
if(i%50==0)
{
LED1 = !LED1;
}
delay_ms(10);
}
}
4.2.2 WWDG软件实现
(1)初始化WWDG
#include "WWDG.h"
void WWDG_Iint(void)
{
//(2)使能 WWDG 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
//(3)设置 WWDG 窗口值、分频数
WWDG_SetWindowValue(0x5F); //用户设置上窗口值
WWDG_SetPrescaler(WWDG_Prescaler_8);
//(4)开启 WWDG 中断并分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
//(5)设置计数器初始值并使能WWDG
WWDG_Enable(0x7f);
WWDG_ClearFlag();
WWDG_EnableIT();
}
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7f);
WWDG_ClearFlag();
LED1 = !LED1;
}
(2)主函数
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "system.h"
#include "LED.h"
#include "SysTick.h"
#include "USART.h"
#include "WWDG.h"
/* 主函数main() --------------------------------------------------------------*/
int main()
{
// 自定义变量
// 初始化
SysTick_Iint(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断分组
USART1_Iint(115200);
LED0 = 0;
delay_ms(500);
LED0 = 1;
WWDG_Iint();
while(1)
{
}
}