zoukankan      html  css  js  c++  java
  • CC2541蓝牙学习——看门狗

    看门狗是在软件跑飞的情况下CPU自恢复的一个方式,看门狗分为硬狗和软狗,硬狗就是由专门的看门狗硬件电路实现看门狗功能,看门狗芯片也比较多,比如DS1232,除了看门狗功能外还有电源电压监测功能。软狗就是由软件实现的看门狗功能,现在很多CPU都自带了软狗,很难说硬狗好还是软狗好,如果软狗够用,尽量使用软狗简化设计,看门狗说白了就是一个定时器!,当软件在选定的时间间隔内不能置位看门狗定时器(WDT),WDT就复位系统。看门狗可用于电噪声,电源故障或静电放电等恶劣工作环境或高可靠性要求的环境。如果系统不需要应用到看门狗,则WDT可配置成间隔定时器,当时间间隔到达产生中断。 WDT的特性如下:

    1. 4个可选择的时间间隔
    2. 看门狗模式
    3. 定时器模式
    4. 定时器模式下产生中断请求

    CC2541的看门狗定时器(WDT)可以配置成看门狗模式或者普通的间隔定时器,WDT包括一个15位定时/计数器,它的频率由32.768KHz的晶振决定,用户不能查看计数器的值。

    看门狗的模式由寄存器WDCTL来配置,寄存器WDCTL的定义如下:

    WDCTL.INT[1:0]:定时器定时间隔选择位,有四种可选的时间间隔,32.768KHz时钟下,1s、0.25s、15.625ms、1.9ms分别对应32768、8192、512和64个时钟周期。注意,定时时间间隔只能在看门狗处于空闲(IDLE)模式下才能配置有效。

    WDCTL.MODE[1:0]:模式选择位,有三种模式可选择,空闲模式、看门狗模式和计时器模式,在计时器模式下,设置该位为00空闲模式则停止该计数器,当需要从计数器模式转换到看门狗模式,必须首先使该位为00使之处于空闲模式,然后再赋值10,转换到看门狗模式。如果处于看门狗模式,则不管向该位写入什么值都不起作用了,始终处于看门狗模式。一般来说,也不会在程序里切换模式,都是作单一用途的。

    WDCTL.CLR[3:0]:看门狗定时器清零位,在看门狗模式下,先向该位写入0xa,再写入0x5,定时器计数值清0,注意的是写入0x5必须紧跟着写入0xa,这两条语句之间不能插入其他语句。当处于空闲模式下,写该位不会产生任何影响

     1 /******************************************************************************
     2 *函 数 名:FeetDog
     3 *功    能:喂狗,计数器清0
     4 *入口参数:无
     5 *出口参数:无
     6 ******************************************************************************/
     7 void FeetDog(void)
     8 {
     9   WDCTL = 0xa0;   //清除定时器。当0xA 跟随0x5 写到这些位,定时器被清除
    10   WDCTL = 0x50;
    11 }

    计时器模式下WDCTL.CLR[0]位置1(其他三位不管写入什么值),则计数器清0(0x0000),但计数器不会停止计数,WDCTL.MODE[1:0]设置为00,计时器模式下计数器才停止并且计数值清0。

    1、看门狗模式

    系统复位后默认是处于空闲模式的,所以需要人为设置为看门狗模式,将WDCTL.MODE[1:0]设置为10,此时看门狗计数器开始从0计数,一旦处于看门狗模式,就没有办法停止该计数器了,向WDCTL.MODE[1:0]写入00或者其他值都没有作用了。

    如果计数器计数到设定的计数值(32768、8192、512或者64),就会产生一个系统复位信号,如果计数器被清0,则此时计数器又从0开始计数,此过程称为”喂狗“,所以在程序合适的位置放置喂狗代码,程序运行一次循环则会清除计数器一次(喂狗一次),计数器就不会溢出,如果程序跑飞了,就执行不到喂狗代码,超过设定的时间间隔,计数器就会溢出,对系统复位。看门狗模式下不会产生中断。另外前面说过定时间隔只能在看门狗处于空闲(IDLE)模式下才能配置有效,而一旦设定为看门狗模式,就不会回到空闲(IDLE)模式,所以定时时间间隔也是不可更改的了。注意:看门狗的时间间隔应该大于喂狗程序执行一次所需的时间!不然还没喂狗计数器就溢出复位了。一般的1s都够了,没有哪个程序执行一次的时间会超过1s吧,呵呵。

    2、计时器模式

    将WDCTL.MODE[1:0]设置为11,WDT处于计时器模式。一旦设定WDCTL.MODE[1:0]为11,计数器就开始从0计数,当计数值达到设定的的计数值(32768、8192、512或者64),便会产生看门狗中断请求,IEN2.WDTIE看门狗中断使能的情况下,IRCON2.WDTIF看门狗中断标志位变为1。注意中断使能信号放在WDCTL.MODE[1:0]配置前面,不然计数器开始计时了,还没有开中断。

    在计数器模式下,WDCTL.CLR[0]为1则清除计数器,然后从0开始计数,并不会停止计数器,WDCTL.MODE[1:0]设置为00,计数器停止工作并且计数值清0。在计数器工作的时候,写入

    WDCTL.INT[1:0] 无效,定时时间间隔无法改变,当计数器达到设定值时,并不会产生系统复位信号。如果定时器不够用的时候可以用该定时器,但是定时的时间只有4种选择。

    看门狗模式

    示例程序:WDT为看门狗模式,时间间隔为1s,定时喂狗,如果没有喂狗,则系统不断复位,LED灯每隔1s亮灭一次,无需第87行延时程序,因为看门狗的时间间隔设定为1s,LED刚好亮1s。

     1 /******************************************************************************
     2 *文 件 名:WDT.c
     3 *作    者:陈照
     4 *时    间:2015-06-01
     5 *版    本:1.0
     6 *描    述:看门狗程序
     7 ******************************************************************************/
     8 #include <iocc2541.h>
     9 
    10 #define LED1 P1_0
    11 
    12 /******************************************************************************
    13 *函 数 名:Delay1ms
    14 *功    能:延时1ms
    15 *入口参数:uiDelay,延时参数,值越大,延时越长
    16 *出口参数:无
    17 ******************************************************************************/
    18 void Delay1ms(unsigned int uiDelay)
    19 {
    20   unsigned int i,j;
    21   for(i = 0; i < uiDelay; i++)
    22   {
    23     for(j = 0;j < 1322; j++);
    24   }
    25 }
    26 
    27 /****************************************************************
    28 *函 数 名:InitClock
    29 *功    能:系统时钟初始化
    30 *入口参数:无
    31 *出口参数:无
    32 *****************************************************************/
    33 void InitClock(void)
    34 {
    35   CLKCONCMD &= ~(1 << 6);       //选择32MHz晶振
    36   while(CLKCONSTA & (1 << 6));  //等待时钟稳定
    37   CLKCONCMD &= ~0x47;           //系统时钟和定时器时钟都是32M 
    38 }
    39 
    40 /******************************************************************************
    41 *函 数 名:InitLED
    42 *功    能:LED灯初始化
    43 *入口参数:无
    44 *出口参数:无
    45 ******************************************************************************/
    46 void InitLED(void)
    47 {
    48   P1SEL &= ~0x01;      //P1.0设置为通用I/O口
    49   P1DIR |=  0x01;      //P1.0设置为输出
    50 }
    51 
    52 /******************************************************************************
    53 *函 数 名:Init_Watchdog
    54 *功    能:看门狗初始化
    55 *入口参数:无
    56 *出口参数:无
    57 ******************************************************************************/
    58 void Init_Watchdog(void)
    59 {
    60   WDCTL = 0x00;  //打开IDLE 才能设置看门狗
    61   WDCTL |= 0x08; //定时器间隔选择,间隔一秒,设定为看门狗模式
    62 }
    63 
    64 /******************************************************************************
    65 *函 数 名:FeetDog
    66 *功    能:喂狗,计数器清0
    67 *入口参数:无
    68 *出口参数:无
    69 ******************************************************************************/
    70 void FeetDog(void)
    71 {
    72   WDCTL = 0xa0;   //清除定时器。当0xA 跟随0x5 写到这些位,定时器被清除
    73   WDCTL = 0x50;
    74   LED1 = 1;      //系统不复位LED1 灯长亮
    75 }
    76 
    77 /******************************************************************************
    78 *程序入口函数
    79 ******************************************************************************/
    80 int main(void)
    81 {
    82   InitClock();               //时钟初始化,32MHz
    83   InitLED();                 //LED初始化
    84   LED1 = 0;                  //熄灭LED1
    85   Delay1ms(1000);
    86   LED1 = 1;                  //点亮LED1
    87   //Delay1ms(1000);
    88   Init_Watchdog();           //看门狗初始化
    89    
    90   while(1)
    91   {
    92      FeetDog();              //喂狗程序
    93                               //注释掉次子函数,系统不断复位,LED1闪烁
    94   }
    95 }

     

    计时器模式

    示例:WDT处于计时器模式,中断方式,LED灯闪烁,0.25s状态改变一次

     1 /******************************************************************************
     2 *文 件 名:WDT.c
     3 *作    者:陈照
     4 *时    间:2015-06-01
     5 *版    本:1.0
     6 *描    述:WDT计时器模式
     7 ******************************************************************************/
     8 #include <iocc2541.h>
     9 
    10 typedef unsigned char uchar;
    11 typedef unsigned int  uint;
    12 
    13 #define LED1 P1_0
    14 
    15 /******************************************************************************
    16 *函 数 名:Delay1ms
    17 *功    能:延时1ms
    18 *入口参数:uiDelay,延时参数,值越大,延时越长
    19 *出口参数:无
    20 ******************************************************************************/
    21 void Delay1ms(unsigned int uiDelay)
    22 {
    23   unsigned int i,j;
    24   for(i = 0; i < uiDelay; i++)
    25   {
    26     for(j = 0;j < 1322; j++);
    27   }
    28 }
    29 
    30 /****************************************************************
    31 *函 数 名:InitClock
    32 *功    能:系统时钟初始化
    33 *入口参数:无
    34 *出口参数:无
    35 *****************************************************************/
    36 void InitClock(void)
    37 {
    38   CLKCONCMD &= ~(1 << 6);       //选择32MHz晶振
    39   while(CLKCONSTA & (1 << 6));  //等待时钟稳定
    40   CLKCONCMD &= ~0x47;           //系统时钟和定时器时钟都是32M 
    41 }
    42 
    43 /******************************************************************************
    44 *函 数 名:InitLED
    45 *功    能:LED灯初始化
    46 *入口参数:mode,mode为1则点亮所有LED,mode为0则熄灭所有LED
    47 *出口参数:无
    48 ******************************************************************************/
    49 void InitLED(uchar mode)
    50 {
    51   P1SEL &= ~0x01;      //P1.0设置为通用I/O口
    52   P1DIR |=  0x01;      //P1.0设置为输出
    53   LED1 = mode;         //LED灯亮熄控制
    54 }
    55 
    56 /******************************************************************************
    57 *函 数 名:Init_Watchdog
    58 *功    能:看门狗初始化
    59 *入口参数:无
    60 *出口参数:无
    61 ******************************************************************************/
    62 void Init_Watchdog(void)
    63 {
    64   WDCTL = 0x00;  //打开IDLE 才能设置计时器间隔时间
    65   WDCTL |= 0x0d; //设定为计时器模式,定时器间隔为0.25秒
    66 }
    67 
    68 /******************************************************************************
    69 *函 数 名:WDT_ISR
    70 *功    能:WDT计时器模式中断服务程序
    71 *入口参数:无
    72 *出口参数:无
    73 ******************************************************************************/
    74 #pragma vector = WDT_VECTOR 
    75 __interrupt void WDT_ISR(void) 
    76 { 
    77   WDTIF = 0;      //看门狗中断清除
    78   LED1 = ~LED1;   //定时时间到,LED状态翻转
    79 }
    80 
    81 /******************************************************************************
    82 *程序入口函数
    83 ******************************************************************************/
    84 int main(void)
    85 {
    86   InitClock();               //时钟初始化,32MHz
    87   InitLED(0);                //LED初始化,熄灭LED1
    88   IEN2 |= 0x20;              //看门狗中断使能
    89   EA = 1;                    //开总中断
    90   Init_Watchdog();           //看门狗初始化
    91    
    92   while(1)
    93   {
    94   };
    95 }

    拓展问题:CC2541在睡眠模式下,看门狗如何工作。初步认识为看门狗继续工作,计数器一直计数,有待后续验证!

  • 相关阅读:
    洛谷 P1316丢瓶盖
    喵哈哈村的魔法考试 (1)
    英语 词根 词缀 查询网址
    洛谷 保龄球
    find函数
    图书管理员
    最大公约数和最小公倍数问题
    openjudge 错误探测
    函数 记忆化搜索模型
    JSon_零基础_002_将List类型数组转换为JSon格式的对象字符串,返回给界面
  • 原文地址:https://www.cnblogs.com/chenzhao207/p/4544744.html
Copyright © 2011-2022 走看看