STM32中的看门狗

发布者:喜悦的38号最新更新时间:2019-03-12 来源: eefocus关键字:STM32  看门狗 手机看文章 扫描二维码
随时随地手机看文章

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog) 。


简单来说,看门狗就是在不停地对我们正在运行的程序进行监视,我们必须在规定的时间的有效的时间内去进行“喂狗”操作,这样看门狗就知道我们的程序正在正常的运行,如果我们程序由于外界原因跑飞了,那么就无法进行喂狗操作,那么看门狗由于饥饿难耐,他就会使我们的单片机进行复位,以便让程序重新开始运行。


看门狗分为独立看门狗和窗口看门狗,独立看门狗比较简单,当然它的安全性没有窗口看门狗高。下面就简单介绍一下这两个狗狗。


1、独立看门狗(IWDOG)

独立看门狗是由专门的低速总线进行驱动,即LSI总线(时钟频率40KHz),它可以在主时钟故障的情况下仍然可以工作(或许这就是把这只狗成为独立看门狗的原因吧)。独立看门狗适合应用于需要看门狗作为一个在主程序之外 能够完全独立工作,并且对时间精度要求低的场合。


在键值寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗。此时计数器开始从其复位值0xFFF递减,当计数器值计数到尾值0x000时会产生一个复位信号(IWDG_RESET)。


无论何时,只要在键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗,但是0XAAAA并不是装入计数器中的值,真正装入计数器中的值是我们根据分频系数和我们需要的超时时间来计算好的), 自动重装载寄存器IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。


如果程序异常,就无法正常喂狗,从而系统复位。

下面是独立看门狗所用到的库函数


void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);//取消写保护:0x5555使能

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//设置预分频系数:写PR

void IWDG_SetReload(uint16_t Reload);//设置重装载值:写RLR

void IWDG_ReloadCounter(void);//喂狗:写0xAAAA到KR

void IWDG_Enable(void);//使能看门狗:写0xCCCC到KR

FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);//状态:重装载/预分频 更新


由于预分频寄存器和重装载寄存器具有写保护,所以我们在设置这两个寄存器的值的时候,需要先取消写保护(调用相关函数即可)。

独立看门狗操作步骤


1、  取消寄存器写保护:

     IWDG_WriteAccessCmd();

2、  设置独立看门狗的预分频系数,确定时钟:

     IWDG_SetPrescaler();

3、  设置看门狗重装载值,确定溢出时间:

     IWDG_SetReload();

4、  使能看门狗

     IWDG_Enable();

5、  应用程序喂狗:

     IWDG_ReloadCounter();


   溢出时间计算:

   Tout=((4×2^prer) ×rlr) /40 (M3)



相关代码如下


//初始化独立看门狗

//prer:分频数:0~7(只有低3位有效!)

//分频因子=4*2^prer.但最大值只能是256!

//rlr:重装载寄存器值:低11位有效.

//时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).

void IWDG_Init(u8 prer,u16 rlr) 

{

  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  //使能对寄存器IWDG_PR和IWDG_RLR的写操作,即取消写保护

IWDG_SetPrescaler(prer);  //设置IWDG预分频值

IWDG_SetReload(rlr);  //设置IWDG重装载值

IWDG_ReloadCounter();  //按照IWDG重装载寄存器的值重装载IWDG计数器

IWDG_Enable();  //使能IWDG

}

//喂独立看门狗

void IWDG_Feed(void)

{   

  IWDG_ReloadCounter();//reload    

}


这里面所谓的时间计算就是让我们设置必须在多长的时间内进行喂狗,我们根据上面的公式,选择好与分频系数和重装载的值,就可以得到这个喂狗时间了,我们必须在这个时间内进行喂狗至少一次(哪怕你一直不停的喂,但是必须至少喂一次,否则它就会使单片机复位)


2、窗口看门狗(WWDOG)

窗口看门狗是用APB1总线驱动的,时钟频率最大36MHz

说起窗口看门狗,其实它的基本原理和独立看门狗是一样的,只不过我们又在喂狗的时间上做了一些手脚,在独立看门狗中,我们可以从计数器的值一直减到0的中间的任何时刻都可以进行喂狗,但是在窗口看门狗中,我们规定只能在某一个时间段内进行喂狗,举个栗子,假如说我们计数器是从100减到0,我们现在规定只能在计数器为80—30这个段内进行喂狗(这也就是窗口这个名词的来源),否则我们看门狗就会产生一个复位信号,从而使单片机复位,从这可以看出来,窗口看门狗的安全性比独立看门狗要高一些,毕竟它喂狗的时间段缩短了,这样就会降低由于程序跑飞而误打误撞的去执行喂狗操作的几率了。

对于窗口看门狗,我们不能太早喂狗,也不能太晚喂狗,最晚喂狗时间所对应的计数器值为0X3FH

我们来看一张图


当计数器的值T6:0>W6:0的值,也就是此时我们还处于上窗口,假如说我们现在喂狗,也就是把WWDG_CR置1,这时与门输出1,经过一个或门,输出1,然后我们又使能了WDGA位(使能这一位就相当于开启了窗口看门狗),然后又经过一个与门输出1,所以此时就会产生复位,即我们不能在上窗口之前进行喂狗(即不能太早喂狗)。第二种情况是我们不能等到计数器减到0X3FH之后再喂狗,因为到达0X3FH的时候,T6位就会由高跳变为低(0X40是0100 0000,0X3F是0011 1111),此时他经过一个非门和或门,再加上WDGA位也置1了(即开启了窗口看门狗),此时就会复位,即我们也不能太晚喂狗。


对于窗口看门狗,我们可以建立一个提前唤醒中断EWI,用来提醒我们去喂狗,即当计数器减到0X40的时候,产生一个中断,我们在这个中断里面去执行喂狗操作,这样就能够保持这个狗狗不闹腾了(即它不会让单片机复位了)。关于此中断,有一个中断标志位EWIF,这个标志位是当计数器减到0X40的时候,由硬件置1,当我们进入到中断服务函数并且执行完喂狗之后,需要用软件把这一位清零。


窗口看门狗配置过程如下


 1、使能看门狗时钟:

     RCC_APB1PeriphClockCmd();

2、  设置分频系数:

     WWDG_SetPrescaler();

3、 设置上窗口值:

     WWDG_SetWindowValue();

4、 开启提前唤醒中断并分组(可选):

     WWDG_EnableIT();   

     NVIC_Init();

5、 使能看门狗:

     WWDG_Enable();

6、 喂狗:

    WWDG_SetCounter();

7、 编写中断服务函数

    WWDG_IRQHandler();


部分代码如下


//保存WWDG计数器的设置值,默认为最大. 

u8 WWDG_CNT=0x7f; 

//初始化窗口看门狗

//tr   :T[6:0],计数器值 

//wr   :W[6:0],窗口值 

//fprer:分频系数(WDGTB),仅最低2位有效 

//Fwwdg=PCLK1/(4096*2^fprer). 


void WWDG_Init(u8 tr,u8 wr,u32 fprer)

RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //   WWDG时钟使能


WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.   

WWDG_SetPrescaler(fprer);////设置IWDG预分频值

WWDG_SetWindowValue(wr);//设置窗口值

WWDG_Enable(WWDG_CNT); //使能看门狗,设置计数器初值                 

WWDG_ClearFlag();//清除提前唤醒中断标志位 

WWDG_NVIC_Init();//初始化窗口看门狗 NVIC

WWDG_EnableIT(); //开启窗口看门狗中断

//重设置WWDG计数器的值

void WWDG_Set_Counter(u8 cnt)

{

    WWDG_Enable(cnt);//使能看门狗 , 设置 counter .  

}

//窗口看门狗中断服务程序

void WWDG_NVIC_Init()

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;    //WWDG中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   //抢占2,子优先级3,组2

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占2,子优先级3,组2

  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; 

NVIC_Init(&NVIC_InitStructure);//NVIC初始化

}


void WWDG_IRQHandler(void)

{


WWDG_SetCounter(WWDG_CNT);   //当禁掉此句后,窗口看门狗将产生复位


WWDG_ClearFlag();   //清除提前唤醒中断标志位

}


这里面我们注意到这样的语句


u8 WWDG_CNT=0x7f; 


WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.  


我们把送入的初值的最高位利用与的操作给清零了,这是因为在窗口看门狗的控制寄存器中(也就是计数器中)的最高位是控制窗口看门狗是否使能的控制位,这一位不参与计数,所以我们需要把最高位给清零,然后再在后面使能这个最高位,即开启窗口看门狗


关于使能和设置计数器初值是使用一个函数来完成的,即WWDG_Enable(WWDG_CNT); //使能看门狗,并设置计数器初值

关于两只小狗狗就先说到这吧


关键字:STM32  看门狗 引用地址:STM32中的看门狗

上一篇:STM32中的串口通信
下一篇:STM32之AHB与APB总线

推荐阅读最新更新时间:2024-03-16 16:25

PIC16位单片机CAN(8)看门狗
程序的框架已经出来了,把看门狗打开剩下的就是程序结构的完善了。 根据文档说明,看门狗主要就是配置位的配置。下面是我的配置: _FWDT(WDTPOST_PS4096&WDTPRE_PR32&PLLKEN_OFF&WINDIS_OFF&FWDTEN_ON); //后分频器4096(4096*1ms=4s) 预分频器32分频(1ms) 禁止看门狗窗口模式 使能看门狗 看门够一个独立的32KHz的时钟,可以经过预分频和后分频进行操作, 由 LPRC 提供的看门狗定时器时钟源的频率标称值为 32 kHz。该信号输入给可配置为 5 位 (32 分频)或 7 位(128 分频)工作的预分频器。预分频比通过 WDTPRE 配置位进行设置
[单片机]
STM32学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
1.实验目的 使用高级定时器,输出两路互补的PWM输出,需要有带死区和不带死区两种情况 2.实验效果 图1:不带死区的两路互补的PWM输出 图2 :带死区的两路互补的PWM输出 3.理论部分 3.1时钟源 内部时钟(基本定时器,通用定时器时钟源来自PCLK1,但高级定时器的时钟源来自PCLK2(72M)) 实践中几乎无需使用:外部时钟模式1、外部时钟模式2 3.2时基单元 组成: 16bit预分频PSC 16bit计数器CNT 8bit重复计数器RCR(高级定时器独有) 16bit自动重装载寄存器ARR 3.3输入捕获 作用:对输入信号的上升沿/下降沿/双边沿进行捕获,测量输入信号的脉宽,和
[单片机]
<font color='red'>STM32</font>学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
【话说定时器系列】之四:STM32定时器更新事件及案例分享
我们知道,STM32定时器中的四个带影子特性的寄存器组,每组寄存器分别由 影子寄存器【即实际控制寄存器】和预装寄存器组成。其中,影子寄存器是真正起作用的控制寄存器,用户访问不到它。而预装寄存器是用户访问的为实际影子寄存器准备数据或指令的寄存器。它们分别是: TIMx_PSC 分频寄存器 TIMx_ARR 自动重装载寄存器 TIMx_CCR 捕捉寄存器 TIMx_RCR 重复计数寄存器[高级定时器有】 其中,ARR、CCR寄存器带预装载使能控制位,即它们的预装功能可以软件开启或关闭。 TIMx_ARR 带预装载使能控制位 ARPE@TIMx_CR1 TIMx_CCR 带预装载使能控制位 OCxPE@TIMx_CC
[单片机]
stm32 tim6、tim7中断配置以及注意事项
void TIM6_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; N
[单片机]
STM32调试过程中常见的问题及解决方法?
STM32调试过程中常见的问题及解决方法 一、 在 Debug选项卡 下设置好仿真器的类型后,下载程序时却提示 No ULINK Device found. 解决办法: Keil MDK默认使用ULINK仿真器下载程序,在 Project --- Option for Target 'xxx' --- Utilities选项卡 下把编程所使用的仿真器改为相应的类型即可。 二、 编译工程时提示如下信息: main.axf: Error: L6218E: Undefined symbol __BASEPRICONFIG (referred from stm32f10x_nvic.o). main.axf: E
[单片机]
用汇编语言做一个看门狗测试
用STC的MCU的IO方式控制74HC595驱动8位数码管。 ; 用户可以修改宏来选择时钟频率. ; 显示效果为: 显示秒计数, 5秒后不喂狗, 等复位. Fosc_KHZ EQU 22118 ;22118KHZ STACK_POIRTER EQU 0D0H ; 堆栈开始地址 DIS_DOT EQU 020H DIS_BLACK EQU 010H DIS_ EQU 011H AUXR DATA 08EH P4 DATA 0C0H P5 DATA 0C8H P0M1 DATA 0x93 ; P0M0 DATA 0x94 ; P1M1 DATA 0x91 ; P1M0 DATA 0x92 ; P2M1 DATA 0x95 ; P2M0
[单片机]
关于STM32中断的部分理解
中断这个问题从学习stm32一开始就困扰着我,我想估计很多初学者都会有这样的问题。曾经问过隔壁实验室的职工,人家没告诉我,让我自己回去理解。同行是冤家,这句话很在理。 首先提出我对几个中断的理解不了的问题: 1、中断是干嘛的? 2、中断是如何从函数进入的? 3、中断相关设置是如何设置的? 第一个问题:关于中断可以有一个很形象的解释:你正在吃饭,突然尿急了,准备去尿尿,中断了吃饭的这一过程。从程序上解释就是吃饭可以分解为一系列的动作,称为主程序,每个动作相当于函数,组成了这个主程序。这时候你尿急了,产生了一个信号,相当于中断信号,告诉大脑CPU,现在尿急比较重要,不然会尿裤子。这时候大脑会停下吃饭这一主程序,去执行撒尿这程序
[单片机]
ST新开发环境极大降低STM32微控制器的使用门槛
意法半导体(纽约证券交易所代码:STM)发布一套价格极低的开发环境,让更多的开发人员有机会使用意法半导体针对嵌入式应用专门研制、采用ARM Cortex-M3处理器内核的STM32系列微控制器。 新的开发环境整合Atollic TrueSTUDIO®/STM32开发工具和意法半导体的ST-LINK调试器,前者可以从网站免费下载,无使用代码量或使用时间限制;后者通过USB端口可连接到目标微控制器。对于初期投资很小的项目,花费很少即可拥有ST-LINK,因此尝试性和小批量的产品概念的各种初始设计,均能受益于STM32系列微控制器的高性能、低功耗和丰富功能,方便选择STM32系列70多款软件、引脚和外设相互兼容的产品
[单片机]
ST新开发环境极大降低<font color='red'>STM32</font>微控制器的使用门槛
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved