按键状态机由五个状态组成,等待按下、延时确认1、延时确认2、等待释放、已经释放,每隔10ms读取一次按键的状态,驱动状态机转入新的状态。采用状态机可以很清晰地体现按键处理的思路,并且较好的抗干扰。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
这个程序主要是处理按键和连击的,在等待按下状态时,如果检测到低电平,转入延时确认1状态,再等10ms,如果又检测到低电平,则真的有键按下,把按键信息送到消息队列。如果在确认阶段检测到高电平,则判定为干扰,返回到等待按键状态。
在等待释放阶段,如果检测到低电平,且长按键标志没有置位,则进行时间累计,若按下时间超过连击等待时间,则置位长按键标识;若长按键标志下,每次累计一个小的时间,就发送一个有效按键信息,这就是所谓的连击。
void Task_FiveOK(void *pdata)
{
u8 FiveOKState;
KeyStateMachine KeySM="WaitForPress";
pdata=pdata;
for(;;)
{
OSTimeDly(1); //延时10ms,利用ucos实现。每隔10ms进行一次检测
FiveOKState=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15);//读取PB15的状态,OK健
switch(KeySM) //根据此时状态机的状态做出不同反应
{
case WaitForPress: //等待按键状态
if(FiveOKState==0) //如果检测到低电平,转入延时确认1状态
{KeySM=KeyVerify1;
}
break;
case KeyVerify1: //在确认1状态,如果是低电平,转入确认2状态
if(FiveOKState==0)
{KeySM=KeyVerify2;
}
else
{KeySM=WaitForPress; //如果是高电平,则为干扰,回到按键等待状态。
}
break;
case KeyVerify2: //在确认2状态如果是低电平,则真的被按下了。
if(FiveOKState==0)
{KeySM=WaitForRelease; //转入释放等待阶段。
Key[KeyNum]=KeyOK;//将按键信息送入消息队列
OSQPost(KeyOSQ,&Key[KeyNum]);
KeyNum++;
}
else
{KeySM=WaitForPress;
}
break;
case WaitForRelease:
if(FiveOKState==0) //在等待释放阶段,如果检测到0。就进行按下时间计时。
{KeySM=WaitForRelease;
PressTimeCount++;
if(!LongPress) //如果长按键标识没有置位,则累加。
{
if(PressTimeCount==150) //累加到1.5s后,长按键标识置位
{LongPress=1;
PressTimeCount=0;
}
}
Else //长按键标识置位后
{
if(PressTimeCount==10) 每隔0.1s就发送一次按键信息。
{Key[KeyNum]=KeyOK;
OSQPost(KeyOSQ,&Key[KeyNum]);
KeyNum++;
PressTimeCount=0;
}
}
}
else
{
LongPress=0;
PressTimeCount=0;
KeySM=WaitForPress;
}
break;
default:
break;
}
}
}
用户607758 2012-7-7 19:15