有没有办法关闭stm32 独立看门狗狗

嵌入式裸机开发(46)
看门狗作用:在嵌入式领域,有些系统需要长期运行在无人看守的环境。在运行过程中,难免不出现系统死机的情况,这时就需要系统自身带有一种自动重启的功能。watchdog一般是一个硬件模块,其作用就是在系统死机时,帮助系统实现重新启动。
看门狗工作方式:watchdog在硬件上实现了计时功能,启动计时后,用户(软件)必须在计时结束前重新开始计时,俗称“喂狗”,如果到了约定的时间还没有重新开始计时,那么它就认为系统死机了,就自动重启系统。
看门狗原理图:
uboot以及一般的bootloader都会关闭看门狗,这是因为bootloader较简单,没有复杂的功能,不会出现死机的情况。如果不关闭看门狗,则需要不断“喂狗”,因此为了节省资源,减少不必要的操作都会关闭看门狗。
通过WTCON寄存器可以实现看门狗的关闭或者使用。
以S3C2440芯片为例,WTCON寄存器:
由上图可知,WTCON地址为0x,该寄存器最后一位置零就可以关闭看门狗,为了方便,可以将整个寄存器置零
汇编代码:
#define pWTCON 0x
disable_watchdog:
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:68734次
积分:2039
积分:2039
排名:千里之外
原创:122篇
转载:53篇
(2)(4)(1)(5)(4)(16)(142)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'posts - 9,&
comments - 2,&
trackbacks - 0
一、独立看门狗
STM32&的独立看门狗由内部专门的&40Khz&低速时钟驱动,即使主时钟发生故障,它也仍然有效。
看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种情况的发生。看门狗的作用就是在一定时间内(通过定时计数器实现)没有接收喂狗信号(表示&MCU&已经挂了),便实现处理器的自动复位重启(发送复位信号)&。
在键值寄存器(IWDG_KR)中写入&0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值&0xFFF&递减计数。当计数器计数到末尾&0x000&时,会产生一个复位信号(IWDG_RESET)。无论何时,只要键寄存器&IWDG_KR&中被写入&0xAAAA,&&IWDG_RLR&中的值就会被重新加载到计数器中从而避免产生看门狗复位&&。
IWDG_PR&和&IWDG_RLR&寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR&寄存器中写入&0x5555。将其他值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入&0xAAAA)也会启动写保护功能。
只要对以上三个寄存器进行相应的设置,我们就可以启动&STM32&的独立看门狗,启动过程可以按如下步骤实现(独立看门狗相关的库函数和定义分布在文件&stm32f10x_iwdg.h&和stm32f10x_iwdg.c&中)&:
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&重装载值
设置好看门狗的分频系数&prer&和重装载值就可以知道看门狗的喂狗时间&(也就是看门狗溢出时间)&,该时间的计算方式为:
Tout=((4×2^prer)&&×rlr)&/40
其中&Tout&为看门狗溢出时间(单位为&ms)&;prer&为看门狗时钟预分频值(IWDG_PR&值),范围为&0~7;rlr&为看门狗的重装载值(IWDG_RLR&的值)&;
比如我们设定&prer&值为&4,&rlr&值为&625,那么就可以得到&Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是&1s,只要你在一秒钟之内,有一次写入&0XAAAA&到&IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的&40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。
3)重载计数值喂狗(向&IWDG_KR&写入&0XAAAA)
库函数里面重载计数值的函数是:
IWDG_ReloadCounter();&&&//按照&IWDG&重装载寄存器的值重装载&IWDG&计数器
通过这句,将使&STM32&重新加载&IWDG_RLR&的值到看门狗计数器里面。&即实现独立看门狗的喂狗操作。
4)&&启动看门狗(向&IWDG_KR&写入&0XCCCC)
库函数里面启动独立看门狗的函数是:
IWDG_Enable();&&&//使能&IWDG
通过这句,来启动&STM32&的看门狗。注意&IWDG&在一旦启用,就不能再被关闭!想要关闭,只能重启,并且重启之后不能打开&IWDG,否则问题依旧,所以在这里提醒大家,如果不用&IWDG&的话,就不要去打开它,免得麻烦。
* 初始化独立看门狗
* 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预分频值*/
IWDG_SetReload(rlr);
/*设置IWDG重装载值*/
IWDG_ReloadCounter();
/*按照IWDG重装载寄存器的值重装载IWDG计数器*/
IWDG_Enable();
/*使能IWDG*/
* 喂独立看门狗
void IWDG_Feed(void)
IWDG_ReloadCounter();
/*reload*/
void main(void)
NVIC_Configuration();//优先级配置
IWDG_Init(<span style="color: #,<span style="color: #5);//初始化独立看门狗,分频数为64,重装载值为625,溢出时间计算为:64*625/40=1000ms=1s
 while(<span style="color: #)
    delay_ms(<span style="color: #0);//<span style="color: #.5秒喂一次狗
  IWDG_Feed();//喂狗
二、窗口看门狗
窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在&T6&位&(WWDG-&CR&的第六位)变成&0&前被刷新,看门狗电路在达到预置的时间周期时,会产生一个&MCU&复位。在递减计数器达到窗口配置寄存器(WWDG-&CFR)数值之前,如果&7&位的递减计数器数值(在控制寄存器中)被刷新,&&&那么也将产生一个&MCU&复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。
1、有个7位递减计数器(WWDG-&CR),就这个计数器和窗口计数器(WWDG-&CFR)决定什么时候喂狗。狗喂早了,复位——“早”体现在 计数器值(tr)&窗口值(wr),也就是计数器值还没有减到窗口值以下;
2、当 0x40 & 计数器值(tr) & 窗口值(wr) 时,这时候最适合喂狗了,也只有在这时候喂狗才合适;
3、当 计数器的值 从0x40变到0x3F的时候,将产生看门狗复位;当然在要产生复位的前一段时间,如果开启了提前唤醒中断,那么就会进入中断,在中断函数里,我们需要及时喂狗,否则会产生复位;
4、据网上资料介绍,在这个中断里面一般不进行喂狗,一般是系统去世前的“遗嘱”,比如存储重要的数据等。这个就需要根据个人需要设计。&
库函数中用中断的方式来喂狗的方法,窗口看门狗库函数相关源码和定义分布在文件stm32f10x_wwdg.c&文件和头文件&stm32f10x_wwdg.h&中。步骤如下:
1)使能&WWDG&时钟
&WWDG使用的是&PCLK1&的时钟,需要先使能时钟。方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,&ENABLE);&&&//&WWDG&时钟使能
2)设置窗口值和分频数
设置窗口值的函数是:
void&WWDG_SetWindowValue(uint8_t&WindowValue);
这个函数就一个入口参数为窗口值,很容易理解。
设置分频数的函数是:
void&WWDG_SetPrescaler(uint32_t&WWDG_Prescaler);
这个函数同样只有一个入口参数就是分频值。
3)开启&WWDG&中断并分组
开启&WWDG&中断的函数为:
WWDG_EnableIT();&//开启窗口看门狗中断
接下来是进行中断优先级配置,使用&NVIC_Init()函数即可。
4)设置计数器初始值并使能看门狗
这一步在库函数里面是通过一个函数实现的:
void&WWDG_Enable(uint8_t&Counter);
该函数既设置了计数器初始值,同时使能了窗口看门狗。
5)编写中断服务函数
在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当窗口看门狗计数器值减到&0X3F&的时候,就会引起软复位了。在中断服务函数里面也要将状态寄存器的&EWIF&位清空。&
完成了以上&5&个步骤之后,我们就可以使用&STM32&的窗口看门狗了。
static u8 WWDG_CNT=<span style="color: #x7f;
/*保存WWDG计数器的设置值,默认为最大. */
* 初始化窗口看门狗
* 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_SetPrescaler(fprer); /*设置IWDG预分频值*/
WWDG_SetWindowValue(wr);
/*设置窗口值*/
WWDG_CNT=tr&WWDG_CNT; /* 初始化WWDG_CNT. */
WWDG_Enable(WWDG_CNT);
/*使能看门狗 ,
设置 counter . */
WWDG_ClearFlag();
/*清除提前唤醒中断标志位*/
WWDG_NVIC_Init();/* 初始化窗口看门狗 NVIC */
WWDG_EnableIT(); /* 开启窗口看门狗中断 */
* 窗口看门狗中断服务程序
void WWDG_NVIC_Init(void)
NVIC_InitTypeDef NVIC_InitS
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
/*WWDG中断*/
/* 抢占2,子优先级3 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = <span style="color: #;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = <span style="color: #;
NVIC_Init(&NVIC_InitStructure);/*
NVIC初始化*/
* 重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
WWDG_Enable(cnt); /*使能看门狗 ,
设置 counter .
* 看门狗中断服务程序
void WWDG_IRQHandler(void)
WWDG_Set_Counter(WWDG_CNT);
WWDG_ClearFlag();
/*清除提前唤醒中断标志位*/
LED1 = ~LED1;
/*LED状态翻转 */
小总结,一般工程都会使用两个看门狗,一个是独立看门狗,主要用于在代码跑飞之后复位使用,一个是窗口看门狗,主要用于在复位前对于一些重要数据进行保存。
参考来源:http://blog.chinaunix.net/uid--id-4088766.html
     &http://blog.chinaunix.net/uid--id-4089265.html
阅读(...) 评论()博客访问: 5283
博文数量: 10
博客积分: 0
博客等级: 民兵
技术积分: 75
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
IWDG独立看门狗实验,本实验通过设置窗口看门狗IWDG间断时间来定期的检查是否出错,在SysTick_Handler中断函数中加入了流水灯用来测试是否运行了IDWG看门狗程序,用PD6-LED2通过闪烁验证程序可行性,编程工程大致和USART实验过程差不多,先是开启系统时钟,然后GPIO端口时钟,然后复用功能时钟AFIO,然后各个模块用的的时钟,,呵呵,之后进入各个模块初始化,设置,编写子程序,中断的话,要在中断函数中填写某模块的中断触发处理函数,重要的是在CONFG.H函数中开启模块的声明,差不多是这样的了。
以下为IWDG函数主要部分:
//IWDG窗口看门狗设置初始化
void IWDG_Config(void)
&&//独立看门狗初始化
&&&IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//启动寄存器读写
&&&IWDG_SetPrescaler(IWDG_Prescaler_32);//40K时钟32分频
&&&IWDG_SetReload(349);&&&&&&&&&&&&&&&&&//计数器数值
&&&IWDG_ReloadCounter();&&&&&&&&&&&&&//重启计数器
&&&IWDG_Enable();&&&&&&&&&&&&&&&&&&&&&&&//启动看门狗
***********************************************************
注意事项:
i. 有狗平常没事情可以不理,但是千万别忘了喂它,否则死都不知道怎么死的!
ii. 初始化程序的调用一定要在systic的初始化之后。
iii. 独立看门狗需要systic中断来喂,但是systic做别的用处不能只做这件事,所以我写了如下几句代码,可以不影响systic的其他应用,其他systic周期代码也可参考:
第一步:在stm32f10x_it.c中定义变量
int Tic_IWDG;&&&&&&&&&&&//喂狗循环程序的频率判断变量
第二步:将SysTickHandler中喂狗代码改为下面:
Tic_IWDG++;&&&&&&&&&&//变量递增
if(Tic_IWDG>=100)&&&&//每100个systic周期喂狗
{&&&IWDG_ReloadCounter();//重启计数器(喂狗)
&&&Tic_IWDG=0;&&&&&&&//变量清零
完整代码为
void SysTick_Handler(void)
&&Tic_Val++;&&&&&&&&&&&//精确延时变量递增
&&Tic_IWDG++;&&&&&&&&&&//独立看门狗变量递增
&&if(Tic_IWDG>=100)&&&&//每100个systic周期喂狗
&&&&IWDG_ReloadCounter();//重启计数器(喂狗)
&&&&Tic_IWDG=0;&&&&&&&//变量清零
&switch(IWDGFLAG)
&&GPIO_SetBits(GPIOD, GPIO_Pin_6);
&&GPIO_ResetBits(GPIOD, GPIO_Pin_6);
&IWDGFLAG=!IWDGFLAG;
阅读(92) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。热点资讯||

我要回帖

更多关于 stm32f407 独立看门狗 的文章

 

随机推荐