关于一种新的按键处理的思路,今天和应广的技术支持通了一个电话,讨论到了按键下理的问题,他和我说了有两种按键处理的方法,一种就是我用的那一种,即每10ms判断一次按键的情况,然后oldkey,newkey的方法,他还说了另一种更为简单的办法,当然这个也只能用在最简单的情况,他说每30ms判断一次按键的情况,如果按键是按下的情况那么就执行相应的按键处理程序,仔细分析一下他说的很有道理啊!!!
下面分析一下这种情况的可行性,首先无论是按键按下或是释放的时候都有一个抖动的时间,这个时间一般是10ms左右,首先从逻辑上来分析一下这个问题消抖的目的无非就是将这个不稳定的抖动的状态的多次高低电平的变化,使其只有作用一次低电平(假如这里是低电平有效)的相应的处理,条条大路通罗马,假如一第一个下降沿的时候单片机检测到这个低电平,而后是按键的处理程序,然后是按键处理的失能,想要再次使能按键的作用只有等待按键的再次变为高电平,试想如果这个检测的时间如果太短或太长的话会有什么情况,如果这个时间设置的太短的假如是1ms那么在这个10ms的时间里会他就会检测到10次,现在以最坏的情况一分析的话,如果按照原来的按键处理程序的话,按照最坏的情况就会有5次按键作用的情况,也就是说有5次高电平和5次低电平都被检测到了,有5次的按键使能故能最多作用5次的样子。假如这个时间足够长的话,比如检测一次要1年的时间,那么这其间的按键作用都会丢失掉,这是非常可怕的啊,其实这个时间在逻辑上只能大于10ms就行了,只要这个时间大于1倍的按键抖时间就能保证在这个抖动时间里按键最多只检测两次,而只有在抖动时间里按键的检测次数超过3次才能导致多次触发的情况发生,因为这个抖动的时间一共是20ms这个情况是在最坏的情况下考虑到的最坏的,最坏的情况下没有按键的多次作用那么在其他情况下也就更不会有按键的多次作用了。
下面直接上源代码:
/***************************************************************************************************
函数功能:扫描按键值,交将扫描到的按键触发信息转换成数字赋给Key_num
函数入口:无
函数出口:无
作者 :任丁
***************************************************************************************************/
void KeyScan(void)
{
if(KEY1==0&&KEY2==1&&KEY3==1)
{
key_num=1; //KEY1键按下,返回1
return;
}
elseif(KEY1==1&&KEY2==0&&KEY3==1)
{
key_num=2; //KEY2键按下,返回2
return;
}
elseif(KEY1==1&&KEY2==1&&KEY3==0)
{
key_num=3; //KEY3键按下,返回3
return;
}
elseif(KEY1==1&&KEY2==0&&KEY3==0)
{
key_num=4; //KEY2键和KEY3键同时按下,返回4
return;
}
//这里还可以添加更多的按键,和更多的返回值,霸气不?!?!?!
//这里有一个问题啊,就是这里是三个按键的情况,如果为大于三个按键的情况
//而同时要处理多个按键按下的问题用这种if else if else if …else的形式
//就会有一个严峻的问题,不能很好的区分每一种按键的情况,因为这时会有一个非常复杂的逻辑空间
//区别这每一种按键的
//逻辑条件,如果有更多的按键,那么这种方法肯定是行不通的,但是如果只是最简单
//的情况,也就是只会按下一个键的情况,那样的话问题就会简单很多
//总而言之使用if else if else if else if else的这种结构的关键就在于每一个if 或 else if 语句
//都必顺是不同的情况,如果不是这样的话就会有重和漏掉的情况的发生
//对于多个按键的情况有一个较为聪明的解决的办法,就是把在在每一个if或else if 语句里把每一个按键的情况
//都写清楚,使每一种分支都和别的分支都没有逻辑上的包含的被包含的情况都,从而用这种方法构建的if else if …else
//是一个没有包含和被包含情况的逻辑关系非常清晰的空间,也就是实际上这是一个数学上的一个非常简单的问题
//最终的可能的情况有2的按键次数次方的个数,一个关键的问题就是书写条件时先写if 和 else if 里面的语句而后再
//用一个else语句来把剩下的情况全部概括,其实思路就是抓信己知的情况,从而把未知的情况剩出来。编程时这
//些情况直接用一个else语句来概括,这样的话对于这些没有定义的情况统统返回一个0,在KEY_process()里面这些情况
//全部作为是无效按键的情况,这些情况下的按键触动情况就会直接作为无效按键的情况,KEPY_process()会直接路出
//这些情况从而对于这些情况想当于是没有任何的作用的。只有有作用的按键触发情况才会转而去执行相应的按键处理程序
//特别要注意的一点就是这些有作用的按键触发情况有都是最细小的逻辑体,这样才话能够做到不重不漏,严谨有序
//这一种方法是非常有实践意义和应用价值的
else
{
key_num=0; //如果所有按键都没有按下就返回0或255,这里返回0
return;
}
}
/***************************************************************************************************
函数功能:根据扫描到的不同的按键触发情况,执行相应的按键的处理功能
函数入口:无
函数出口:无
作者 :任丁
***************************************************************************************************/
void KeyProcess(void)
{
if(KeyScan_Flag==1) //按键扫描的时间30ms到了
{
KeyScan_Flag=0;
KeyScan();
if(0<key_num&&key_num<255) //如果有键按下
{
if(key_num==1)
{
if(Key1_EnableFlag==0)
{
//此处添加KEY1按键的处理程序
Key1_EnableFlag=1;
return;
}
}
elseif(key_num==2)
{
if(Key2_EnableFlag==0)
{
//此处添加KEY2按键的处理程序
Key2_EnableFlag=1;
return;
}
}
elseif(key_num==3)
{
if(Key3_EnableFlag==0)
{
//此处添加KEY3按键的处理程序
Key3_EnableFlag=1;
return;
}
}
else
{
return;//实际上不会走到这一条语句,因为return回的有效值为1到255
//除此之外没有其他值,而如果为0或者大于255时,是不会进入这个分支的
//直接在第二层的else语句执行相应的程序
}
}
else //按键无效,即无键按下
{
Key1_EnableFlag=0; //按键使能标志位置0,使能按键作用
Key2_EnableFlag=0; //按键使能标志位置0,使能按键作用
Key3_EnableFlag=0; //按键使能标志位置0,使能按键作用
Key4_EnableFlag=0; //按键使能标志位置0,使能按键作用
return;
}
}
else //按键检测使能标志为0,即没有到达按键检测的时间间隔,这里设置为10ms,不进行按键检测
{
return;
}
}