单片机
返回首页

51单片机识别四个独立按键是短按还是长按

2014-01-13 来源:dqjsw

这是一个可以识别四个独立按键是短按还是长按的参考程序,此程序已编译通过,初学者可以移植到51单片机上试试.
/********************************************/
//FileName:识别四个独立按键是短按还是长按
//Function: 不同按键 短按或长按分别显示不同的LED
//author:liu yong
//QQ:545018331
//Date:2013/03/13
/********************************************/        
#include
__CONFIG(0X3B31);
#define uint8 unsigned char
unsigned int time_10ms_ok=0;
uint8 KeyValue;
bit KeyShortpressFlag,KeyLongpressFlag;
//=========定义长按键断口的TICK数及连发间隔的TICK数=======//
#define KEY_LONG_PERIOD  200
//=========定义按键断口=======//
#define io_key_1  RB0
#define io_key_2  RB1
#define io_key_3  RB2
#define io_key_4  RB3
//=========定义按键键值=======//
#define KEY_VALUE_1 0X0e
#define KEY_VALUE_2 0X0d
#define KEY_VALUE_3 0X0b
#define KEY_VALUE_4 0X07
#define KEY_NULL    0X0f

//=========定义按键返回值状态(按下,长按,连发,释放)=======//
#define KEY_SHORT    0X80
#define KEY_LONG     0X40

//=========定义按键状态=======//
#define KEY_STATE_INIT       0
#define KEY_STATE_WOBBLE     1
#define KEY_STATE_PRESS      2
#define KEY_STATE_LONG       3
#define KEY_STATE_RELEASE    4

void initial(void)
{
      TRISB=0xff;
      TRISC=0;
      PORTC=0XFF;
      RBPU=0;
      T1CON=0X01;//1:1
      TMR1H=-(10000 >> 8);
      TMR1L=-(10000 & 0XFF);
      TMR1IF=0;
      TMR1IE=1;
      INTCON=0XC0;
}
void interrupt  timer1_isr(void)       // 定时器10ms中断服务
{
       if(TMR1IF)
        {
           TMR1H=-(10000 >> 8);
           TMR1L=-(10000 & 0XFF);
           time_10ms_ok = 1;
           TMR1IF=0;
        }
}

void KeyInit(void)
{
     io_key_1 = 1;
     io_key_2 = 1;
     io_key_3 = 1;
     io_key_4 = 1;
}
uint8 KeyScan(void)
{
      if(io_key_1 == 0)return KEY_VALUE_1;
      if(io_key_2 == 0)return KEY_VALUE_2;
      if(io_key_3 == 0)return KEY_VALUE_3;
      if(io_key_4 == 0)return KEY_VALUE_4;
      return KEY_NULL;
}
uint8 GetKey(void)
{
      static uint8 s_u8KeyState = KEY_STATE_INIT ;
      static uint8 s_u8KeyTimeCount = 0;
      uint8 i ;
      uint8 KeyTemp=KEY_NULL;
      KeyTemp = KeyScan();//0x0e 0f
      switch(s_u8KeyState)
      {
        case KEY_STATE_INIT:
              {
                if(KEY_NULL != KeyTemp)
                 {
                   s_u8KeyState = KEY_STATE_WOBBLE ;
                 }
              }
        break;
 
        case KEY_STATE_WOBBLE:
              {
                 s_u8KeyState = KEY_STATE_PRESS ;
              }
        break;
        case KEY_STATE_PRESS://识别哪个键
              {
                if(KEY_NULL != KeyTemp) // KeyTemp=0x0e  short press
                 {
                   s_u8KeyState = KEY_STATE_LONG ;
                   i=KeyTemp;//0x0e
                 }
                else
                 {
                   s_u8KeyState = KEY_STATE_INIT;
                 }
              }
        break;
        case KEY_STATE_LONG:  //判断按键是短按还是长按
              {
                if(KEY_NULL != KeyTemp)
                 {
                   if(++s_u8KeyTimeCount > KEY_LONG_PERIOD)
                    {
                      s_u8KeyTimeCount = 0;
                      KeyLongpressFlag=1;
                      KeyShortpressFlag=0; 
                      s_u8KeyState = KEY_STATE_RELEASE;
                    }
                 }
                else
                 { 
                      s_u8KeyTimeCount = 0; 
                      KeyShortpressFlag=1;
                      KeyLongpressFlag=0;
                      s_u8KeyState = KEY_STATE_RELEASE;
                 }
              }
        break;
       case KEY_STATE_RELEASE://按键释放去抖
              {
                if(KEY_NULL == KeyTemp)  //此语句必须加上去不然程序不稳定
                {
                 if(KeyShortpressFlag)
                 {
                     KeyShortpressFlag=0;
                     i=i | KEY_SHORT;//0x0e | 0x80=0x8e
                     s_u8KeyState = KEY_STATE_INIT;
                 }
                if(KeyLongpressFlag)
                 {
                     KeyLongpressFlag=0;
                     i=i | KEY_LONG;
                     s_u8KeyState = KEY_STATE_INIT;
                 }
               }
             }
        break;
        default:break;
      }
     return i; 
}

void main(void)
{
     initial();
     KeyInit();
     while(1)
     {
      if (time_10ms_ok)            //每10ms执行一次, 
        { 
             time_10ms_ok =0;
             KeyValue=GetKey();
             if(KeyValue == (KEY_VALUE_1 | KEY_SHORT))     PORTC = ~1;
             if(KeyValue == (KEY_VALUE_1 | KEY_LONG))       PORTC = ~3;
             if(KeyValue == (KEY_VALUE_2 | KEY_SHORT))     PORTC = ~7;
             if(KeyValue == (KEY_VALUE_2 | KEY_LONG))       PORTC = ~0X0F;
             if(KeyValue == (KEY_VALUE_3 | KEY_SHORT))     PORTC = ~0X1F;
             if(KeyValue == (KEY_VALUE_3 | KEY_LONG))      PORTC = ~0X3F;
             if(KeyValue == (KEY_VALUE_4 | KEY_SHORT))     PORTC = ~0X7F;
             if(KeyValue == (KEY_VALUE_4 | KEY_LONG))      PORTC = ~0XFF;  
        }
     }
}
进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

最新器件
精选电路图
  • CCD图像传感器在微光电视系统中的应用

  • 光控音效发生器电路

  • 非常简单的150W功放电路图

  • 分享一个电网倾角计电路

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章