zoukankan      html  css  js  c++  java
  • N76E003之WDT(看门狗定时器)

    N76E003提供一个看门狗定时器(WDT),它可以配置成一个超时复位定时器用于复位整个设备。一旦由于外界干扰设备进入非正常状态或挂起,看门狗可以复位恢复系统。这有用于监测系统运行以提高系统可靠性。对于容易受到噪声,电源干扰或静电放电干扰的系统,是十分有用的。看门狗也可以配置成通用定时器,可以工作在空闲模式或掉电模式,用于周期中断服务作为事件定时器或连续系统监测。WDTEN[3:0] (CONFIG4[7:4])初始化WDT工作在超时复位定时器或通用定时器模式。

    WDT带一个独立的分频器用于分频10K LIRC时钟。分频器的时钟分频可选,来决定超时间间隔。当达到超时间隔,系统会被从空闲或掉电模式唤醒,且如果WDT中断使能会产生一个中断事件。如果WDT初始化为一个超时复位定时器,在经过一个延时周期而软件没有任何动作后会产生系统复位。

    超时复位定时器
    当配置 CONFIG 位 WDTEN[3:0] (CONFIG4[7:4]) 不是 FH时,WDT将初始化为一个超时复位定时器。如果WDTEN[3:0] 不是 5H, WDT在系统进入空闲或掉电模式后允许继续运行。注意当WDT初始化为超时复位定时器时,WDTR 和 WIDPD 没有作用。

    在设备上电后,开始执行软件代码,同时WDT开始计数。超时间隔时间通过WDPS[2:0] (WDCON[2:0])配置。当
    配置的超时事件发生,WDT会置位中断标志WDTF (WDCON.5)。如果WDT中断使能位EWDT (EIE.4)和全局中
    断使能EA都置位,WDT中断程序被执行。同时如果系统在正常运行中,在512个LIRC时钟延时期间,系统可通
    过置位WDCLR来清零计数器来避免系统被WDT复位。如果在这512个LIRC时钟内没有写1到WDCLR,WDT复
    位将会发生。置位WDCLR位用来清零WDT计数器。如系统正常运行,该位是自我清零。一旦WDT复位发生,
    WDT复位标志WDTRF (WDCON.3)将会被置位,除上电复位之外的其他任何复位后,该位都保持不变。用户可
    以通过软件清零WDTRF。注意WDCON的所有位有写入时序要求。

    注意:WDT计数器需特别注意。硬件会自动清除WDT计数器和预分频数值在下面事件发生后:
    (1)进入空闲或掉电模式,或被唤醒从空闲或掉电模式
    (2)重启。它能阻止不可预测的系统重启。
    看门狗定时器复位的主要应用是系统监测,这对于实时控制系统来说这很重要。在一些电源干扰,电磁干扰,
    CPU可能执行错误代码,或进入不可控制的状态。如果发生这些情况不加以控制,系统有可能崩溃。使用看门狗
    定时器用户可选择理想的“喂狗”时间来清除WDT计数器。通过指令置位 WDCLR, 可使程序继续运行而不看门
    狗定时器复位。如果干扰引起代码运行在错误的状态下,导致无法及时清除看门狗定时器,将引起芯片复位,使
    系统从错误的状态恢复过来。
    注意:如下条件会造成WDT复位失效,请避免。当CKDIV有设定值(不等于00H),说明系统频率除频生效,
    此时如果进入掉电模式,WDT复位会失效。建议对于掉电模式唤醒的应用,采用WKT唤醒。

    通用定时器
    看门狗定时器的另一个应用是用作简单的,长周期定时器。当CONFIG 位 WDTEN[3:0] (CONFIG4[7:4]) 是
    FH,WDT初始化为通用定时器。在这种模式下,WDTR 和 WIDPD 是可以通过软件进行访问操作。

    看门狗定时器通过设置WDTR为1开始运行,通过清零WDTR停止。当WDT配置的时间间隔到后,WDTF标志会
    置位。可通过软件查询WDTF标志来侦测是否超时。如果EWDT (EIE.4)和EA置位,WDT会产生中断,接着WDT
    会继续计数。用户必须清零WDTF并等待下一次溢出,通过查询WDTF标志或等待中断发生。
    在一些低功耗的应用中,为节省功耗,CPU在没有处理事件时常处于空闲模式。通过运行定时器0~3,周期性的
    的唤醒察看是否有需求响应,然后这种空闲模式下耗电量将达到毫安(mA)级,为了减少耗电量达到微安(μA)级的
    要求,当没有需求需要相应的时候,CPU应该停留在掉电模式,并且可以通过编程的时候间隔来唤醒。
    N76E003配备了很有用的WDT唤醒功能,由于基于内部10kHz的RC时钟源,看门狗定时器功耗非常低,它能够
    在掉电模式下计数并唤醒CPU。

    /*---------------------------------------------------------------------------------------------------------*/
    /*                                                                                                         */
    /* Copyright(c) 2016 Nuvoton Technology Corp. All rights reserved.                                         */
    /*                                                                                                         */
    /*---------------------------------------------------------------------------------------------------------*/
    
    //***********************************************************************************************************
    //  Nuvoton Technoledge Corp. 
    //  Website: http://www.nuvoton.com
    //  E-Mail : MicroC-8bit@nuvoton.com
    //  Date   : Apr/21/2016
    //***********************************************************************************************************

    #define set_WIDPD BIT_TMP=EA;EA=0;TA=0xAA;TA=0x55;WDCON|=SET_BIT4;EA=BIT_TMP;

    //***********************************************************************************************************
    //  File Function: N76E003 Watch Dog as pure timer with interrupt demo code
    //***********************************************************************************************************
    
    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_define.h"
    
    
    /************************************************************************************************************
    *    WDT interrupt sub-routine
    ************************************************************************************************************/
    void WDT_ISR (void)   interrupt 10
    {
    
                        //---------toggle GPIO1---------    
                            clr_GPIO1;
                            Timer0_Delay1ms(50);
                            set_GPIO1;
                            Timer0_Delay1ms(50);
                            clr_GPIO1;
                            Timer0_Delay1ms(50);
                            set_GPIO1;
                            Timer0_Delay1ms(50);
                        //---------end toggle GPIO2--------
            clr_WDTF;
            set_WDCLR;
    }
    
    /************************************************************************************************************
    *    Main function 
    ************************************************************************************************************/
    void main (void)
    {
    /* Note
      WDT timer base is LIRC 10Khz
    */
        
      Set_All_GPIO_Quasi_Mode;
        
                            clr_GPIO1;
                            Timer0_Delay1ms(500);
                            set_GPIO1;
                            Timer0_Delay1ms(500);
                            clr_GPIO1;
                            Timer0_Delay1ms(500);
                            set_GPIO1;
                            Timer0_Delay1ms(500);
        
    //WDT init
    //--------------------------------------------------------
    //Warning:
    //Pleaes always check CONFIG WDT disable first 
    //only when WDT reset disable, WDT use as pure timer
    //--------------------------------------------------------
          TA=0xAA;TA=0x55;WDCON=0x07;          //Setting WDT prescale 
            set_WDTR;                       //WDT run
            set_WDCLR;                                            //Clear WDT timer
            set_EWDT;
            EA =1;
    
    #if 0
        while(1);
    #else
            set_WIDPD;                                             //WDT run in POWER DOWM mode setting if needed
            while (1)
            {
                set_PD;
                        //---------toggle GPIO1---------    
                            clr_P04;
                            Timer1_Delay10ms(5);
                            set_P04;
                            Timer1_Delay10ms(5);
                            clr_P04;
                            Timer1_Delay10ms(5);
                            set_P04;
                            Timer1_Delay10ms(5);
                        //---------end toggle GPIO1---------
            }
    #endif
    }

    #if   ...   
    #else
    ...
    #endif//与#if对应
    作为一个编译“开关”,比如:
    #if(条件满足)
    执行代码1
    #else
    执行代码2
    #endif
    假如编译时,确实满足条件,则生成的程序文件(.exe文件)中不会有执行代码2的。如果用普通if语句,生成的程序文件就会有执行代码2,这个区别看看生成文件大小就可以知道。
    如果你的条件在程序编译前就已经确定了,那就用#if;如果条件需要在程序运行过程中才能判断,则用if。
  • 相关阅读:
    c#中String跟string的“区别”<转>
    JS中判断对象是否为空
    report builder地址:http://localhost/reports
    今天开始,主攻MS Dynamics CRM
    IO负载高的来源定位
    ORACL学习笔记 之 分区表
    Linux自动删除n天前日志
    Oracle中NVL2 和NULLIF的用法
    Ubuntu学习笔记之Sqldeveloper安装
    给ubuntu的swap分区增加容量
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/9306333.html
Copyright © 2011-2022 走看看