一、独立看门狗IWDG
1、简介
1、IWDG:即看门狗
2、本质:能产生系统复位信号的计数器。
3、特性:递减的计数器
时钟由独立的RC振荡器提供(可在待机和停止模式下运行)
看门狗被激活后,当递减计数器计数到0x000时产生复位
4、喂狗:在计数器计数到0之前,重装计数器的值,防止复位
2、作用
独立看门狗是异常处理的最后手段,不可依赖,应在设计时尽可能避免异常发生。
3、IWDG工作原理
时钟源(Src CLK)到PSC预分频器 再得到真正的工作时钟(IWDG CLK),经过CNT递减计数器的递减,判断CNT是否为0,为0则复位,在递减过程中会进行喂狗,即RELOAD重装载寄存器使CNT= RELOAD。
4、IWDG寄存器
低16位有效,通过键值来实现不同的功能,当键值为0xAAAA表示喂狗;当键值为0x5555表示允许访问预分频器寄存器IWDG_PR和IWDG_RLR重装载寄存器;当键值为0x5555表示启动看门狗工作;也即是上述这三个功能。
以上使寄存器编写用到的,如果用HAL直接一个函数就可以了
5、IWDG溢出时间计算
6、IWDG配置步骤
7、编程实战:验证不及时喂狗,系统将复位重启
1、先复制正点原子的串口实验文件夹,进入在D:\1野火嵌入式\正点原子看门狗\实验5 串口实验\Drivers\BSP 路径新建WDG文件夹,在其下面新建俩个文件:wdg.c和wdg.h文件
2、打开工程,还需要在工程上添加如下图文件:
1、首先打开wdg.c文件,编写以下代码,运行之后导入wdg.h文件
#include "./BSP/WDG/wdg.h"
2、在wdg.c文件编写iwdg_init初始化函数和iwdg_feed喂狗函数。
#include "./BSP/WDG/wdg.h"
IWDG_HandleTypeDef g_iwdg_handle; //句柄
/*IWDG初始化函数*/
/* uint8_t和uint16_t是为了节约内存空间,也可以都设置为32位 */
/* prer:分频系数,rlr:重装载值 */
void iwdg_init(uint8_t prer, uint16_t rlr){
//基地址
g_iwdg_handle.Instance = IWDG;
//Init里有俩个参数,一个是分频系数,另一个是重装载值
g_iwdg_handle.Init.Prescaler = prer;
g_iwdg_handle.Init.Reload = rlr;
HAL_IWDG_Init(&g_iwdg_handle);
}
/*喂狗函数*/
void iwdg_feed(void){
HAL_IWDG_Refresh(&g_iwdg_handle);
}
3、在wdg.h文件进行声明
#ifndef _WDG_H
#define _WDG_H
#include "./SYSTEM/sys/sys.h"
void iwdg_init(uint8_t prer, uint16_t rlr);
void iwdg_feed(void);
#endif /*_WDG_H*/
4、在main.c文件进行实验测试看门狗,首先系统初始化-----串口打印------初始化IWDG的溢出时间大约为1s------进入循环判断是否在1s内喂狗,喂狗则打印已经喂狗,否则系统复位。
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/WDG/wdg.h"
int main(void)
{
/*系统初始化*/
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟为72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
// led_init();
printf("您还没喂狗,请及时喂狗!!!\r\n");
/* 预分频系数为32,重装载值为1250,溢出时间约为1s */
iwdg_init(IWDG_PRESCALER_32,1250);
while (1)
{
delay_ms(1000);
iwdg_feed();
printf("已经喂狗!!!\r\n");
}
}
/*
*溢出时间是1秒,F1,根据那张图
*1、先选分频系数,根据最长时间大于1秒来选择(本次选择IWDG_PRESCALER_32)
*2、计算重装载值,根据公式计算(Tout=1s,psc就是上面选的32,fIWDG时钟频率为40000即40kHz)
* 计算结果为1250
*/
8、总结
二、WWDG窗口看门狗
1、简介
1、全称:WWDG,即窗口看门狗
2、本质:能产生系统复位信号和提前唤醒中断的计数器
3、特性:递减的计数器
当递减计数器值从 0x40减到0x3F时复位(即T6位跳变到0)
计数器的值大 于W[6:0]值(窗口上限值)时喂狗会复位
提前唤醒中断(EWI):当递减计数器等于 0x40 时可产生
4、喂狗:在窗口期内重装载计数器的值,防止复位
2、作用
1、作用:用于监测单片机程序运行时效是否精准,主要检测软件异常
2、应用:需要精准监测程序运行时间的场合
3、WWDG工作原理
注意:窗口上限值必须大于下限值
4096分频系数是固定的
WDGA:激活位
写WWDG_CR:喂狗
这个图很好分析,对比了上面的内容,太棒了,学会了
4、寄存器
5、WWDG超时时间计算
6、WWDG配置步骤
最重要介绍的时1和6
7、编程实战:验证窗口看门狗功能
1、同独立看门狗一样,不过这次选择流水灯工程进行复制,然后步骤一样
2、首先打开wdg.c文件,编写以下代码,运行之后导入wdg.h文件
#include "./BSP/WDG/wdg.h"
3、在wdg.c文件编写:步骤1、2、3、4、5
#include "./BSP/WDG/wdg.h"
#include "./BSP/LED/led.h"
WWDG_HandleTypeDef g_wwdg_handle;
/* 窗口看门狗初始化函数 */
void wwdg_init(uint8_t tr,uint8_t wr,uint32_t fprer){
/* 下面时初始化结构体 */
/* 寄存器基地址 */
g_wwdg_handle.Instance = WWDG;
/* 结构体成员Init */
//计数器值
g_wwdg_handle.Init.Counter = tr;
//窗口值
g_wwdg_handle.Init.Window = wr;
//预分频系数
g_wwdg_handle.Init.Prescaler = fprer;
//是否产生 提前唤醒中断使能
g_wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;
HAL_WWDG_Init(&g_wwdg_handle);
}
/* WWDG MSP回调函数 */
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg){
/* 设置CLOCK时钟 */
//在stm32f1xx_hal_wwdg.c下的stm32f1xx_hal_rcc.h的文件的408行
__HAL_RCC_WWDG_CLK_ENABLE();
/* 下面是配置NVIC */
/* 设置优先级 */
HAL_NVIC_SetPriority(WWDG_IRQn, 2 , 3);
/* 使能中断请求 形参WWDG_IRQn是中断号*/
HAL_NVIC_EnableIRQ( WWDG_IRQn);
}
/* WWDG中端服务函数 */
//在startup_stm32f103xe.s中找,78行
void WWDG_IRQHandler(void){
HAL_WWDG_IRQHandler(&g_wwdg_handle);
}
/* WWDG提前唤醒回调函数 进行重定义*/
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg){
//也可以在这里喂狗
HAL_WWDG_Refresh(&g_wwdg_handle);
/* 反转一下LED灯 , 在led.h 的55行*/
LED1_TOGGLE();
}
4、在wdg.h文件声明初始化函数
#ifndef _WDG_H
#define _WDG_H
#include "./SYSTEM/sys/sys.h"
extern WWDG_HandleTypeDef g_wwdg_handle;
void wwdg_init(uint8_t tr,uint8_t wr,uint32_t fprer);
#endif /*_WDG_H*/
5、在main.c编写验证窗口看门狗功能
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/WDG/wdg.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟,72M */
delay_init(72); /* 初始化延时函数 */
//串口的初始化函数,用串口打印一些数据
usart_init(115200); /* 串口初始化为波特率115200 */
led_init(); /* 初始化LED */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET ){
printf("窗口看门狗复位!!!\r\n");
__HAL_RCC_CLEAR_RESET_FLAGS();
}
else{
printf("外部复位!!!\r\n");
}
delay_ms(500);
printf("请在窗口期喂狗\r\n\r\n");
/* 1、窗口看门狗初始化 */
/* 计数器值:0x7F 窗口值:0x5F 预分频系数:WWDG_PRESCALER_8 */
wwdg_init(0x7F , 0x5F ,WWDG_PRESCALER_8);
while(1)
{
delay_ms(29);
/*喂狗函数,在stm32fxx_hal_wwdg.c 文件的343行*/
//HAL_WWDG_Refresh(&g_wwdg_handle);
}
}