独立看门狗

来源:互联网 发布:算法导论15章思考题 编辑:程序博客网 时间:2024/04/30 19:44

一,看门狗简介

由于单片机会受到来自外界电磁场的干扰,造成程序跑飞使系统陷入死循环,造成不可预知的后果
于是有了用于检测单片机程序运行状态的模块或芯片,叫做”看门狗”(watchdog)

看门狗作用:检测系统,当系统跑飞时复位系统,重新执行程序


二,STM32看门狗

STM32有两个看门狗:独立看门狗和窗口看门狗

独立看门狗:

 驱动:由LSI驱动,即使主时钟发生故障它仍有效 适用场景:      作为主程序之外能够完全独立工作      对时间精度要求较低

窗口看门狗:

 驱动:由APB1时钟分频后得到时钟驱动 适用场景:      在精确计时窗口起作用的程序

三,独立看门狗原理

启动:键值寄存器IWDG_KR写入0xCCCC开始启用独立看门狗过程:计时器从重装载值(由寄存器IWDG_RLR配置,默认0xFFF)开始递减,当递减到0x000时产生复位信号IWDG_RESET喂狗:键值寄存器IWDG_KR写入0xAAAA,重装载寄存器IWDG_RLR的值会重新加载到递减计数器,避免看门狗复位复位:如果程序异常跑飞,不能完成喂狗,系统复位

这里写图片描述

如图:    独立看门狗时钟LSI通过预分频(IWDG_PR)    向减值寄存器IWDG_KR写入0xCCCC,开启独立看门狗,此时重装载值写入递减计数器    在任何时间向IWDG_KR写入0xAAAA完成喂狗,重装载寄存器IWDG_RLR的值会重新加载到递减计数器,避免看门狗复位    如果在0xFFF递减到0x000前未完成喂狗,系统复位

四,独立看门狗相关寄存器

键值寄存器IWDG_KR: 0~15位有效

这里写图片描述

写入0x5555取消IWDG_PR和IWDG_RLR写保护写入0xCCCC开启独立看门狗写入0xAAAA喂狗

预分频寄存器IWDG_PR:0~2位有效。具有写保护功能,要操作先取消写保护

这里写图片描述

重装载寄存器IWDG_RLR:0~11位有效。具有写保护功能,要操作先取消写保护。

这里写图片描述

0-11位[11:0]有效,[12:31]位保留 默认值,最大值为0xFFF当IWDG_KR写入0xAAAA是,重装载值会被传送到计数器中IWDG_SR寄存器RVU位为0时才能对IWDG_RLR寄存器进行修改

状态寄存器IWDG_SR:0~1位有效

这里写图片描述


五,独立看门狗超时时间

这里写图片描述

看门狗时钟源 : 由LSI经过IWDG_PR分频提供     LSI时钟频率=40MHz     IWDG_PR预分频系数 P = 4 * 2^prer     所以看门狗时钟频率 = 40/PIWDG_RLR计数器重装载值,每经过一个看门狗时钟周期-1看门狗时钟周期 = P/40看门狗移除时间:     Tout = ((4 * 2^prer) * RLR) / 40最短时间 : 一个看门狗时钟周期  即IWDG_RLR=0x001最长时间 : IWDG_RLR寄存器最大值(0xFFF) * 看门狗时钟周期

六,独立看门狗相关库函数

void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess); // 取消写保护:0x5555使能void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);    // 设置预分频系数:写PRvoid IWDG_SetReload(uint16_t Reload);          // 设置重装载值:写RLRvoid IWDG_ReloadCounter(void);              // 喂狗:写0xAAAA到KRvoid IWDG_Enable(void);                  // 使能看门狗写0xCCCC到KRFlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);  // 状态:重装载/预分频 更新

七,独立看门狗操作步骤

//取消寄存器写保护:    IWDG_WriteAccessCmd();//设置独立看门狗的预分频系数,确定时钟:    IWDG_SetPrescaler();//设置看门狗重装载值,确定溢出时间:    IWDG_SetReload();//使能看门狗    IWDG_Enable();//应用程序喂狗:    IWDG_ReloadCounter();//溢出时间计算:    Tout=((4×2^prer)×rlr) /40

八,独立看门狗代码:

功能:        独立看门狗设置1秒溢出,按下WK_UP按键喂狗        如果不喂狗可以看到每1秒程序重启一次        现象LED0闪烁,因为每次启动程序有500毫秒延时        若连续快速按下WK_UP,使看门狗不进入溢出,LED0常亮

HAEDWARE/IWDG下新建Iwdg.h头文件

#ifndef __WDG_H#define __WDG_H#include “sys.h” //因为使用了u8 u16/** * 看门狗初始化 *     prer     预分频系数 *     rlr      重装载值 */void IWDG_Init(u8 prer,u16 rlr);void IWDG_Feed(void);  // 喂狗#endif

头文件添加到项目配置
这里写图片描述

HAEDWARE/IWDG下新建Iwdg.c实现函数

在stm32f10x_iwdg.h中找到:

/** @defgroup IWDG_Exported_Functions  * @{  */void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);     // 取消写保护void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);          // 设置预分频系数void IWDG_SetReload(uint16_t Reload);                    // 设置重装载值void IWDG_ReloadCounter(void);                           // 喂狗void IWDG_Enable(void);                                  // 使能独立看门狗FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);       // 获取状态
#include "wdg.h"//看门狗初始化void IWDG_Init(u8 prer,u16 rlr){    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  // 取消IWDG_PR WDG_RLR写保护    IWDG_SetPrescaler(prer);  // 设置预分频系数    IWDG_SetReload(rlr);      // 设置重装载值    IWDG_ReloadCounter();     // 喂狗-使第一次从重装载值开始计数,默认首次0xFFF    IWDG_Enable();            // 使能看门狗}// 喂狗void IWDG_Feed(void){     IWDG_ReloadCounter();    // reload}

USER/main.编写主函数

#include "led.h"         // LED#include "delay.h"       // 延时函数#include "key.h"         // 按键#include "sys.h"#include "usart.h"#include "wdg.h"         // 独立看门狗 int main(void) {    delay_init();        // 延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // NVIC中断优先级分组    uart_init(115200);   // 设置USART波特率115200    LED_Init();          // LED端口初始化 - 默认LED0熄灭    KEY_Init();          // 按键端口初始化    delay_ms(500);       // 延时500ms - 复位时LED闪烁    IWDG_Init(4, 625);   // 独立看门狗初始化-设置溢出时间1S-预分频系数4,重装载值625    LED0=0;              // LED0点亮    while(1)    {        if(KEY_Scan(0)==WKUP_PRES) // 按下按键WK_UP        {            IWDG_Feed(); // 喂狗        }        delay_ms(10);    };}

以上代码实现:    独立看门狗设置1秒溢出,按下WK_UP按键喂狗    如果不喂狗可以看到每1秒程序重启一次    现象LED0闪烁,因为每次启动程序有500毫秒延时    若连续快速按下WK_UP,使看门狗不进入溢出,LED0常亮
0 0