您尚未登录。

楼主 # 2021-06-26 12:49:27

cube
会员
注册时间: 2021-03-11
已发帖子: 288
积分: 202.5

单片机按键识别篇---单击---双击----长按 (转载)

https://www.cnblogs.com/UPUPDay2152/p/9673886.html

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

一、思路

  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++

  
}

离线

楼主 #1 2021-06-26 13:00:51

cube
会员
注册时间: 2021-03-11
已发帖子: 288
积分: 202.5

Re: 单片机按键识别篇---单击---双击----长按 (转载)

https://blog.csdn.net/qq_28877125/article/details/85158323

key_state_t key_state = {
	.key_time      = 0,
	.current_state = RELEASE,
	.state         = NO_PRESS,
};

// 1ms 定时器中断服务函数
void Timer0_IRQ_Handler(void)
{
	...

	if(key_state.current_state == RELEASE)          
	{  
		if(KEY_PIN == 0)  // 按键被按下
	    {  
	        key_state.current_state = MAY_PRESS;  
	        key_state.key_time = 0; 
	    }  
	}  
	else if(key_state.current_state == MAY_PRESS)  
	{  
		key_state.key_time++; // 累加每次为1ms
		
		if(KEY_PIN == 1)  // 按键释放
		{  
			// 由释放时的时间长短区分出长按与短按
			if((key_state.key_time > 10)&&(key_state.key_time < SHORTPRESS_THRESHOLD))
			{  
				key_state.state = SHORT_PRESS;  // 按下时间为:10ms~1500ms 判定为短按
				key_state.current_state = RELEASE;  
			}  
			else if(key_state.key_time > SHORTPRESS_THRESHOLD)  
			{  
				key_state.state = LONG_PRESS;  // 按下时间超过1500ms判定为长按
				key_state.current_state = RELEASE;  
			}  
			else // 按下时间小于10ms就释放视为杂波
			{
				key_state.current_state = RELEASE; 
			} 	  
		}  
	}
	...
}

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn