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在睡眠模式下,看门狗如何工作。初步认识为看门狗继续工作,计数器一直计数,有待后续验证!

  • 相关阅读:
    Attach Files to Objects 将文件附加到对象
    Provide Several View Variants for End-Users 为最终用户提供多个视图变体
    Audit Object Changes 审核对象更改
    Toggle the WinForms Ribbon Interface 切换 WinForms 功能区界面
    Change Style of Navigation Items 更改导航项的样式
    Apply Grouping to List View Data 将分组应用于列表视图数据
    Choose the WinForms UI Type 选择 WinForms UI 类型
    Filter List Views 筛选器列表视图
    Make a List View Editable 使列表视图可编辑
    Add a Preview to a List View将预览添加到列表视图
  • 原文地址:https://www.cnblogs.com/chenzhao207/p/4544744.html
Copyright © 2011-2022 走看看