天天看點

應廣單片機休眠和按鍵喚醒

      對應電池供電的産品,在不使用的時候,單片機和外設都應該進入休眠狀态,用于減少對電池電量消耗.在使用的時候又能夠通過按鍵,或是其他信号喚醒系統,然後進入正常工作狀态.在電壓V3.3V的情況下,應廣單片機的休眠電流幾乎在2uA以下,經常測到都是一點幾uA.非常不錯|那麼應廣單片機的低功耗和按鍵喚醒是怎麼實作的呢?不多說上代碼.除了外部喚醒,還有一種機制是内部定時器定時喚醒,請聽下回分解!

#include    "extern.h"

#define     HIGH    1

#define  LOW    0

#define DISABLE 0

#define ENABLE 1

#define EMPTY 0

#define FULL 1

#define ON 1

#define OFF 0

#define LOW_POW_TIMING_TMR  5000

/*燈*/

BIT     LED_R           :        PA.0;

/*按鍵*/

BIT     KEY_POW           :        PA.3;

#define KEY_DEBOUNCE_CNT  20

#define KEY_LONG_PRESS_TIMER 1200

#define LED_R_ON   LED_R=1

#define LED_R_OFF  LED_R=0

/*定時時間是否到了cinit*/

bit     FLAG_NMS;

/*計數值cinit*/

byte    count;

/*定時器初始化cinit*/

word    T16COUNTER;

Eword ueLowPowAltTm;

byte ucKeyPowHigtCnt;

byte ucKeyPowLowCnt;

byte ucKeyPowSt;

byte ucKeyPowBak;

word usKeyPowLoPreCnt;

//word usKeyPowLoPreCntSet;

bit ucKeyPowPreSt;

void UpDateLedSt(void);

/***************************************/

void    TIME16_Init(void)

{

    /*計數值清零*/

    T16COUNTER    =488;

    /*ms标記reset*/

    FLAG_NMS    =0;

    /*使能定時器*/

    $    INTEN    T16;

    /*關中斷*/

    INTRQ        =    0;

    /*停止定時器*/

       T16M.5        =0;               

    STT16 T16COUNTER;

    /*計算方法16M/*/

    $    T16M    IHRC,/1,BIT11;     

}

//byte ucPadierBak;

/*低功耗*/

void LowPow(void)

{

    /*退出功能則進入低功耗*/

   if((!ueLowPowAltTm) )

   {    

         /*關燈*/

         LED_R_OFF;

        .delay 1000;

        /*清看門狗*/

        wdreset;

        /*IHRC ->ILRC,關看門狗*/

        CLKMD=0xf4;

        /*禁用IHRC*/

        CLKMD.4=0;

        while(1)

        {

             /*低功耗*/

             STOPSYS;

             if(KEY_POW==0)

             { 

                   break;   

             }

        }

        /*ILRC->IHRC ,

         b7:5@001=IHRC/8,

         b4@1=IHRC

         b3@1=模式1

         b2@ 1=ILRC啟動

         b1@ 1=看門狗開啟

         b0@ 0=Pa5;

         模式口1;開看門狗*/

        CLKMD=0b001_1_1110;

        ueLowPowAltTm=LOW_POW_TIMING_TMR;

        //$ padier 0b111_1_1001;

    }

}

/*10ms任務函數*/

void UpDateKeyTmr(void)

{

    if(KEY_POW)

    {

        ucKeyPowHigtCnt=KEY_DEBOUNCE_CNT;

    }

    /*目前狀态為0*/

    else

    {

        ucKeyPowLowCnt=KEY_DEBOUNCE_CNT;

    }

     /*KeyPow高電平計數值*/

     if(ucKeyPowHigtCnt)

     {

         ucKeyPowHigtCnt--;

        if(!ucKeyPowHigtCnt)

        {

            /*高電平倒計時完成說明目前為低*/

            ucKeyPowSt=LOW;

        }

     }

     /*KeyPow低電平計數值*/

     if(ucKeyPowLowCnt)

     {

         ucKeyPowLowCnt--;

        if(!ucKeyPowLowCnt)

        {

            /*低電平倒計時完成,說明目前為高*/

            ucKeyPowSt=HIGH;

        }

     }

}

/*狀态切換*/

void GetKeySt(void)

{

      /*狀态有變化*/

   if(ucKeyPowSt!=ucKeyPowBak)

   {  

        ucKeyPowBak=ucKeyPowSt;

        /*按鍵按下動作*/

        if(!ucKeyPowSt)

        {

                ueLowPowAltTm=LOW_POW_TIMING_TMR;

                /*點燈*/

                LED_R_ON;

           }

    }

}

/*端口狀态初始化*/

void KeyAppInit(void)

{

    if(KEY_POW)

    {

        ucKeyPowSt=HIGH;

        ucKeyPowBak=HIGH;

    }

    else

    {

        ucKeyPowSt=LOW;

        ucKeyPowBak=LOW;

    }

    ucKeyPowHigtCnt=KEY_DEBOUNCE_CNT;

    ucKeyPowLowCnt=KEY_DEBOUNCE_CNT;

    usKeyPowLoPreCnt=0;

    ucKeyPowPreSt=0;

}

void    FPPA0 (void)

{

    .ADJUST_IC    SYSCLK=IHRC/8, IHRC=16MHz, VDD=3.0V;

    $ CLKMD IHRC/8,En_IHRC,En_ILRC,En_WatchDog;

    .delay 40000;

    $  KEY_POW     IN,PULL; 

    $  LED_R     OUT,LOW;

    TIME16_Init();

    KeyAppInit();

    ueLowPowAltTm=1;

    engint;

    while (1)

    {

            wdreset;

         /*1ms定時時間到*/

         if ( FLAG_NMS )

         {

             /*清除标記*/

            FLAG_NMS=0;

            UpDateKeyTmr();

            /*低功耗定時器*/

            if(ueLowPowAltTm)

            {

                ueLowPowAltTm--;

            }

            LowPow();

        }

        /*取得按鍵狀态*/

        GetKeySt();

    }

}

void    Interrupt ( void )

{

    pushaf;

    if ( Intrq.T16 )  

    {

        Intrq.T16    =    0;

        STT16 T16COUNTER;

        if ( count>0 )

        {

            count--;

        }

        else

        {

            count   =   9;

            /*1ms*/

            FLAG_NMS=   1;      

        }