单片机一个按键的多次击键组合判别技巧
基于单片机的快速按键识别方法

基于单片机的快速按键识别方法基于单片机的快速按键识别方法快速按键识别技术是信息处理方面的一个重要领域,应用于各种设备与系统。
在现代电子产品中,按键控制是常用的操作方式之一。
而基于单片机的快速按键识别方法,是目前较为常见的实现方式之一。
一、快速按键识别原理快速按键识别是通过按键接通时,产生的电信号来判断你所按的按键类型及次数,进而执行对应的操作。
单片机通过外部中断或定时器来进行按键事件的处理和识别,实现快速的数据处理与反馈。
二、快速按键识别系统设计1.硬件设计硬件设计主要包括单片机、键盘、蜂鸣器和LED等模块。
其中,单片机为整个系统的核心部件,键盘是输入信号的来源,蜂鸣器是输出信号的反馈,LED则为系统的指示灯。
2.软件设计软件设计则需要通过编程实现按键事件的处理、识别及反馈,其中主要包括定时器、外部中断、键盘扫描和矩阵按键扫描等方式。
三、快速按键识别方法1.定时器扫描法通过定时器来设定扫描周期,通过中断来响应按下事件,实现按键的检测。
相比其他方法,定时器扫描法的扫描速度较快,适用于对响应速度有要求的场合。
2.(硬件)按键编码法每个按键使用一个编码计数器的,通过单片机译码器来解码,实现按键的响应。
这种方法根据不同的按键引脚电平来区分每个按键,适合于按键比较多的场合。
3.矩阵按键扫描法矩阵扫描是常用的键盘扫描方法,遵循矩阵思想,通过行列交叉检测来检测按键的按下,比较简单可靠,适合于按键数量较多的场合。
四、总结基于单片机的快速按键识别方法应用广泛,可以有效提高按键的响应速度和灵敏度,实现更加智能化的操作。
实现这种技术需要考虑系统的硬件和软件设计,但是相比其他识别方式,它更加高效和快速,更容易向各个方向进行扩展。
单片机按键单击双击长按功能实现

单片机按键单击双击长按功能实现在很多嵌入式系统中,都需要对按键进行检测和处理,以实现不同的功能。
常见的按键功能包括单击、双击和长按。
在这篇文章中,我们将介绍如何使用单片机实现这些按键功能。
首先,我们需要连接一个按键到单片机的I/O口。
按键通常是一个开关,有两个接触点。
当按键按下时,两个接触点会闭合,导致I/O口的电平发生变化。
我们可以利用这个变化来检测按键的状态。
为了实现按键功能,我们需要编写一段程序来监测按键的状态。
以下是一个简单的流程:1.初始化I/O口:将按键连接到I/O口上,并将I/O口设置为输入模式。
2.监测按键状态:定时读取I/O口的电平状态,以检测按键是否按下。
如果I/O口电平发生变化,则按键被按下或松开。
3.单击功能:当按键被按下时,记录当前时间,并等待一段时间,如果超过这段时间,说明按键已松开,则触发单击功能。
4.双击功能:如果在两次按键之间的时间间隔内再次检测到按键按下,则触发双击功能。
5.长按功能:当按键被按下一段较长的时间后,触发长按功能。
下面我们来具体介绍如何实现这些功能。
首先,我们需要初始化单片机的I/O口。
这个过程可以通过配置相应的寄存器实现。
具体的方法和步骤依赖于你使用的单片机型号和开发环境。
在这里,我们不具体展开,而是假设我们已经成功初始化了I/O口。
接下来,我们需要设置一个计时器用于定时检测按键的状态。
计时器的定时周期决定了我们可以检测的最短按键时间间隔。
通常,我们使用一个定时器来实现单击和双击功能,使用另一个定时器来检测长按功能。
一旦我们完成了计时器的配置,我们就可以开启定时器中断,并启动计时器。
每当定时器溢出时,中断函数会被触发,我们可以在这个函数中检测按键的状态。
在中断函数中,我们读取I/O口的电平状态,并根据当前的按键状态做出相应的处理。
首先,我们需要检测按键是否按下。
为了防止按键的抖动和误触发,我们使用一个状态机来确定按键的状态。
状态机的状态可以分为按下和松开两种。
占用较少的单片机IO口就能够实现较多的按键功能

本文介绍两种方法解决"如何占用较少的单片机I/O口就能够实现较多的按键功能?"
方法一:二进制编码法
这个方法我在好几个产品上都用过,适合需要的按键不是太多的情况下使用.如果单片机有n 个I/O口,那么在理论上就可以实现2n—1个按键, 下面的电路图是利用3个I/O口实现6个按键的功能,每个按键代表1个二进制编码,如[ENT]键的编码是[0 0 1],其他按键以此类推。
方法二:A/D值判断法
这个方法只占用单片机的1个A/D输入口,就可以实现较多的按键功能.通过采样A/D值的大小就可以判断是哪个按键被按下,缺点是当多个按键同时按下时,容易判断出错.
本文简单介绍“低边与高边电流检测”的主要区别。
图B低边电流检测方案简单而且便宜,一般的运放器都可以实现此功能。
但是很多应用无法接受检测电阻Rs引入的地线干扰问题,负载电流较大时更会加剧这个问题,因为系统中一部分电路的地电位由于低边检流电阻而产生偏移,而这部分电路可能与另一部分地电位没有改变的电路相互联系。
所以当需要大电流检测时,必须重视这个问题。
图A在负载的高端进行电流检测的简易电路,不仅消除了地线干扰,而且能够检测到短路故障,需要注意的是高边检测要求放大器能够处理接近电源电压的共模电压。
本文介绍无源滤波电路的频率计算公式
1. 常用的RC滤波电路
f 0 = 1/(2πRC)
例:R = 16K ,C =10nF
f 0 = 1/(2πRC) = 1/(2π×16×103×10×10-9 ) =1000Hz
2. LC滤波电路
下期介绍。
单片机按键处理方式(一)——典型的按键处理方式

单⽚机按键处理⽅式(⼀)——典型的按键处理⽅式前⾔ 按键处理是学习单⽚机的必修课之⼀。
⼀次按键的过程,并⾮是⼀个理想的有⼀定宽度的电平脉冲,⽽是在按下、弹起过程中存在抖动,只有在中间阶段电平信号是稳定的。
⼀次典型的按键过程是酱紫的: 在抖动过程中,电平信号⾼低反复变化,如果你的按键检测是检测下降沿或上升沿或者是⽤外部中断检测按键,都可能在抖动时重复检测到多次按键。
这就是在未消抖的按⼀次键显⽰值加1的程序中,出现按⼀次键显⽰值+2、+3甚⾄加更多的原因。
对于按键消抖,常⽤的有硬件消抖和软件消抖。
本⽂是我个⼈对按键处理的⼀些常见⽅法的总结,由于我本⼈不太懂硬件,所以这⾥只讨论独⽴按键的软件消抖实现。
⽔平有限,如有错误请不吝指正。
硬件环境 本⽂代码均在单⽚机STC90C516RD+、晶振12.0MHz硬件环境下试验通过。
带消抖的简单的按键处理 最简单的消抖处理就是在⾸次检测到电平变化后加⼀个延时,等待抖动停⽌后再次检测电平信号。
这也是⼤多数单⽚机教程讲述的消抖⽅式。
但在实际应⽤中基本不⽤这种⽅式,原因后⾯讲,先看代码://⽅法⼀:带消抖的简单的按键处理#include <reg52.h>#define GPIO_KEY P1 //8个独⽴按键IO⼝#define GPIO_LED P0 //8个LED灯,⽤于显⽰键值unsigned char ScanKey();void DelayXms(unsigned char x);void main(){unsigned char key;GPIO_LED = 0x00; //初始化LEDwhile (1){key = ScanKey(); //读取键值// if (0xff != key) //若有键按下,则更新LED的状态GPIO_LED = ~key; //点亮LED}}unsigned char ScanKey(){unsigned char keyValue = 0xff; //赋初值,0xff表⽰没有键按下GPIO_KEY = 0xff; //给按键IO⼝置位if (0xff != GPIO_KEY) //检查按键IO⼝的电平,如有键按下则不为0xff{DelayXms(15); //延时15ms,滤掉抖动。
单片机按键单击、双击、长按功能实现

单片机按键单击、双击、长按功能实现由于项目产品的需要,只能设置一个按键,但是需要实现短按(即单击)切换工作模式、长按开关机、双击暂停等复用功能。
下图是三种情况下的按键波形。
按键未按下时是高电平,按下去是低电平。
按键单击时,判断时间门槛设置为50~2000ms;长按门槛为持续按下2000ms。
双击可以视为时间间隔很短的俩次有效单击,从第一次单击上升沿到第二次单击上升沿延时门槛为100~500ms。
按键单击按键长按按键双击在STM8单片机上面实现代码为://按键按下去会出现下降沿,设置按键IO口GPIOB4所在的外部端口B下降沿触发中断void exit_init(void){EXTI_DeInit();EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB,EXTI_SENSITIVITY_FALL_ONLY);}//按键按下中断服务程序INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4){if(GPIO_ReadInputPin(GPIOB,GPIO_PIN_4)==0)//是按键下降沿{key_fall_flag = 1;//生成按键按下标志}}//周期1ms的定时器中断服务程序INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23){if(key_fall_flag==1)//发生按键按下事件{if(GPIO_ReadInputPin(GPIOB,GPIO_PIN_4)==0)//按键持续按下{if(key_holdon_ms <= 2000){key_holdon_ms++;}else //按键按下到2000ms就判断长按时间成立,生成长按标志{key_holdon_ms = 0;short_key_flag=0;//清短按键标志key_long_down = 1;//长按键标志置位key_fall_flag = 0;//清按键按下标志}}else //按键抬起{if(key_holdon_ms>50)//按下时间大于50ms,生成单击标志{key_holdon_ms=0;short_key_flag=1;key_long_down =0;key_fall_flag=0;//距离上次单击时间在100~500ms之间,则认为发生连击事件if(keyupCnt>100 && keyupCnt<500){doubleClick = TRUE;short_key_flag=0;}keyUpFlag = TRUE;//单击抬起按键后,生成按键抬起标志}else //按键持续时间小于50ms,忽略{key_holdon_ms=0;short_key_flag=0;long_key_flag=0;key_fall_flag=0;}}}if(keyUpFlag)//单击抬起后,启动计数,计数到500ms keyupCnt++;if(keyupCnt>500){keyupCnt = 0;keyUpFlag = FALSE;}}。
基于单片机的快速按键识别方法

基于单片机的快速按键识别方法摘要:在使用单片机实现的智能控制系统中,快速、可靠的按键识别控制非常关键,一定程度上决定了整个系统的高效运行。
本文在分析传统的按键扫描或识别方法的基础上,对比各种方法的优缺点,重点讨论一种高效的按键识别方法,并给出该方法对应的程序设计思路,它可快速识别对按键的一次响应,解决多次冗余响应的缺陷。
关键词:单片机按键识别一次响应中图分类号:tp368.12 文献标识码:a 文章编号:1007-9416(2012)08-0175-021、引言在以单片机为核心控制的应用系统中,键盘按键能实现向单片机输入数据、传送命令等功能,是单片机应用系统中人工干预单片机的主要手段。
而单片机对按键闭合与否的判断,主要是通过其引脚上的电压高低进行的。
本文以51单片机为例说明,所述键盘按键的硬件电路设计也非常简单——轻触开关的一端接地,另一端连接单片机引脚,该引脚同时接10k上拉电阻[1]。
很明显,单片机引脚呈现高电平表示按键开关断开;反之,引脚电压呈现低电平表示按键开关闭合。
因此,对单片机的按键识别只要通过对其引脚电平的高低状态的检测,即可确认按键按下与否[2]。
众所周知,按键为机械弹性开关,加之按键按下或抬起瞬间均会产生抖动现象,因此消除按键抖动也是整个系统的关键。
为更突出本文的讨论重点,这里不再重点讨论按键去抖的方法。
2、传统按键识别方法2.1 简单的按键识别该按键识别方法虽然简单,但当按下按键的瞬间,却可能让系统多次循环处理同一按键事件,造成cpu资源的浪费。
以下为该方法的程序设计思路,下述中的“按键确实按下”表示延迟10ms后,按键仍处于按下状态。
(1)初始化按键;(2)if(按下按键){延迟10ms去抖;if(按键确实按下){事件处理,退出}}else {未按按键,退出}单片机程序可能是一个循环执行的过程,当按键按下闭合,程序进入按键事件,执行完该事件,若按键仍未被抬起,则程序循环又再一次进入同样的按键事件执行。
单片机按键识别篇---单击---双击----长按

单⽚机按键识别篇---单击---双击----长按 最近做⼀任务需要使⽤⼀个按键实现三种功能,分别是按键单击功能,按键双击功能和按键长按功能,可能之前没有接触过这类按键复⽤情况,顶多也只是简单识别单击和长按,没有想过双击以上按键功能,也是绞尽脑汁,想了半天,⼜上⽹看了些例程,算是对于按键的识别有点⼩⼩的了解,感觉这个功能挺实⽤,在此做个随笔。
⼀、思路 1.识别长按操作思路:我们使⽤系统定时器定时,然后让系统每过⼀段时间去扫描按键I/O⼝状态,当扫描到按键按下I/O⼝状态超过设定长按时间的阀值,就判定这次按键操作为“长按”操作; 2.识别单击操作思路:当系统扫描按键按下的I/O⼝时间⼩于我们设定的长按阀值,这时就可能出现两种情况,情况1.可能是单击;情况2.可能是双击;⾸先我们来说情况1,单击操作,这时我们可以检测按键按下后,按键弹起的时间到下次按键按下的时间间隔,当按键按下弹起到下次按键按下的时间超过某个值,则我们判定这次操作为“单击”操作; 3.识别双击操作思路:上⾯刚说的情况1,这次来说情况2,:双击操作,当我们检测按键按弹起后在⼀定时间阀值内,⼜检测到按键I/O⼝有电平变化,则我们判断这次操作为“双击”操作⼆、程序部分unsigned char scan_key(){/*值key_return如下:1---------单击2---------双击3---------长按*/static unsigned char key_state=0; //按键状态static unsigned char state=0;static unsigned char time,time1,time2;static unsigned char key_up_flag=0; //按键弹起标志位static unsigned char key_return;if(Key==0) //按键按下消抖{delay(50);if(Key==0){key_state=0;}}else{delay(50); //按键松开消抖if(Key==1){key_state=1;key_up_flag=0;}}if((state==0)&&(key_state==0)&&(key_up_flag==0)) //这⾥主要防⽌,按键在识别长按后,⼜会执⾏⼀遍单击操作{state=1;time=key_time; //记录按键按下的时间为多少,做标记}if(state==1){time1=key_time;time2=time1-time; //计算按键按下时长if(time2>50) //长按判断{state=2;}if(key_state==1) //按键弹起{state=3;time=key_time; //标志什么时间按键弹起的}}if(state==2) //长按{state=0; //重置状态key_up_flag=1;key_return=3;}if((state==3)&&(key_up_flag==0)){time1=key_time;time2=time1-time; //计算按键弹起后时间if(time2>6) //判断按键弹起后的时间,超过300ms,则说明为单击 {state=0;key_return=1;}else if(key_state==0) //按键弹起后,300ms内⼜有按键按下{state=4;}}if(state==4){if(key_state==1) //按键弹起{state=0;key_return=2;}}return key_return;}void timer0() interrupt 1//定时器T0中断函数⼊⼝{TH0=0X9E; //初值重载TL0=0X57; //定时50ms=50000us; 50000/2=25000key_time++; //50MS++}。
简谈单片机检测按键原理和中断按键检测的办法

简谈单片机检测按键原理和中断按键检测的办法单片机检测按键原理首先说一下独立键盘检测,在单片机外围电路中,通常用到的按键都是机械弹性开关,当开关闭合时,线路导通,开关断开时,线路断开。
单片机检测按键的原理:按键的一端接地,另一端与单片机的某个I/O口相连,开始先给I/O赋一高电平,然后让单片机不断检测该I/O口是否变为低电平,当按键闭合时,相当于I/O口与地相连,就会变为低电平。
在单片机检测按键是否被按下时,电压的实际波形与理想波形时有一点=定差别的,波形在按下和释放瞬间都有抖动现象,抖动时间的长短和按键的机械特性有关。
所以单片机在检测键盘是否被按下都要加上去抖操作,所以在编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时。
独立键盘与单片机连接时每一个按键都需要一个I/O口,会过多占用I/O口资源。
所以就引出了矩阵键盘。
矩阵键盘的连接方式,每一行将每个按键的一端连接在一起构成行线,每一列将按键的另一端连接在一起构成列线。
这样的话,16个按键排成4行4列就只要8根线。
它的按键检测,简单点说,就是先送一列低电平,其余均为高电平,然后轮流检测,确认行列。
这里就要提到另外一个东西,switch-case语句又称开关语句,它是一个专门用于处理多分支结构的条件选择语句。
使用switch语句可直接处理多个分支。
按键检测是初学单片机的同学玩的前几个例程,按键的种类有许多(普通按钮,矩阵键盘等等),按键检测的方法也有许多。
对于普通按钮当然你会说设计一个外围电路通过GPIO 口读一下还不简单,或许你说通过外部中断做边沿检测,对于矩阵键盘来说,往往你会通过行列分别扫描的方法做按键检测,通常我们会加一个按键防抖(经典的方法是通过延时二次确认的方法进行按键防抖,还有就是按键释放的时候你可能会通过while语句去防抖,也就是按键如果一直按下,让程序一直死在while里),这些都是初学者常用的方法,但是如果是一个大的程序,往往是不允许你有这么多延时和死循环的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《一个按键的多次击键组合判别技巧》大话篇
小匠自从上次在旧社区发表了一篇《<程序编写规范倡议书>大话篇》后,好久没有发表"高"论了.急坏了一帮MM,以为小匠退隐江湖了。
(斑竹在旁问道:“MM”不是“Mie Mie”,而是“Ma Ma”吧?)
论坛内外谣言四起,有人说小匠改行了,不做程序匠,改做泥水匠了;还有人说小匠上阿富汗反恐怖去了;其实非也,只因新板论坛启用后,小匠一直用不惯......
(斑竹在旁笑道:是“用不来”吧?)
今天,小匠再次隆重登坛献演。
贴一个小程序段.....
(斑竹道:我看是“蹬痰现眼”吧?)
(程序匠人贴完帖子,下到后台,一边洗着手上残余的浆糊,一边哼着小曲:“如果你的‘芯’是一座作坊,我愿作那不知疲倦的程序匠,……”)
(一黑客悄悄贴近匠人,将一个废弃的浆糊桶扣到匠人头上......)
(匠人忙问:“斑竹,谁把灯给关了?”)
(众人哈哈大笑!......)
一个按键的多次击键组合判别技巧
有时在设计中,往往要用一个按键来输入多种信息。
如:单击/双击/三击、短击/长击、还有各种组合击键方式。
可以用以下程序来做。
如果按键闭合时间<500MS,判断为一次短击(0);
如果按键闭合时间>500MS,判断为一次长击(1);
两次击键时间间隔应<700MS,如果按键释放后700MS内无键按下,则结束读键。
读键完毕返回一个键号值KEY_NUM。
其意义如下:
KEY_NUM 意义
00000000 无键按下过
00000001 无意义
00000010 单次短击
00000011 单次长击
00000100 短击+ 短击
00000101 短击+ 长击
00000110 长击+ 短击
00000111 长击+ 长击
…………
10000000 7次短击
11111111 7次长击
上表中的KEY_NUM值的规律是,从左向右看,第一个"1"后面的每一位代表一次击键;"0"代表短击,"1"代表长击。
掌握该规律后,我们可将任何一个8位的二进制数"翻译"成一种击键组合。
例如:01010101,代表的是:短+长+短+长+短+长。
该程序最多可识别7次连续击键,共254种组合。
但并非每个程序中用得上。
在大多数程序中,能判断双击即可以了,这时可将程序中的ZHBIT定义为2。
同理,如果要判断3次按键,将ZHBIT定义为3即可。
当ZHBIT=1时,程序仅能判断一次击键,包括2种组合(短击/长击);当ZHBIT=2时,程序还能判断两次击键,包括6(2+4)种组合(短击/长击/(短+短)/(短+长)/(长+短)/(长+长));以次类推,当ZHBIT=3时,程序能判断三次击键,包括14(2+4+8)种组合。
ZHBIT 组合种类
1 2
2 2+4=6
3 2+4+8=14
4 2+4+8+16=30
5 2+4+8+16+32=62
6 2+4+8+16+32+64=126
7 2+4+8+16+32+64+128=254
下面这段程序摘自小匠的一个智能充电器程序(MCU是EM78P458),如下:
;********************************
;读键子程序
;出口: KEY_NUM =键号值
;中间: KEY_DL =计数器
;说明:
/*
短击:键按下时间<500MS
长击:键按下时间>500MS
两次按键间隔时间<700MS
键号定义:
KEY_NUM=00000000: 无键按下
KEY_NUM=00000001: 无意义
KEY_NUM=00000010: 单次短击
KEY_NUM=00000011: 单次长击
KEY_NUM=00000100: 短击+ 短击
KEY_NUM=00000101: 短击+ 长击
KEY_NUM=00000110: 长击+ 短击
KEY_NUM=00000111: 长击+ 长击
...
...
KEY_NUM=11111110: 长击+ 长击+ 长击+ 长击+ 长击+ 长击+ 短击
KEY_NUM=11111111: 长击+ 长击+ 长击+ 长击+ 长击+ 长击+ 长击
*/
ZHBIT EQU 2 ;按键组合位(选择范围1~7)
;********************************
READKEY:
CLR KEY_NUM ;清键号
JKOFF READKEYF ;键未按下跳
BS KEY_NUM,0 ;"1" -> 键号低位
;=================
READKEYA:
CLR KEY_DL ;清计数器
READKEYB:
INC KEY_DL
MOV A,@50
SUB A,KEY_DL
JBC R3,C
JMP READKEYC ;计数器溢出跳
JKON READKEYB ;键未释放跳
BC R3,C ;C=0
JMP READKEYD
;=================
READKEYC:
WDTC ;喂狗
JKON READKEYC ;键未释放跳
BS R3,C ;C=1
READKEYD:
RLLC KEY_NUM ;键号左移一位,C -> 键号低位JBC KEY_NUM,ZHBIT ;按键检测未完成继续
RET
;=================
CLR KEY_DL ;清计数器
READKEYE:
CALL DL10MS
MOV A,@70
SUB A,KEY_DL
JBC R3,C
READKEYF:
RET ;计数器溢出返回
JKOFF READKEYE ;键未按下跳
JMP READKEYA ;再次检测
;=================
;键闭合跳(宏)
;=================
JKON MACRO ADDRESS
JBS R5,KEY ;键断开跳
FJMP ADDRESS ;键闭合跳
CALL DL10MS ;延时去抖动JBS R5,KEY ;键断开跳
FJMP ADDRESS ;键闭合跳ENDM
;=================
;键断开跳(宏)
;=================
JKOFF MACRO ADDRESS
JBC R5,KEY ;键闭合跳
FJMP ADDRESS ;键断开跳
CALL DL10MS ;延时去抖动JBC R5,KEY ;键闭合跳
FJMP ADDRESS ;键断开跳ENDM。