单片机按键识别篇---单击---双击----长按

  最近做一任务需要使用一个按键实现三种功能,分别是按键单击功能,按键双击功能和按键长按功能,可能之前没有接触过这类按键复用情况,顶多也只是简单识别单击和长按,没有想过双击以上按键功能,也是绞尽脑汁,想了半天,又上网看了些例程,算是对于按键的识别有点小小的了解,感觉这个功能挺实用,在此做个随笔。

一、思路

  1.识别长按操作思路:我们使用系统定时器定时,然后让系统每过一段时间去扫描按键I/O口状态,当扫描到按键按下I/O口状态超过设定长按时间的阀值,就判定这次按键操作为“长按”操作;

  2.识别单击操作思路:当系统扫描按键按下的I/O口时间小于我们设定的长按阀值,这时就可能出现两种情况,情况1.可能是单击;情况2.可能是双击;首先我们来说情况1,单击操作,这时我们可以检测按键按下后,按键弹起的时间到下次按键按下的时间间隔,当按键按下弹起到下次按键按下的时间超过某个值,则我们判定这次操作为“单击”操作;

  3.识别双击操作思路:上面刚说的情况1,这次来说情况2,:双击操作,当我们检测按键按弹起后在一定时间阀值内,又检测到按键I/O口有电平变化,则我们判断这次操作为“双击”操作

二、程序部分

unsigned char scan_key()  
{
/*
值key_return如下:
          1---------单击
          2---------双击
          3---------长按
*/
static unsigned char key_state=0;                           //按键状态
static unsigned char state=0;
static unsigned char time,time1,time2;    
static unsigned char key_up_flag=0;                           //按键弹起标志位
static unsigned char key_return;


  if(Key==0)                                                 //按键按下消抖
  { 
    delay(50);
     if(Key==0)
     { 
       key_state=0;
     } 
   }  
  else 
  {
    delay(50);                                                //按键松开消抖
    if(Key==1)
    {
     key_state=1;
     key_up_flag=0;
    }
  }
   if((state==0)&&(key_state==0)&&(key_up_flag==0))        //这里主要防止,按键在识别长按后,又会执行一遍单击操作                               
    {
             state=1;
             time=key_time;                                       //记录按键按下的时间为多少,做标记
    }
     if(state==1)
     {
          time1=key_time;
          time2=time1-time;                                 //计算按键按下时长
                
           if(time2>50)                                    //长按判断
             {
              state=2;
            } 
         if(key_state==1)                                //按键弹起
           {
              state=3;
              time=key_time;                                  //标志什么时间按键弹起的
           }
     }
     if(state==2)                                         //长按
      {
            state=0;                                     //重置状态
            key_up_flag=1;
            key_return=3;
      }
         if((state==3)&&(key_up_flag==0))
          {
               time1=key_time;
               time2=time1-time;                          //计算按键弹起后时间
                if(time2>6)                                //判断按键弹起后的时间,超过300ms,则说明为单击
                    {
                      state=0;
                    key_return=1;
                  }    
              else    if(key_state==0)                     //按键弹起后,300ms内又有按键按下
                 {
                      state=4;
                 }
           }
           if(state==4)
          {
                  if(key_state==1)                        //按键弹起
                  {
                     state=0;
                    key_return=2;
                   }
          }
          
     return key_return;          
}

void timer0() interrupt 1     //定时器T0中断函数入口
{
     TH0=0X9E;             //初值重载
     TL0=0X57;           //定时50ms=50000us; 50000/2=25000
     key_time++;        //50MS++

  
}

 

posted @ 2018-09-19 12:12  一切都会好  阅读(17126)  评论(3编辑  收藏  举报