本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发
目录
WDG简介
IWDG
IWDG特性
独立看门狗时钟
键寄存器
超时时间
IWDG代码
WWDG
WWDG特性
窗口看门狗时钟
超时时间
WWDG时序
WWDG代码
IWDG和WWDG对比
WDG简介
WDG(Watchdog)看门狗 ,可以监控程序的运行状态。
当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性
看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号
STM32内置两个看门狗
独立看门狗(IWDG):独立工作,对时间精度要求较低 。IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合
窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用。WWDG最适合那些要求看门狗在精确计时窗口起作用的应用程序
IWDG
IWDG特性
● 自由运行的递减计数器
● 时钟由独立的RC振荡器提供(可在停止和待机模式下工作)
● 看门狗被激活后,则在计数器计数至0x000时产生复位
独立看门狗时钟
独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效
如果独立看门狗已经由硬件选项或软件启动,LSI振荡器将被强制在打开状态,并且不能被关闭。在LSI振荡器稳定后,时钟供应给IWDG。
键寄存器
键寄存器本质上是控制寄存器,用于控制硬件电路的工作 在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率
写入键寄存器的值 | 作用 |
0xCCCC | 启用独立看门狗 |
0xAAAA | IWDG_RLR中的值重新加载到计数器(喂狗) |
0x5555 | 解除IWDG_PR和IWDG_RLR的写保护 |
0x5555之外的其他值 | 启用IWDG_PR和IWDG_RLR的写保护 |
//通过写入键寄存器
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能或者失能对寄存器 IWDG_PR 和 IWDG_RLR 的写操作
IWDG_ReloadCounter(); //重装计数器,喂狗
IWDG_Enable(); //独立看门狗使能
超时时间
超时时间:TIWDG = TLSI × PR预分频系数 × (RL + 1)
其中:TLSI = 1 / FLSI
注: 这些时间是按照40kHz时钟给出。实际上,MCU内部的RC频率会在30kHz到60kHz之间变化。 此外,即使RC振荡器的频率是精确的,确切的时序仍然依赖于APB接口时钟与RC振荡器时钟之间的相位差,因此总会有一个完整的RC周期是不确定的。
IWDG代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"int main(void)
{OLED_Init();OLED_ShowString(1, 1, "IWDG TEST");/*判断复位信号来源*/if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)//如果是独立看门狗复位{OLED_ShowString(2, 1, "IWDGRST");Delay_ms(500);OLED_ShowString(2, 1, " ");Delay_ms(100);RCC_ClearFlag();//清除标志位}else{OLED_ShowString(3, 1, "RST");Delay_ms(500);OLED_ShowString(3, 1, " ");Delay_ms(100);} /*IWDG初始化*/IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //独立看门狗写使能IWDG_SetPrescaler(IWDG_Prescaler_16); //设置预分频为16IWDG_SetReload(2499); //设置重装值为2499,独立看门狗的超时时间为1000msIWDG_ReloadCounter(); //重装计数器,喂狗IWDG_Enable(); //独立看门狗使能while (1){IWDG_ReloadCounter(); //重装计数器,喂狗OLED_ShowString(4, 1, "FEED");//喂狗间隔为200+600=800msDelay_ms(200);OLED_ShowString(4, 1, " ");Delay_ms(600);}
}
WWDG
WWDG特性
● 可编程的自由运行递减计数器
递减计数器处于自由运行状态,即使看门狗被禁止,递减计数器仍继续递减计数。当看门狗被启用时,T6位必须被设置,以防止立即产生一个复位
● 条件复位 ─ 当递减计数器的值小于0x40,(若看门狗被启动)则产生复位。 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。
● 如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以被用于重装载计数器以避免WWDG复位。
启动看门狗在系统复位后,看门狗总是处于关闭状态,设置WWDG_CR寄存器的WDGA位能够开启看门狗,随后它不能再被关闭,除非发生复位
窗口看门狗时钟
窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。
超时时间
超时时间:TWWDG = TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] + 1)
窗口时间:TWIN = TPCLK1 × 4096 × WDGTB预分频系数 × (T[5:0] - W[5:0])
其中:TPCLK1 = 1 / FPCLK1
WWDG时序
递减计数器T[6:0]的值小于0x40时,WWDG产生复位
递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位
递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位
WWDG代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"int main(void)
{ OLED_Init(); OLED_ShowString(1, 1, "WWDG TEST");/*判断复位信号来源*/if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) //如果是窗口看门狗复位{OLED_ShowString(2, 1, "WWDGRST"); //OLED闪烁WWDGRST字符串Delay_ms(500);OLED_ShowString(2, 1, " ");Delay_ms(100);RCC_ClearFlag(); //清除标志位}else //否则,即为其他复位{OLED_ShowString(3, 1, "RST"); //OLED闪烁RST字符串Delay_ms(500);OLED_ShowString(3, 1, " ");Delay_ms(100);}/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //开启WWDG的时钟/*WWDG初始化*/WWDG_SetPrescaler(WWDG_Prescaler_8); //设置预分频为8WWDG_SetWindowValue(0x40 | 21); //设置窗口值,窗口时间为30msWWDG_Enable(0x40 | 54); //使能并第一次喂狗,超时时间为50mswhile (1){OLED_ShowString(4, 1, "FEED"); //OLED闪烁FEED字符串Delay_ms(20); //喂狗间隔为20+20=40msOLED_ShowString(4, 1, " ");Delay_ms(20);WWDG_SetCounter(0x40 | 54); //重装计数器,喂狗}
}