第11节:同一个按键短按与长按的区别触发

发布者:CrystalBreeze最新更新时间:2016-03-14 来源: eefocus关键字:按键  短按  长按  区别触发 手机看文章 扫描二维码
随时随地手机看文章
开场白:

上一节讲了类似电脑键盘组合按键触发的功能,这节要教会大家一个知识点:如何在上一节的基础上,略作修改,就可以实现同一个按键短按与长按的区别触发。

 

具体内容,请看源代码讲解。

 

(1)硬件平台:基于朱兆祺51单片机学习板。用矩阵键盘中的S1和S5号键作为独立按键,记得把输出线P0.4一直输出低电平,模拟独立按键的触发地GND。

 

(2)实现功能:两个独立按键S1和S5,按住其中一个按键,在短时间内松手,则认为是短按,触发蜂鸣器短鸣一声。如果一直按住这个按键不松手,那么超过规定的长时间内,则认为是长按,触发蜂鸣器长鸣一声。

 

(3)源代码讲解如下:

#include "REG52.H"

 

#define const_voice_short 20 //蜂鸣器短叫的持续时间

#define const_voice_long 140 //蜂鸣器长叫的持续时间

 

/* 注释一:

* 调整抖动时间阀值的大小,可以更改按键的触发灵敏度。

* 去抖动的时间本质上等于累计定时中断次数的时间。

*/

#define const_key_time_short1 20 //短按的按键去抖动延时的时间

#define const_key_time_long1 400 //长按的按键去抖动延时的时间

 

#define const_key_time_short2 20 //短按的按键去抖动延时的时间

#define const_key_time_long2 400 //长按的按键去抖动延时的时间

 

void initial_myself(); 

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void T0_time(); //定时中断函数

void key_service(); //按键服务的应用程序

void key_scan(); //按键扫描函数 放在定时中断里

 

sbit key_sr1=P0^0; //对应朱兆祺学习板的S1键

sbit key_sr2=P0^1; //对应朱兆祺学习板的S5键

sbit key_gnd_dr=P0^4; //模拟独立按键的地GND,因此必须一直输出低电平

 

sbit beep_dr=P2^7; //蜂鸣器的驱动IO口

 

unsigned char ucKeySec=0; //被触发的按键编号

 

unsigned int uiKeyTimeCnt1=0; //按键去抖动延时计数器

unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志

unsigned char ucShortTouchFlag1=0; //短按的触发标志

 

unsigned int uiKeyTimeCnt2=0; //按键去抖动延时计数器

unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志

unsigned char ucShortTouchFlag2=0; //短按的触发标志

 

unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的持续时间计数器

 

void main() 

{

initial_myself(); 

delay_long(100); 

initial_peripheral(); 

while(1) 

key_service(); //按键服务的应用程序

}

 

}

 

void key_scan()//按键扫描函数 放在定时中断里

/* 注释二:

* 长按与短按的按键扫描的详细过程:

* 第一步:平时只要按键没有被按下时,按键的自锁标志,去抖动延时计数器一直被清零。

* 第二步:一旦两个按键都被按下,去抖动延时计数器开始在定时中断函数里累加,在还没累加到

* 阀值const_key_time_short1或者const_key_time_long1时,如果在这期间由于受外界干扰或者按键抖动,而使

* IO口突然瞬间触发成高电平,这个时候马上把延时计数器uiKeyTimeCnt1

* 清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。这是我实战中摸索出来的。

* 以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。

* 第三步:如果按键按下的时间超过了短按阀值const_key_time_short1,则马上把短按标志ucShortTouchFlag1=1;

* 如果还没有松手,一旦发现按下的时间超过长按阀值const_key_time_long1时,

* 先把短按标志ucShortTouchFlag1清零,然后触发长按。在这段程序里,把自锁标志ucKeyLock1置位,

* 是为了防止按住按键不松手后一直触发。

* 第四步:等按键松开后,自锁标志ucKeyLock12及时清零,为下一次自锁做准备。如果发现ucShortTouchFlag1等于1,

* 说明短按有效,这时触发一次短按。

* 第五步:以上整个过程,就是识别按键IO口下降沿触发的过程。

*/

if(key_sr1==1)//IO是高电平,说明两个按键没有全部被按下,这时要及时清零一些标志位

{

ucKeyLock1=0; //按键自锁标志清零

uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。 

if(ucShortTouchFlag1==1) //短按触发标志

{

ucShortTouchFlag1=0;

ucKeySec=1; //触发一号键的短按

}

}

else if(ucKeyLock1==0)//有按键按下,且是第一次被按下

{

uiKeyTimeCnt1++; //累加定时中断次数

if(uiKeyTimeCnt1>const_key_time_short1) 

{

ucShortTouchFlag1=1; //激活按键短按的有效标志 

}

 

if(uiKeyTimeCnt1>const_key_time_long1) 

{

ucShortTouchFlag1=0; //清除按键短按的有效标志

 

uiKeyTimeCnt1=0; 

ucKeyLock1=1; //自锁按键置位,避免一直触发

 

ucKeySec=2; //触发1号键的长按

 

}

 

}

 

if(key_sr2==1)//IO是高电平,说明两个按键没有全部被按下,这时要及时清零一些标志位

{

ucKeyLock2=0; //按键自锁标志清零

uiKeyTimeCnt2=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。 

if(ucShortTouchFlag2==1) //短按触发标志

{

ucShortTouchFlag2=0;

ucKeySec=3; //触发2号键的短按

}

}

else if(ucKeyLock2==0)//有按键按下,且是第一次被按下

{

uiKeyTimeCnt2++; //累加定时中断次数

if(uiKeyTimeCnt2>const_key_time_short2) 

{

ucShortTouchFlag2=1; //激活按键短按的有效标志 

}

 

if(uiKeyTimeCnt2>const_key_time_long2) 

{

ucShortTouchFlag2=0; //清除按键短按的有效标志

 

uiKeyTimeCnt2=0; 

ucKeyLock2=1; //自锁按键置位,避免一直触发

 

ucKeySec=4; //触发2号键的长按

 

}

 

}

 

 

}

 

 

void key_service() //第三区 按键服务的应用程序

{

switch(ucKeySec) //按键服务状态切换

{

case 1:// 1号键的短按 对应朱兆祺学习板的S1键

 

uiVoiceCnt=const_voice_short; //按键声音的短触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break; 

case 2:// 1号键的长按 对应朱兆祺学习板的S1键

 

uiVoiceCnt=const_voice_long; //按键声音的长触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break; 

case 3:// 2号键的短按 对应朱兆祺学习板的S5键

 

uiVoiceCnt=const_voice_short; //按键声音的短触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break; 

case 4:// 2号键的长按 对应朱兆祺学习板的S5键

 

uiVoiceCnt=const_voice_long; //按键声音的长触发,滴一声就停。

ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发

break; 

}

 

 

 

void T0_time() interrupt 1

{

TF0=0; //清除中断标志

TR0=0; //关中断

 

key_scan(); //按键扫描函数

 

if(uiVoiceCnt!=0)

{

uiVoiceCnt--; //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫

beep_dr=0; //蜂鸣器是PNP三极管控制,低电平就开始鸣叫。

}

else

{

; //此处多加一个空指令,想维持跟if括号语句的数量对称,都是两条指令。不加也可以。

beep_dr=1; //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。

}

 

 

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //开中断

}

 

 

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //内嵌循环的空指令数量

{

; //一个分号相当于执行一条空语句

}

}

}

 

 

void initial_myself() //第一区 初始化单片机

{

/* 注释三:

* 矩阵键盘也可以做独立按键,前提是把某一根公共输出线输出低电平,

* 模拟独立按键的触发地,本程序中,把key_gnd_dr输出低电平。

* 朱兆祺51学习板的S1和S5两个按键就是本程序中用到的两个独立按键。

*/

key_gnd_dr=0; //模拟独立按键的地GND,因此必须一直输出低电平

 

 

beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。

 

 

TMOD=0x01; //设置定时器0为工作方式1

 

 

TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

 

}

void initial_peripheral() //第二区 初始化外围

{

EA=1; //开总中断

ET0=1; //允许定时中断

TR0=1; //启动定时中断

 

}

 

总结陈词:

在很多需要人机交互的项目中,需要用按键来快速加减某个数值,这个时候如果按住一个按键不松手,这个数值要有节奏地快速往上加或者快速往下减。要现实这种功能,我们该怎么写程序?欲知详情,请听下回分解-----按住一个独立按键不松手的连续步进触发。

关键字:按键  短按  长按  区别触发 引用地址:第11节:同一个按键短按与长按的区别触发

上一篇:第十节:两个独立按键的组合按键触发
下一篇:第12节:按住一个独立按键不松手的连续步进触发

推荐阅读最新更新时间:2024-03-16 14:47

51单片机-按键
矩阵按键: 实现功能按一个键,相应的灯亮。 左边的是普通二极管,右边的是发光二极管。左边的二极管如果想导通,则右边要比左边电平低。如果导通就是按键可以控制灯亮,那么按键左下的都为低电平,系统复位时默认I/O是高电平,所以给垂直方向的I/O拉低,这样如果按键按下,电路导通,那么垂直方向I/O的低电平会把水平方向的拉低。这样就可以通过检测水平方向哪个I/O为低电平来检测哪个键被按下。 开始时对程序的错误想法:被按下的键两边肯定都是低电平,把它们存在一个数组里,然后检测。这样是不对的,用一个临时变量去存P0的值,不会有相同的,开始P0的值为oxff,这样即使按下按键,那么两边的引脚还是高电平,所以失败了。 #
[单片机]
51单片机-<font color='red'>按键</font>
【STM32Cube_05】使用EXIT中断检测按键
1. 准备工作 硬件准备 首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi): 软件准备 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码。 Keil MDK和串口助手Serial Port Utility 的安装包都可以在文末关注公众号获取,回复关键字获取相应的安装包: 2.生成MDK工程 选择芯片型号 打开STM32CubeMX,打开MCU选择器: 搜索并选中芯片STM32L431RCT6: 配置时钟源 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC; 如果使用默认内部时钟(HSI),这一步可以略过; 这里我都使用外部时
[单片机]
【STM32Cube_05】使用EXIT中断检测<font color='red'>按键</font>
STM32中断方式检测按键
1.简述 对于按键,常见的是通过MCU不断检测按键连接 GPIO 的状态变化(高– 低或低— 高),来确认是否有按键输入,这样的缺点很明显,MCU 一直在循环检测,对资源是一种浪费,不够高效。对于STM32,GPIO 是可以配置成中断的,有这个优势,我们就可以通过中断的方式来检测 GPIO 上电平的变化,进一步的得到按键的状态。 2.硬件电路 按键无上拉电阻,需要在 GPIO 上设为上拉状态,提供一个确定电平。 3.驱动实现 //按键初始化做了三件事 ///1.按键连接的GPIO初始化;2.中断配置初始化;3.中断优先级配置 void Key_Init(void) { GPIO_InitTypeDef
[单片机]
STM32中断方式检测<font color='red'>按键</font>
解析示波器通道耦合与触发耦合的区别
相信大家对示波器有着一定的了解,都知道示波器中有两反设置,其实,在示波器当中也存在两种“两耦”设置,一种是通道耦合方式,另一种是触发耦合方式,那么这两种耦合方式设置是什么,做什么用的呢?下面则对这两种耦合方式就行一下讲解。 通道耦合,也就是所测试的信号以怎样的方式进入示波器的通道放大器,直流耦合是信号通过导线直接到放大器输入级,AC就是信号经过电容耦合到前置放大器。 触发耦合,是指扫描触发电路的信号是以那种方式耦合至触发同步放大器的。是抑制一些特殊信号的,例如交流耦合就是抑制掉直流信号部分留下交流部分,直流耦合相反。另外常见的还有高频耦合和低频耦合,也分别是滤掉低频和高频部分。 按下通道控制软键,可看到通道耦合的菜单。
[测试测量]
解析示波器通道耦合与<font color='red'>触发</font>耦合的<font color='red'>区别</font>
HDJF手持式局部放电测试仪使用前仪器按键功能说明
一、采用标准 本多功能局放测试仪(HDJF)的设计采用以下标准: GB/T 7354-2003局部放电测量; GB 4793.1-2007 测量、控制和实验室用电气设备的安全要求 第1部分:通用要求; GB/T 2423.8-1995 电工电子产品基本环境试验规程; GB 2900电工名词术语; GB/T 16927 高电压试验技术; DL/T 356-2010局部放电测量仪校准规范; DL/T 417-2006电力设备局部放电现场测量导则; IEC1000电磁兼容性。 二、操作注意 1、使用仪器之前,请仔细阅读本使用说明书。 2、在试验过程中,不同的传感器测量时,应在“参数设置”项中正确设置参数,以确保测量准确。 3、检测过
[测试测量]
HDJF手持式局部放电测试仪使用前仪器<font color='red'>按键</font>功能说明
矩阵式键盘扫描,单片机扫描按键是否被按下
单片机系统中,若使用按键较多时如电子密码锁、电话机键盘等一般都至少有12到16个按键,通常采用矩阵键盘。矩阵键盘又称行列键盘,它是用四条I/O线作为行线,四条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4*4个。这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。最常见的键盘布局一般由16个按键组成,在单片机中正好可以用一个P口实现16个按键功能,这也是在单片机系统中最常用的形式,4*4矩阵键盘的内部电路如下图所示。 当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。 判断有无按键按下的方法是:第一步,
[单片机]
矩阵式键盘扫描,单片机扫描<font color='red'>按键</font>是否被按下
按键控制LED亮/暗的程序
一个按键控制LED亮/暗的汇编程序。开机,第一次按下第一个开关时,8个LED灯亮,第二次按下第一个开关时,8个LED灯暗,再按开关时8个LED灯就再亮,再次按下时8个LED灯再暗。按一次亮一下,再按一次暗一下。程序编好后,开始编译,发现又是通不过,找了好几遍也没找到原因,后来找枫雪大哥看了,才找出原因,原来编写程序时不能在中文环境下编写,不然就会编译时出错。现在搞好了,发上来给大家看看。此程序在仿真软件PROTEUS及EDN51实验板上均通过。 程序如下: ORG 0000H ;地址0000 LJMP STAR ;转STAR ORG 0100H ;地址0100 STAR: MOV P2,#0FH ;#0FH---P2 MOV
[单片机]
基于MC9S08SC4的汽车方向盘按键控制器技术
随着汽车在人们日常生活中的普及以及汽车电子在汽车应用领域价值不断地扩大,越来越多的舒适性能和“智能”应用被集成进车身电子的领域。飞思卡尔最新的汽车级8位微控制器MC9S08SC4便是本文所要介绍的主角,该款微控制器是业界使用广泛的飞思卡尔HCS08系列汽车级微控制器家族最新的成员,以其低成本、小封装但同时兼具高性能、高可靠性的特点,适用于众多汽车电子应用领域,例如:简单的灯光控制、按键控制、HVAC、LIN通信控制器、车内后视镜调光以及简单的继电器和马达控制。如果你正在为你的应用物色一颗高性能、低成本的汽车级微控制器,但又为电子模块成本和PCB面积的限制而苦恼,相信MC9S08SC4正是你要找的这颗芯片。 MC9S08SC4的
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved