目录
一、概述
由于最近需要对单Button开发多功能,因此,我们需要实现单击、双击、长按的效果反馈,实现不同的操作效果。(代码开源)
二、整体思路
针对不同按压方式,我们首先要了解单击、双击、长按的区别在于什么地方。
下面我们继续再看一下长按的波形。
通过分析我们不难发现,单击就是一个最简单的由高电平-低电平-高电平的过程,且低电平持续时间短,长按是两次快速的单击,中间间隔的高电平时间较短,长按本质上是一次单击,但中间低电平持续时间长。
电平变化 | 持续时间 | |
单击 | 高-低-高 | 短 |
长按 | 高-低-高 | 长 |
双击 | 高-低-高-低-高 | 短 |
我们通过上述的表格确定编程思路,即将收到的按键信号分为两种,一是持续时间长的(长按),二是持续时间短的(单击或双击),因为我们需要一个变量来存储两次之间的时间,便于我们做判断。
三、代码实现
此处我选用低电平触发的Button,来实现如下功能。
首先初始化相关LED与Switch引脚。
P1SEL &=~ 0X44;
P1DIR &= ~0X44;
P1SEL &= ~0x1b;
P1DIR |= 0X1B;
随后我们先定义一个全局变量,此处我使用unsigned long,受限于在单片机中的最大数,已经每秒单片机能处理的指令数量,各位自行选择。
随后我们在主循环中让定义的标志位自增,我选择60000是因为在我们单片机上,60000大致相当于半秒。
if(flag<60000)
{
flag++;
}
随后我们继续完成主函数,并对此进行分析。
if(sw1==0)
{
halMcuWaitMs(10);
if(sw1==0)
{
if(flag<60000)//认为是第二次双击
{
//执行双击策略
halLedToggle(2);//执行某个语句
}
flag=0;
while(!sw1)
{
if(flag<60000)
flag++;
if(flag==60000)
{
halLedSet(1);//执行某个语句
flag++;//只执行一次
}
}
if(flag==60001)
{
halLedClear(1);//执行某个语句
}
flag=0;
}
每次按钮松开都会重置标志位,当按钮再次按下的时候,如果flag小于60000则说明这是一次双击事件,否则则说明这次事件和上次事件的持续时间长,没有必然联系,我们就可以进一步分析是否为单击或长按。
在等待按键松开的工程中,再次重置标志位,用标志位计算时间,如果按钮松开时,标志位小于60000,说明低电平持续时间小于0.5s,则属于一次单击,否则属于一次长按。
在按键松开后,通过判断flag的值,如果小于60000,则说明这是单击后的结束事件,否则则是长按结束后的事件。
四、总结
本次活动通过计时的思路,分析单击、双击、长按的区别,实现区分,一键多用,发挥出不同的功能,提高开发效率。