两种基于电平计时的按键检测方法
2017-09-29刘宸
刘 宸
(四川职业技术学院电子电气工程系,四川 遂宁 629000)
两种基于电平计时的按键检测方法
刘 宸
(四川职业技术学院电子电气工程系,四川 遂宁 629000)
在电子设备中,按键是较常用的输入设备之一,机械式按键在按下和释放时在一定时间内会产生机械抖动,使得输出电平不稳定,从而会导致程序的错误动作.为了消除抖动,通常使用软件消抖.本文以几种按键检测程序对比它们的特点及应用场合,总结出一种对电平计时的程序算法是更具通用性、效率更高和多任务实时响应更优的方法.
按键;程序;消抖
许多电子设备键盘常使用机械触点式按键开关,其主要功能是把机械上的通断转换成为电气上的逻辑关系.机械式按键在按下和释放时,由于机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才能稳定下来.这种机械抖动会使输出电平不稳定,如图1所示.抖动时间的长短与按键的机械特性和按键力度有关,一般为5~10 ms.按下按键的闭合稳定时间通常大于100 ms.
图1 按键触点的机械抖动示意
输出电平的不稳定,可能导致程序误判.即按键一次按下或释放被错误地认为是多次操作,这种情况是不允许出现的.为了克服按键触点机械抖动所致的检测误判,必须采取消抖措施.消除电平抖动可从硬件电路或软件控制两方面实现.在键数较少时,可采用硬件消抖,让程序控制十分简单,如单次脉冲发生电路.当按键数量较多时,通常采用软件消抖来达到同样可靠的效果,成本低廉.对应的有多种按键检测程序,本文接下来对比它们的优缺点及应用场合,探寻最优的解决方案.本文示例程序用C 51语言编写来说明算法,其他单片机开发环境均可参照此算法来实现.
1 方案分析
1.1 传统按键检测方法
传统按键检测程序如图2所示,是一种简单的软件消抖流程.首先检测按键是否按下,如果没有按键按下,则跳过这段程序.如果有键按下,通过调用10 ms延时函数,使按键可能抖动的时间不做任何操作,待按键电平稳定后,再次判断键是否按下.如果第二次判断时,按键是按下状态,就表示有键可靠地按下,否则表示第一次检测到的是干扰信号或者为按键释放时的抖动.如果第二次判断时,没有按键按下,就应该跳过执行按键功能程序.
在确定有键按下的情况下,根据按键的功能,执行相应的按键处理程序.为了确保每次按键按下时仅做一次操作,还要等待按键松开,也就是要再进行按键检测,有键按下则表示按键未松开,需要继续循环检测,直到按键松开为止,结束按键的处理.
图2传统检测按键流程图
图2 对应的程序段如下所示.
void inkey()
{ uchar i;
uchark;//存储键值的临时变量
k=P1IN&0xC0;//读键盘端口
if(k!=0xC0)//第一次判断是否按下键
{//如果按下键,则要进一步判断和处理
delay10ms();//调用延时函数,使按键抖动时间过去
if(k==(P1IN&0xC0))//与第一次检测相同,则表示有键稳定按下
{key act(k);//执行按键功能
while(k==(P1IN&0xC0));//键未松开,继续循环检测
}}
这段程序能够较好地实现按键消抖,如果系统为“按键”+“数码管静态显示”或“按键”+“LCD 显示”,使用这样的检测方法是可以的.但在等待按键松开时和消抖延时内,程序是停在这的,不能处理其他实时任务,如动态显示、传感器检测等.即便可以利用中断系统处理其他实时任务,而让主程序来检测按键,那么会无法进入休眠模式,导致功耗太高.当然,也可把这段按键检测放在中断里,那么由于中断优先级的问题,也会因程序停在这里导致无法运行其他任务.
1.2 对电平计时的按键检测方法
传统方法的按键检测与其它实时任务的运行存在矛盾,有诸多弊端,本文提出的对电平计时的按键检测方法可以解决这些问题. 程序流程图如图3所示,每隔几个ms读取一次按键值,可以放在主函数如图3(a),也可放在定时中断函数里,只要间隔时间是几个ms左右,目的是在时间上抽样检测引脚电平.
读取键值的方法如图3(b),读取端口数据,判断有无按键,有键按下时出现低电平则计时+1,由于是间隔时间抽样检测按键,这个统计的计时值就能表征低电平保持的时间. 若连续多次都检测到低电平,则表示已经度过抖动时间,稳定按住按键.将按住按键20 ms时视为短按有效,若间隔时间是2 ms,则计时值则为10次,当计时值达到10时满足短按条件,就可返回键值,执行相应按键功能.当计时值达到500,即按住了500*2 ms=1 s,视为长按,此时将计时值回拨到400,并返回键值执行相应功能.当继续长按住按键,计时值从400增大到500时,再次满足长按条件,但触发的周期只有(500-400)*2 ms=200 ms,即长按1秒后每隔0.2秒就执行一次,实现了电视遥控器上的连加连减的效果.返回键值的时间点只有10(短按)和500(长按),太小的是按键抖动时期,其他次数都不满足按键条件,都返回按键无效的键值.当释放按键或抖动时,计时值清0,让计时值构成一个循环.整个检测按键的程序里没有延时和等待,因此程序不会停留在这里,方便进行其它任务的处理.
图3 对电平计时的按键检测方法
读取按键值的程序如下:
uchar in key() //读键盘
{ uchark;
staticuint cnt=0;//计时值,用静态变量存储以保存上次的值
k=P 3;
if(k!=0 x f f)//按键
{
cnt++; // 按间隔时间对低电平计数if (cnt==10) {return k;} //10*2ms=20ms 已经按住
else if(cnt〉500)//500*2ms=1s 长按
{cnt=400;return k;}// 实现长按累加else return 0xff; // 其他次数,不满足条件
}
else {cnt=0;return 0xff;}// 没按键时,cnt 清0
}
1.3 进一步改进的按键检测方法
上述对电平计时的按键检测方法能实现长按累加,但是不能区分短按和长按的键值,那么按键的功能是相同的,通过更改长按的键值也可实现短按和长按的不同功能,但是由于计时值从0逐渐增加到10再到500,长按的过程中经过短按的计时值,会造成执行长按功能之前必定执行一次短按的功能.在需要严格区分短按和长按功能的应用场合,这是不允许的,因此可进一步改进.方法是:长按是按住不放的,应在按键时判断,而短按的识别应放在释放按键时判断,这样就保证了执行长按功能前不会执行短按功能.
uchar inkey() // 读键盘
{ uchar k;
static uint cnt=0,last_k;
k=P3;
if(k!=0xff)// 按键
{ last_k=k;// 保存上次按下的键值
cnt++;
if(cnt〉230) return 0x99;// 长按执行不同功能
else return 0xff;
}
else//释放时判断短按
{ if (10〈cnt&&cnt〈200)k=last_k;
//10〈cnt〈200,视为短按
elsek=0xff;
cnt=0;returnk;//没按键时,cnt清0
}
}
2 测试结果
经过仿真实验和真实硬件电路的反复测试,实验结果证明本文提出的对电平计时的按键检测方法既能够可靠地消除前沿和后沿抖动,又能够保证程序顺畅地运行多任务.而改进的按键检测方法在此基础上更进一步能严格区分短按和长按的功能.显示出这两种方法的优越性.
3 结语
综上,传统方法的按键检测与其它实时任务的运行存在诸多矛盾和弊端,如无法进入休眠模式,或放在中断里,由于中断优先级的问题,也会因程序停留导致无法运行其他任务.本文提出的对电平计时的按键检测方法可以解决这些问题,但是不能区分短按和长按的功能,进一步改进为按住时判断长按,释放时判断短按,从而实现执行长按功能前不会执行短按功能,保证了短按和长按功能的严格区分,是通用性和效率更高的方法.
[1]成友才.单片机应用技术[M].成都:西南交通大学出版社,2014.
[2]施保华.M S P 430单片机入门与提高:全国大学生电子设计竞赛实训教程[M].武汉:华中科技大学出版社,2013.
责任编辑:张隆辉
T N 871
A
1672-2094(2017)04-0151-03
2017-05-14
刘 宸(1982-),男,四川射洪人,四川职业技术学院讲师,硕士.研究方向:应用电子技术.