历史上的今天
返回首页

历史上的今天

今天是:2025年03月12日(星期三)

正在发生

2019年03月12日 | STM32中的看门狗

2019-03-12 来源:eefocus

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

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


推荐阅读

史海拾趣

诚芯微(CXW)公司的发展小趣事

在2021年,诚芯微获得了数千万元的Pre-B轮融资,由中信建投和投控东海入股、时代伯乐加投。这笔融资为公司的发展注入了新的动力。同时,公司还完成了股改,正式更名为深圳市诚芯微科技股份有限公司。股改完成后,诚芯微的治理结构更加完善,为公司未来的发展奠定了坚实的基础。

以上故事仅为概述性描述,实际发展过程中可能涉及更多细节和复杂因素。如需更详细的信息,建议查阅相关新闻报道或行业分析报告。

全智景(Allvision)公司的发展小趣事

在追求经济效益的同时,全智景公司也积极履行社会责任,致力于可持续发展。公司注重环保和节能技术的研发和应用,推出了多款绿色环保的产品。同时,全智景公司还积极参与社会公益事业,捐款捐物支持灾区重建和贫困地区的教育事业。这些举措不仅彰显了公司的社会责任感,也为公司的可持续发展奠定了坚实的基础。

通过以上五个故事,我们可以看到全智景公司在电子行业里的发展历程。从技术突破引领市场,到跨界合作拓展应用;从持续创新引领潮流,到全球化战略助力发展;再到履行社会责任与可持续发展。全智景公司以其坚定的信念和不懈的努力,在电子行业中取得了显著的成就。

Amveco Toroidal Power Products公司的发展小趣事

Amveco Toroidal Power Products公司成立于XXXX年,初始阶段主要专注于环形变压器的研发与生产。创始人凭借对环形变压器技术的深入了解和市场需求的敏锐洞察,带领团队克服了初创期的种种困难,成功开发出了具有高效能、低噪音特点的环形变压器产品,并赢得了客户的初步认可。随着市场口碑的逐渐积累,公司的业务规模开始稳步扩大。

Honda Tsushin Kogyo Co Ltd公司的发展小趣事

在电子行业快速发展的同时,Honda Tsushin Kogyo也面临着来自技术革新、市场竞争等方面的挑战。为了保持领先地位,公司可能积极应对这些挑战,通过转型升级来实现可持续发展。例如,公司可能加大了对新能源、物联网等新兴领域的投入,研发出符合市场需求的新产品。同时,公司还注重提升生产效率和降低成本,以应对激烈的市场竞争。

HDK(北陆电气)公司的发展小趣事

Honda Tsushin Kogyo在发展的过程中,可能形成了独特的企业文化和社会责任感。公司注重员工培训和团队建设,为员工提供良好的工作环境和发展机会。同时,公司还积极参与社会公益事业,通过捐赠、志愿服务等方式回馈社会。这些举措不仅提升了企业的社会形象,还增强了员工的归属感和凝聚力。在企业文化和社会责任的引领下,Honda Tsushin Kogyo实现了经济效益和社会效益的双赢。

需要注意的是,由于Honda Tsushin Kogyo的具体发展历程和详细故事可能并不完全公开,以上内容主要基于一般性的电子行业发展趋势和企业发展规律进行推测和整理。

APEM公司的发展小趣事

为了进一步丰富产品线,APEM在1984年开设了新厂,专业生产开关面板。这一举措不仅扩充了公司的产品种类,也满足了客户对多样化产品的需求。此后,APEM不断推出新产品,逐步形成了完善的开关和控制面板产品线。

问答坊 | AI 解惑

数字幅频均衡功率放大器

本帖最后由 paulhyde 于 2014-9-15 09:23 编辑 本科组F题——数字幅频均衡功率放大器本科 一、任务 设计并制作一个数字幅频均衡功率放大器。该放大器包括前置放大、带阻网络、数字幅频均衡和低频功率放大电路,其组成框图如图1所示。 下载 (1 ...…

查看全部问答>

se8a73up

是一USB芯片谁用过? 可以简单介绍下么? 英文资料看起来吃力…

查看全部问答>

AT91RM9200 启动问题

前提环境:AT91Rm9200 +S29Gl064A R6 SDRAM MT48LC16 问题描述:由内部rom启动后将boot.bin、u-boot.bin.gz烧入flash。能够正常烧录,没有问题! 由flash启动,u-boot 能够启动正常,停留在Uboot->处!但写数据到flash,会报timeout错误! 个人问 ...…

查看全部问答>

stc单片机扩展RAM问题——急!

本人使用STC12LE5A60S2单片机,本身有60K的ROM和1280的RAM,但是由于我做的是个通信处理软件所以涉及到的中间变量特别多,所以超出了1280的RAM不得不扩展RAM,但是最近新做好的板子到手后发现一个问题,在设置AUXR.1(也即使EXTRAM)为0不屏蔽内部扩 ...…

查看全部问答>

高手帮忙,内核定制问题

我想请问下如果把定制的映像下载到SDRAM里,掉电会丢失,重启后会回到原来的没下载之前的系统吗?请路过高手帮帮忙。。谢谢 …

查看全部问答>

我的流驱动啊,老是出问题。DLL_THREAD_DETACH

我的串口总是提示DLL_THREAD_DETACH如下: MID = 0xec, DID = 0x76 4th Cycle : 0xa5 NUMBLOCKS : 512(0x200), SECTORSPERBLOCK = 256(0x100), BYTESPERSECTOR = 512(0x200) STRINGS: **********DLL_PROCESS_ATTACH STRFMD_OEMIoControl: unre ...…

查看全部问答>

易电源学习心得

最近老板让我做个电源板,前几天一直忙着选型号。之前老板给我挑了型号LMZ10503ext,后来一查是个军品,价格高不可攀。做这个电源板主要是学习之用,对温度范围没有太高的要求,所以确定了 LMZ10503TZ-ADJ LMZ12001TZ-ADJ LMZ12002TZ-ADJ。有个问题 ...…

查看全部问答>

讨论开发linux到MTD设备时,如何确定NAND FLASH一些参数。

开发linux到MTD设备时,如何确定NAND FLASH一些参数。 struct nand_flash_dev {         char * name;//名字。这个容易理解         int manufacture_id;//制造商。芯片手册上有。     &nbs ...…

查看全部问答>

TFT液晶(ssd1289驱动)快速上手『基于msp430单片机的程序讲解』

本帖最后由 hjl240 于 2014-2-16 18:28 编辑        首先讲个题外话,论坛上有很多分享代码的,不过,我觉得,唯一不好的一点就是:只上传代码,却没有具体讲解一下代码。要是代码里有详细的注释,那样的话,不具体讲解代码 ...…

查看全部问答>

DIY手机+Sur

哎,发不了第一贴 DIY一个手机的话,我最理想的是模块化手机,最起码的GSM,MCU,屏幕,听、话筒,其他的可以删减啊 键盘我们得有,这个可以省掉 显示屏,至少得是彩屏吧 MCU至少要一个哎 GSM模块一只 其他功能嘛 震动:要电机一只 话筒: ...…

查看全部问答>