产品概述

单片机 按键去抖 单片机键盘消抖“独门”汇编方案分享,不用延时还能用什么?

小编 2024-11-24 产品概述 23 0

单片机键盘消抖“独门”汇编方案分享,不用延时还能用什么?

用单片机或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 花的时间根据按键数量的多少而不同,一般为几个微秒到几十微秒)。

单片机学习——按键消抖

简单的说,进入了电子,不管是学纯模拟,还是学单片机,DSP、ARM等处理器,或者是我们的FPGA,一般没有不用到按键的地方。按键:人机交互控制,主要用于对系统的控制,信号的释放等。因此在这里,FPGA上应用的按键消抖动,也不得不讲!

通常的按键所用开关为机械弹性开关。由于机械触电的弹性作用,按键在闭合及断开的瞬间均伴随有一连串的抖动。键抖动会引起一次按键被误读多次。为了确保CPU对键的一次闭合仅作一次处理,必须去除抖动。 消除抖动的方法有硬件和软件两种方法。硬件方法常用RS触发器电路。软件方法是当检测出键闭合后执行一个10ms~20ms的延时程序,再一次检测键的状态,如仍保持闭合状态,则确认真正有键按下。

一、为什么要消抖动

如上图所示,在按键被按下的短暂一瞬间,由于硬件上的抖动,往往会产生几毫秒的抖动,在这时候若采集信号,势必导致误操作,甚至系统崩溃;同样,在释放按键的那一刻,硬件上会相应的产生抖动,会产生同样的后果。因此,在模拟或者数字电路中,我们要避免在最不稳定的时候采集信号,进行操作。

对此一般产用消抖动的原理。一般可分为以下几种:

(1)延时

(2)N次低电平计数

(3)低通滤波

在数字电路中,一般产用(1)(2)种方法。后文中将详细介绍。

二、各种消抖动

1. 模拟电路按键消抖动

对于模拟电路中,一般消抖动用的是电容消抖动或者施密特触发等电路,再次不做具体介绍。

2. 单片机中按键消抖动

对于单片机中的按键消抖动,本节Bingo根据自己当年写过的单片机其中的一个代码来讲解,代码如下所示:

unsigned char key_sCAN(void)

{

if(key == 0) //检测到被按下

{

delay(5); //延时5ms,消抖

if(key != 0)

retrurn 0; //是抖动,返回退出

while(!key1); // 确认被按下,等下释放

delay(5); //延时5ms,消抖

while(!key1); //确认被释放

return 1; //返回按下信号

}

return 0; //没信号

}

针对以上代码,消抖动的顺序如下所示:

(1)检测到信号

(2)延时5ms,消抖动

(3)继续检测信号,确认是否被按下

a) 是,则开始等待释放

b) 否,则返回0,退出

(4)延时5ms,消抖动

(5)确认,返回按下信号,退出

当然在单片机中也可以循环计数来确认是否被按下。

相关问答

51 单片机 ,用 按键 实现外部中断,软件如何 去抖 ?

定时中断里设置一个记录按下时间的static变量t按下按键则将t++(注意不要加到溢出)松开按键,检测tt定时中断里设置一个记录按下时间的static变量t按下...

在做 单片机 按钮控制流水灯,我想达到按一下自己循环,再按一下...

#include"reg52.h"#defineuintunsignedint#defineucharunsignedcharsbitK1=P3^2;//独立...

51 单片机按键 释放时候为什么不用消 ?

释放就释放了,程序只管往下走,抖动又有什么关系由于按键按下有消抖,所以按键释放的抖动绝对不会又被当作按键按下的信号按键按实了,就不会抖动既然检测...

单片机 控制机械臂如何消除 动?

你是要对控制按键消抖吗?那就用延时子程序吧.如果是想消除机械臂的抖动,用液压和三角形结构吧你是要对控制按键消抖吗?那就用延时子程序吧.如果是想消除机械...

单片机 用的无线遥控器按一下相当桉几下怎么像 按键 一样消 ?

按键前,后都会有抖动,所以前后都要加延时效果会好一些,还有一种可能是芯片速度快,导致多次识别按键,你可以在识别一次后加一个标志位按键前,后都会有抖动,所...

按键 接在 单片机 的T0T1口,需要软件消 吗?

在中断中加延时:前消抖:进入时加延时,20um以上低电平时原地跳转:while(!P3_0);直到接收到高电平才往下走;后消抖:再加20um以上延时,作为后消抖在中断中加...

单片机 程序:用一个开关按钮控制一个灯,按钮在上面灯恒亮(高...

一是第一次检测到按键按下后加延时,二是等待按键抬起,用while(!key1&&key2…);后面的switch(key)和P2=…不要放在等待按键抬起过程之中这和只有一个按键...

单片机按键 动延时多长才合适?

单片机按键防抖动延时的合适时间应该根据具体的硬件实际情况来确定。通常情况下,建议设置为10-20ms左右。这个时间足够长,可以保证按键防抖效果好,避免误操作...

51 单片机 ,用一个 按键 来关闭和打开定时器t0,用作暂停。定时时...

既然用一个按键来关闭和打开定时器t0,说明你设计按键是按一次打开、再按一次关闭。是不是按键消抖程序没写好,导致你按一次键实际上是等同按了多次...

51 单片机 菜单式 按键 原理?

一般情况下,独立按键有两个引脚,其中一个通过上拉电阻接到单片机的I/O端口,另外一端接地。也就是说,平时按键没有动作的时候,输出的是高电平,如果有按下动...

猜你喜欢