目录
1. 独立看门狗是什么
2. 独立看门狗 IWDG简介
3. 独立看门狗的主要特性
4. 独立看门狗功能
4.1 独立看门狗功能框图
4.2 IWDG寄存器
4.2.1 关键字寄存器 IWDG_KR
4.2.2 预分频器寄存器 IWDG_PR
4.2.3 重载寄存器 IWDG_RLR
4.2.4 状态寄存器 IWDG_SR
5. 库函数配置独立看门狗
6. 相关实验程序
6.1 main.c
6.2 iwdg.c
6.3 iwdg.h
在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界的电磁波干扰,造成程序的跑飞,从而陷入到死循环,程序的正常运行被打断,由单片机控制的系统无法继续正常工作,会造成整个系统陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”。
STM32板载了两种嵌入式看门狗外设,具有安全性高、定时精准及使用灵活的优点。看门狗分为独立看门狗和窗户看门狗。均可用于检测并解决由于软件错误导致的故障。本章我们着重讲解独立看门狗。
看门狗的作用就是在一定的时间内 (这段时间通过定时器去实现) ,如果超过这段时间还没有被喂养信号(表示MCU已经挂了),便启动处理器的自动复位重启(发送复位信号)。
独立看门狗由其专用的低速内部时钟LSI驱动,通过对时钟的学习,我们知道LSI低速内部时钟是专门用来驱动看门狗的,独立看门狗由内部专门的32Khz低速时钟驱动,即使主时钟发生故障,它也仍然有效。独立看门狗的时钟是一个内部RC时钟,所以并不是准确的32Khz,而是一个在15~47Khz之间的可变化的时钟。
独立看门狗最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。
硬件看门狗:如果通过器件选项位使能 “硬件看门狗” 功能,上电时将自动使能看门狗;如果在计数器计数结束前,若软件没有向关键字寄存器写入相应的值,则系统会产生复位。
1. 自由运行的递减计数器 用于给定一段确定的时间,如果程序运行超过这段时间,表明MCU已经挂了
2. 时钟由独立RC振荡器提供(可在待机和停止模式下运行) 低速内部时钟LSI,主时钟发生故障时,LSI 仍然保持工作状态
3. 当递减计数器达到0x000时产生复位(前提是看门狗已激活) 递减定时器递减到0时,复位为初始值,循环工作
关键字寄存器 IWDG_KR(Key register)32位寄存器
位31:16 保留,必须保持复位值
位15:0 KEY[15:0]:键值,只写位,读为0000h;
必须每隔一段时间便通过软件对这些位写入键值AAAAh,否则当计数器计数到0时,看门狗会产生复位。
写入键值5555h可使能对IWDG_PR和IWDG_RLR寄存器的访问。
写入键值CCCCh可启动看门狗 该寄存器的15:0位再一次强调了上述框图中的情况
在关键字寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要关键字寄存器IWDG_KR中被写入0xAAAA, IWDG_RLR中的值就会被重新加载到计数器中从而避免产生看门狗复位 。
预分频器寄存器 IWDG_PR(Prescaler register) 32位寄存器
位31:3 保留,必须保持复位值
位2:0 PR[2:0]:预分频器
这些值受写访问保护。通过软件设置这些位来选择计数器时钟的预分频因子。若要更改预分频的分频系数,IWDG_SR的PVU位必须为0;
000:4分频 001:8分频 010:16分频 011:32分频 100:64分频 101:128分频 110:256分频 111:256分频
注意:读取该寄存器会返回VDD电压域的预分频值。如果正在对该寄存器执行写操作,则读取的值可能不是最新的/有效的。因此,只有在IWDG_SR寄存器中的PVU位为0时,从寄存器中读取的值才有效。
重载寄存器 IWDG_RLR(Reload register)32位寄存器
位32:12 保留,必须保持复位值
位11:0 RL[11:0]:看门狗计数器重载值
这些值受写访问保护,每次对IWDG_KR寄存器写入值AAAAh时,这个值就会重装载到看门狗计数器中,之后便会从重装载以后的值开始递减计数。若要更改重装载值,IWDG_SR中的RVU位必须为0;该寄存器用来保存重装载到计数器中的值。
状态寄存器 IWDG_SR(Status register)32位寄存器
位31:2 保留,必须保持复位值
位1 RVU:看门狗计数器重装载更新
可通过硬件将该位置1以指示重装载值正在更新。当在VDD电压域下完成重装载更新操作后,会通过硬件将该位复位。
重载值只有在RVU位为0时才可更新。
位0 PVU:看门狗预分频器值更新
可通过硬件将该位置1以指示预分频器值正在更新。当在VDD电压域下完成预分频器值更新操作后,会通过硬件将该位复位。
重载值只有在PVU位为0时才可更新。
库函数配置独立看门狗的步骤:
1. 取消寄存器写保护(向IWDG_KR写入0x5555)
取消写保护的实质其实是取消IWDG_PR和IWDG_RLR的写保护;首先取消写保护的目的是为了后续可以设置IWDG_PR和IWDG_RLR寄存器的值。
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
2. 设置独立看门狗的预分频系数和重装载值
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//设置IWDG的预分频值
void IWDG_SetReload(uint16_t Reload); //设置IWDG重装载值
通过对以上两个寄存器设置可以计算出看门狗的喂狗时间(也就是看门狗溢出时间):
Tout=((4*2^prer)*rlr)/32
Tout:看门狗溢出时间 prer:预分频值 0~7 rlr:重装载值
单位ms 4*2^prer=称为分频因子最大值256 分母=看门狗时钟(并不固定)
具体来说就是:比如通过计算得到看门狗的溢出时间是1000ms,也就是1s,只要你在1s之内,有一次写入0xAAAA到IWDG_KR,就不会导致看门狗复位。
3. 重载计数器喂狗(向IWDG_KR写入0xAAAA)
IWDG_ReloadCounter(); //重载计数器的值到IWDG计数器中,避免其复位 这一步骤就是看门狗喂狗
4. 启动看门狗(向IWDG_KR写入0xCCCC)
IWDG_Enable(); //使能IWDG
注意:IWDG一旦启动,就不能再关闭,想要关闭,只能重启;一般不使用IWDG,就不要启动看门狗;启动看门狗以后必须间隔一段时间去喂狗,否则就会导致程序复位。
该程序将会实现:
LED0常量,如果KEY_UP按下,就进行独立看门狗喂狗,只要看门狗不停的按,看门狗就不会产生复位,保持LED0常量,一旦超过了看门狗的溢出时间还没按,就会导致程序重启,LED熄灭一次。
#include "stm32f4xx.h"
#include "delay.h"
#include "LED.h"
#include "BEEP.h"
#include "Key.h"
#include "usart.h"
#include "exti.h"
#include "iwdg.h"
int main()
{
LED_Init();//初始化LED
delay_init(168);//初始化延迟函数
Key_Init();//初始化按键
delay_ms(500);//延迟500ms 保证肉眼可以看到灯的亮灭,因为LED初始化是置高电平的,默认不亮
IWDG_Init(4,500);//初始化看门狗喂狗 (4*2^4)*500/32=1000ms=1s 设置看门狗的溢出时间为1秒
LED0=0;//LED0点亮
while(1)
{
if(KEY_UP==1)//如果KEY_UP按键按下
{
IWDG_FEED();//喂狗
}
delay_ms(10);//延迟10ms
}
}
#include "stm32f4xx.h"
#include "iwdg.h"
//prer:预分频值
//rlr:自动重装载值
void IWDG_Init(unsigned char prer,unsigned int rlr)//IWDG初始化
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//取消写保护,方便后续调用寄存器
IWDG_SetPrescaler(prer);//设置预分频值
IWDG_SetReload(rlr);//设置重装载值
IWDG_ReloadCounter();//把重装载寄存器rlr的值加载到KR寄存器中,进行看门狗喂狗
IWDG_Enable();//看门狗使能
}
void IWDG_FEED(void)//看门狗喂狗
{
IWDG_ReloadCounter();//往KR寄存器中写0xAAAA;
}
#ifndef _IWDG__H_
#define _IWDG__H_
#include "sys.h"
void IWDG_Init(unsigned char prer,unsigned int rlr);
void IWDG_FEED(void);
#endif