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