王昱顺 发表于 2024-5-16 15:36:26

三行又四行,简单实现长按双击识别

前段时间里,论坛曾经研究过一个三行代码实现按键识别的帖子,近来研究双击和长按的时候,心血来潮研究了一下。成功实现了一种非常简单的双击和长按识别,其中,按键识别占用四行,双击和长按的逻辑占用四行。首先,我们分析一下双击和长按的逻辑,长按即是按下按键后超过了某一个时间,双击则是在单击后的某一段时间内,再次按下按键。所以,如果追求响应速度的话,单击和双击必然是识别冲突的,这里建议只保留双击功能,否则第一下肯定会识别为单击,处理不好甚至会造成逻辑混乱。在上面的逻辑里面,我们不仅仅需要获取到按键按下的边沿,还需要获取到按键抬起的边沿。所以,我们需要对代码做一些小小的改动。代码部分:先贴一下代码:
val = Get_Key();
            down = val & (val ^ old);
            up = old & (val ^ old);
            old = val;这里,我们通过get_key()函数获取了本次按下的键值(这里是矩阵键盘和独立按键都可以,只需要返回对应的数字就可以了)然后,我们使用(val^old)进行边沿检测,如果两次一次为0一次为有效数字,则会返回一个有效数字。然后通过val&(val^old)对当前值进行比较,如果当前值为val(从0到val),则判断为上升沿,如果上次为有效数字,即从val到0,则为下降沿,实现代码为:old&(val^old)
这就完成了上升沿和下降沿的识别,那么长按和双击此时也变得很简单了。先贴一下代码:u32 l_key = 0, d_key = 0;
if (down == 9)
{
    l_key = time;
    if (time - d_key < 200)
      Mode = Tmp_Mode;
}
if (up == 9)
{
    if (time - l_key > 500)
      Mode = UART_Mode;
    else
      d_key = time;
}
这里,down是按下边沿的键值,up是抬起边沿的键值,time为u32大小的1ms自加值。当按键按下的时候,保存一次当前的时间戳。抬起的时候,判断第一次按下的时间戳和当前是的差值,如果大于500ms,则判定为长按。此时保存一次抬起时间戳,如果有第二次按下时,发现距离上次抬起时间小于200ms(时间较短),则可以判断为双击。如果想要拓展为多个按键的双击和长按,可以对l_key和d_key拓展为数组形式,对每个按键进行分别存储。双击和长按实现,核心代码只需要四行即可,并且继承了三行代码按键识别的优点,判断边沿,自带消抖。
这里放一下完整的代码程序,适合大部分的官方开发板,使用P32作为按键,每次长按取反P20口,每次双击取反P21口

zhang32568 发表于 2024-5-16 16:55:05

没有完整代码看不懂

王昱顺 发表于 2024-5-16 18:02:40

zhang32568 发表于 2024-5-16 16:55
没有完整代码看不懂

稍等我整理一下发个完整的代码

zhang32568 发表于 2024-5-16 23:14:07

王昱顺 发表于 2024-5-16 18:02
稍等我整理一下发个完整的代码

谢谢 共同学习。三行经典代码的帖子是我发的。双击和长按没有研究透

嵌入式之路 发表于 2024-5-17 03:13:30

贴下完整的代码 烧录研究下

jwd 发表于 2024-5-17 06:52:23

这种如果要检测多个输入信号的状态该怎么处理,比如上升沿,下降沿啥的

小飞侠 发表于 2024-5-17 07:20:41

希望楼主加上双击和长按

WHX 发表于 2024-5-17 08:08:06

牛啊,{:5_332:}学习了

21cnsound 发表于 2024-5-17 08:22:12

期待完整、完美代码分享{:4_197:}

_奶咖君_ 发表于 2024-5-17 09:43:11

组合键 研究研究{:4_197:}
页: [1] 2 3 4
查看完整版本: 三行又四行,简单实现长按双击识别