当前位置:首页 > 单片机 > 单片机
[导读]用单片机或ARM做的产品经常会遇到有键盘输入的产品,而键盘输入有一个绕不过去的问题就是:键盘去抖。见下图当按键开关闭合或者断开时各有一段电平不稳定的时期,按键开关在闭合时不会马上就稳定的接通,在断开时也不

用单片机或ARM做的产品经常会遇到有键盘输入的产品,而键盘输入有一个绕不过去的问题就是:键盘去抖。见下图

当按键开关闭合或者断开时各有一段电平不稳定的时期,按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的电平抖动。这种抖动一般都在10ms左右。为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的去抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。

按键去抖方法可分为硬件去抖和软件去抖,硬件去抖不在本文的讨论中,本文只讨论软件去抖。

一般的软件去抖就是程序在检测到按键闭合或断开时调用一段延时子程序(在C语言中叫函数),程序在此死等10ms或更长。延时过后再检测按键的状态是否与延时前的状态一致,若一致就执行键盘程序部分,若不一致,则跳过执行键盘程序。

这种方法在程序工作量不是很大时是没有问题的。但在一些CPU负荷量比较大的程序中,特别是在一些程序运转中有比较多的在不确定时间就会发生的中断的情况下(外部中断、串口中断、定时器中断等),在这里死等,就有可能造成某部分程序不能很好地被执行,甚至程序跑飞等严重问题。

本人经过多年的编程,总结了一套解决这问题的方法,供大家参考。

程序是用51汇编语言写的,大家若要用C语言编写,参考这流程图改一下就成。

先解释这流程图中的变量和子程序:

KSTEP:步进指示变量,当程序从主程序进入到此子程序后,立刻根据这KSTEP的值跳到相应的程序段。

KEYSCAN:读键盘子程序,若你的按键数量不多的话,直接读IO口。按键数量多的话,就要用矩阵方式读键盘,这里不作赘述。

HASK:位变量,读键盘子程序中的位变量,当读键盘子程序KEYSCAN检测到有键闭合时置“1”,反之置“0”。

R2:键值变量,读键盘子程序KEYSCAN读出的键值。

KVALU:键值变量,R2的键值送到这里,供此子程序下一次判断或主程序使用。

K20MS:20ms计时器变量,当第一次检测到有键闭合时往里面送值10。程序初始化中设定定时器中断为2ms时间间隔。进入定时器中断后,首先判断K20MS是否为0?若为0则直接退出定时器中断;若不为0则将K20MS减1后再退出定时器中断。这样K20MS变量从10减到0时间为20ms。键断开时也是一样地执行。

KAVA:位变量,告诉主程序:键闭合(断开)有效。

程序解释:

1.程序初始化时KSTEP的值为0,所以一进入本子程序,程序马上就跳到标号KSC0处,在此处调用读键盘子程序KEYSCAN。

1.1从KEYSCAN出来后,若位变量HASK的值为0,说明没有键闭合,程序直接跳到标号RET处退出。

1.2若位变量HASK的值为1,就是有键闭合,此时将数值1送入步进指示变量KSTEP中,便于下次进入本子程序时,程序直接跳到标号KSC1处。再将从KEYSCAN子程序读出来的键值送入变量KVALU中,用于下次再调用读键盘子程序KEYSCAN时与R2读出的键值进行比较。

最后将数值10送入20ms计时器变量K20MS中,用于2ms定时器中断后减1,然后退出子程序。

2.当主程序再次调用本子程序时,程序马上就跳到标号KSC1处。

2.1在此处首先判别20ms计时器变量K20MS是否减到0(也就是判别20ms延时到了没有?),若K20MS不为0(20ms延时还没有到),则立即退出。

2.2若K20MS为0(说明20ms延时时间到了),再次调用读键盘子程序KEYSCAN。调用KEYSCAN子程序后,再次判别位变量HASK是否有效?

2.2.1若HASK无效,说明上次(KSC0处)可能是受到一次干扰。于是复位KSTEP(清0),退出。使下次调用本程序时,又从头开始。

2.2.2若HASK有效,则将这次从KEYSCAN读出的键值与上次读出并存在KVALU中的键值进行比较。

2.2.2.1若比较值不同,则程序跳到标号KE1处,将新的键值存入KAVALU中,20ms后再调用KEYSCAN子程序,再次比较。

2.2.2.2若比较值相同,则说明本次键闭合有效,于是置位KAVA(当主程序是键按下执行时),告诉主程序,键闭合有效,可以执行此键所要做的程序了。同时将数值2送入步进指示变量KSTEP中,便于下次进入本子程序时,程序直接跳到标号KSC2处。最后将数值10送入20ms计时器变量K20MS中,在下次进入KSC2标号处,也得等20ms之后再判别键是否断开。

3.现在主程序调用本子程序时,程序马上就跳到标号KSC2处,在此也一样,首先判别20ms计时器变量K20MS是否减到0(也就是判别20ms延时到了没有?),若K20MS不为0(20ms延时还没有到),则立即退出。若K20MS为0,调用读键盘子程序KEYSCAN。

调用KEYSCAN子程序后,判别位变量HASK是否有效?

3.1若HASK无效,说明按键可能被释放断开,于是将数值3送入步进指示变量KSTEP中,便于下次进入本子程序时程序可以直接跳到标号KSC3处。最后将数值10送入20ms计时器变量K20MS中,在下次进入KSC3标号处,也得等20ms之后再判别键是否继续断开状态。

3.2若HASK有效,说明按键继续闭合状态,再比较KEYSCAN读出的键值与上次读出在KVALU中的键值进行比较。

3.2.1若比较值不同,则程序跳到标号KE0处,重新开始。

3.2.1若比较值相同,则说明按键还没有断开,继续将数值10送入20ms计时器变量K20MS中,等20ms之后再进入标号KSC2处,再次判别按键是否断开。

4.当主程序调用本子程序时,程序程序马上跳到标号KSC3处,还是首先判别20ms计时器变量K20MS是否减到0,若K20MS不为0(20ms延时还没有到),则立即退出。若K20MS为0,调用读键盘子程序KEYSCAN。

调用KEYSCAN子程序后,判别位变量HASK是否有效?

4.1若HASK无效,说明按键已经完全释放断开,于是将数值0送入步进指示变量KSTEP中,便于下次进入本子程序时,程序从头开始,同时置位KAVA(当主程序是键释放执行时),告诉主程序,键释放有效,可以执行此键所要做的程序了。

4.2如果位变量HASK继续有效,说明又有键闭合了(虽然这种概率比较小,但程序得编进去),根据新键值与老键值的相同与不同,分别跳到标号KE3处,或者标号KE0处执行。

说明:KE3标号和KE7标号下面都有SETBKAVA,实际编程时只用一次,根据你的主程序是在键按下执行还是键释放执行选用。

本程序的特点就是:在等键闭合或断开去抖的那20ms时间,不是死等,而是做好标记及置好必要的变量值后立即退出到主程序去做其他事情。程序每次从进入到退出这个子程序中所花的时间一般为十几微秒(不含读键盘子程序KEYSCAN所花的时间,KEYSCAN花的时间根据按键数量的多少而不同,一般为几个微秒到几十微秒)。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭