应广单片机按键程序_生产者/消费者模型

应广单片机按键检测程序,为了方便大家理解,用生产者/消费者模型去做按键检测.


#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


/*单位 ms*/
#define RUN_TMR     15000

#define LOW_POW_TIMING_TMR  3000

BIT     LED_G           :        PA.3;
BIT     KEY_HIT            :        PA.4;

#define KEY_DEBOUNCE_CNT  20

#define GRE_LED_ON   $  LED_G     OUT,LOW

#define GRE_LED_OFF  $  LED_G     OUT,HIGH

#define GRE_LED_FLASH  {if(LED_G){LED_G=0;}else{ LED_G=1;}}


/*计数值Cinit*/
word ucFlashTmrCnt;
/*cinit*/
BIT ubMsFlag; 

/*cinit*/
BIT  ubEnLedFlash; 
/*unit 10ms*/
word usMsFlashTmr;

byte ucSysSt;

bit     FLAG_NMS;
/*计数值cinit*/
byte    count;
/*定时器初始化cinit*/
word    T16COUNTER;

/*高低键盘倒计时*/
byte ucKeyHitHigtCnt;
byte ucKeyHitLowCnt;
/*按键状态*/
byte ucKeyHitSt;
byte ucKeyHitBak;


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;     
    

}

void UpdateLedTmr(void)
{
   /*是否闪烁*/
   if(ubEnLedFlash)
   {
         /*1ms进行一次计数*/
        ucFlashTmrCnt++;
        if(ucFlashTmrCnt>250)
        {
            ucFlashTmrCnt=0;
            /*闪灯*/
            GRE_LED_FLASH;
        }
   }

}


/**********************************************************************
             生产者/消费者模型           
每1ms执行一次,查看按键端口状态
如果端口为1,只生产商品"1";
如果端口为0,只生产商品"0"
根据端口状态,每1ms生产20个产品(商品"1"/商品"0"),
*********************************************
同时设置消费者
消费者每1ms值消费一个商品
******************************
1.如果生产者一直生产,那么消费者永远无法消费完商品(每1ms生产20个商品,而只消费1个)
2.如果生产者不在生产,那么消费者会吧商品消费完,(20ms之后,商品被消耗完了)此时可以反推生产者的状态.
***********************************************************************/
void UpDateKeyTmr(void)
{

   /*********************生产者,要么生产 商品"1",要么生产商品"0"***************************/    
    /*当前状态为1*/
    if(KEY_HIT)
    {
        /*如果按键释放,走这个分支,每1ms产生20个 商品"1"*/
        ucKeyHitHigtCnt=KEY_DEBOUNCE_CNT;
    }
    /*当前状态为0*/
    else
    {
        /*如果按键按下,走这个分支,每1ms产生20个 商品"0"*/
        ucKeyHitLowCnt=KEY_DEBOUNCE_CNT;
    }

   /*********************商品"0"消费者****************************/         
     /*如果按键按下,商品"0"不会被消费完,因为生产商品"0"的速度远大于消费的速度(按键按下1ms生产20个商品"0",而1ms只消耗1个商品"0")*/
     if(ucKeyHitLowCnt)
     {
          /*每1ms消费一个 商品"0"*/
         ucKeyHitLowCnt--;
         
        /*查看商品"0"是否被消耗完",*/
        if(!ucKeyHitLowCnt)
        {
            /*一段时间后,如果没有生产者(当前端口状态为高)也就是无法产生商品"0",
            那么商品"0"会被消耗完,当商品0为消耗殆尽,那么可以认为按键释放(反推生产者的状态)*/
            ucKeyHitSt=HIGH;

        }
     }
     /*********************商品"1"消费者****************************/    
    /*如果按键状态是1,商品"1"不会被消费完,因为生产商品"1"的速度远大于消费的速度(按键没有按下1ms生产20个商品"1",1ms,只消耗1个商品"1")*/
     if(ucKeyHitHigtCnt)
     {
         /*每1ms消费一个 商品"1";*/
         ucKeyHitHigtCnt--;
         
        /*查看商品"1"是否被消耗完",*/
        if(!ucKeyHitHigtCnt)
        {
            /*一段时间后,如果没有生产者(当前端口状态为低)也就是无法产生商品"1",
            那么商品"1"会被消耗完,当商品1为消耗殆尽,那么可以认为按键按下(反推生产者的状态)*/
            ucKeyHitSt=LOW;
        }
     }
/**************************************************/

}

void UpDateLedSt(void)
{
    /*状态切换*/
    ucSysSt++;
    if(ucSysSt>2)
    {
        ucSysSt=0;
    }
    
    switch(ucSysSt)
    {
        /*开闪烁*/
        case 0:
            usMsFlashTmr=0;
            /*使能闪烁*/
            ubEnLedFlash=1;
            break;

        /*开灯*/
        case 1:
            
            ubEnLedFlash=0;
            /*关灯,关闪烁*/
            GRE_LED_OFF;
            /*关灯*/
            break;

         /*关灯*/
        case 2:
            
            ubEnLedFlash=0;
            /*关灯,关闪烁*/
            GRE_LED_ON;
            /*关灯*/
            break;
            
        default:
        break;
    }
    
}



void GetKeySt(void)
{
   /*按键的历史状态和当前状态不一样,
   说明按键状态有切换*/
   if(ucKeyHitSt!=ucKeyHitBak)
   {
          /*保存当前状态*/
          ucKeyHitBak=ucKeyHitSt;


       /*如果当前按键被按下*/
       if(!ucKeyHitSt)
       {    

             /*更新状态*/
             UpDateLedSt(); 
       }
       else
       {
               /*按键释放*/
           
       }
      
   }

}

/*按键端口状态初始化*/
void KeyAppInit(void)
{
    /*检测端口状态*/
    if(KEY_HIT)
    {
        /*当前状态*/
        ucKeyHitSt=HIGH;
        /*历史状态*/
        ucKeyHitBak=HIGH;
    }
    else
    {
        /*当前状态*/
        ucKeyHitSt=LOW;
        /*历史状态*/
        ucKeyHitBak=LOW;
    }

    /*初始化*/
    ucKeyHitHigtCnt=KEY_DEBOUNCE_CNT;
    ucKeyHitLowCnt=KEY_DEBOUNCE_CNT;
#if 0   
   usKeyHitLoPreCnt=0;
   ucKeyHitPreSt=0;
 #endif 
}


void    FPPA0 (void)
{
    .ADJUST_IC    SYSCLK=IHRC/8, IHRC=16MHz, VDD=3.0V;
    $ CLKMD IHRC/8,En_IHRC,En_ILRC,En_WatchDog;
    .delay 40000;
    
    $  LED_G     OUT,HIGH;          
    $  KEY_HIT     IN,PULL;   
    
    TIME16_Init();
    
    KeyAppInit();

    ubMsFlag=0;
    ubEnLedFlash=0;

    /*状态初始化*/
    ucSysSt=2;
    
    engint;
    while (1)
    {

            wdreset;

         /*1ms定时时间到*/
         if ( FLAG_NMS )
         {
          
           /*按键*/
            UpDateKeyTmr();
            /*点灯*/
            UpdateLedTmr();
        
            /*清除标记*/
            FLAG_NMS=0;
        }
        
        /*按键状态切换*/
        GetKeySt();

        
    }
}

void    Interrupt ( void )
{
    pushaf;

    if ( Intrq.T16 )  
    {

        Intrq.T16    =    0;
        
        STT16 T16COUNTER;

        
        
        if ( count>0 )
        {
            count--;
        }
        else
        {
            count   =   9;
            /*1ms*/
            FLAG_NMS=   1;      
        }

    }

    popaf;
}

/*end create by zhongvv QQ:85547259*/

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值