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++
}
离线
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;
}
}
}
...
}
离线