单片机按键长按短按双击连击(四双击)

前面我们说到了按键的循环消抖,长按识别,连击识别,今天我们来对双击按键进行编写,其实双击就是连按连下,双击,三连按,四连按本质上都一样,今天我只进行双击的编写,其实三连按就是在双击的基础上多按一下,多记一次数,然后多一个键值

那么我们开始对代码分析:首先我们开始对事件的过程进行分析,首先我们按下一次按键,按下按键以后,达到消抖时间,再释放,再短时间内再次按下,那么,我们需要记录按下次数和释放的时间,那么就再加个计数和释放计时器,还是老规矩,定义一个结构体:

typedef struct {
    uint8_t key_flag : 1;
    uint8_t key_long_flag : 1;
    uint8_t key_hit_flag : 1;
    uint16_t key_out;
    uint8_t key_click_num;
    uint8_t key_num;
    uint8_t key_long_num;
    uint8_t key_double_num;
}KeyState;

这里首先我们需要消抖判断,然后是连击判断,长按判断,双击判断,按下计时器,释放计时器,按下此时,几个键值,那么这样一个结构体就定义好了

然后我们需要给定一个释放时间,如果释放按键次数超过这个时间那么就不是双击了,将它和前面其他的时间定义放在一块,然后是键值定义,可以是枚举可以是宏定义,我这里建议枚举,下面我们继续编写代码:

​
#ifndef _key_h_
#define _key_h_
 
#include "stm32f10x.h"    // 这里如果是51的同学可以改成REGX51
 
#define KEY_Disp_Time 20
#define KEY_Long_Time 200
#define KEY_Hit_Time  300
#define KEY_Double_Time 50
 
#define KEY1_Disp_num    1
#define KEY1_Long_num    11
#define KEY1_double_num  12
#define KEY2_Disp_num    2
#define KEY2_Long_num    21
#define KEY2_double_num  12
#define KEY3_Disp_num    3
#define KEY3_Long_num    31 
#define KEY3_double_num  32    // 还是可以枚举按键,也可以宏定义,我这里采用宏定义
 
#define KEY1 PAin(0)
#define KEY2 PAin(1)
#define KEY3 PAin(2)        // 还是老规矩定义三个按键
 
typedef struct{
    uint8_t key_flag : 1;
    uint8_t key_long_flag : 1;
    uint8_t key_hit_flag : 1;
    uint8_t key_Double_flag : 1;
    uint16_t key_out;
    uint8_t key_cnt;
    uint8_t key_click_num;
    uint8_t key_num;
    uint8_t key_long_num;
    uint8_t key_double_num;
}KeyState;
 
void Key_Init(void);
uint8_t Key_Read_Output(void);
 
 
#endif

​

我们还是采用模块化思维,方便移植代码,然后我们开始主代码:

#include "key.h"

KeyState Key_State = {
    { 0, 0, 0, 0, 0, 0, KEY1_Disp_num, KEY1_Long_num, KEY1_double_num },
    { 0, 0, 0, 0, 0, 0, KEY2_Disp_num, KEY2_Long_num, KEY2_double_num },
    { 0, 0, 0, 0, 0, 0, KEY3_Disp_num, KEY3_Long_num, KEY3_double_num },
};

void KEY_init(void)
{
    /*
    * 依旧是GPIO初始化
    */
}

KeyState Key_ReadInput(void)
{
    if (!KEY1) return &KeySatet[0];
    else if (!KEY2) return &KeySatet[1];
    else if (!KEY3) return &KeySatet[2];

    return NULL;
}

uint8_t KEY_GETOutput(void)
{
    KeyState *keytate = Key_ReadInput();
    uint8_t key_num;

    if (keystate == NULL)
    {
        for (uint8_t i = 0; i < 3; ++i)
        {
            if (Key_State[i].key_double_flag)
            {
                key_num = Key_State[i].key_double_num;
                Key_State[i].key_double_flag = 0;
            }
            if (Key_State[i].key_click_num > 0)
            {
                Key_State[i].key_cnt++;
                if (Key_State[i].key_cnt > KEY_Double_Time)
                {
                    Key_State[i].key_cnt = 0;
                    Key_State[i].key_click_num = 0;
                }
            }
            if (Key_State[i].key_flag)
            {
                if (Key_State[i].key_long_flag)
                {
                    key_num = keystate->key_long_num;
                } else {
                    key_num = keystate->key_num;
                }
            }
            Key_State[i].key_flag = 0;
            Key_State[i].key_long_flag = 0;
            Key_State[i].key_out = 0;
        }
    } else if (!(keystate->key_double_flag || keystate->key_hit_flag)){
        keystate->key_out++;
        if (keystate->key_out == KEY_Disp_Time)
        {
            keystate->key_flag = 1;
            keystate->key_click++;
            if (keystate->key_click == 2)
            {
                keystate->key_double_flag = 1;
                keystate->key_click = 0;
                keystate->key_flag = 0;
            }
            keystate->key_cnt = 0;
        }
        if (keystate->key_out == KEY_Long_Time)
        {
            keystate->key_long_flag = 1;
            keystate->key_click = 0;
        }
        if (keystate->key_out == KEY_Hit_Time)
        {
            keystate->key_hit_flag = 1;
            keystate->key_long_flag = 0;
            keystate->key_flag = 0;
            keystate->key_out = 0
        }
    } else if (keystate->key_hit_flag) {
        keystate->key_out++;
        if (keystate->key_out == KEY_Disp_Time)
        {

            keystate->key_out = 0;
            key_num = keystate->key_num;
        }

    }

    return key_num;
}

在这里我解释一下代码,是首先,按下按键,我们对计数器开始计数,当计数器达到消抖时间那么就把短按标志位置1,证明有按键按下,然后把按键按下次数加1,如果按键次数达到两次就把双击标志位置1,我们再来看第二个elseif语句,(!(keystate->key_double_flag || keystate->key_hit_flag)),这个一个或,意思就是,这两个事件发生一个事件就不再进入这个判断,那么没有达到双击,我们就继续计数,如果发生长按了,那么我们就不是双击了,就把按下次数清零即可,如果达到连击时间,那么就是连击操作了,就进入下一个判断语句,并且同时将长按和短按标志位清零,当我们按键释放以后,我们的双击标志位如果为1,就证明发生了双击事件,那么就返回双击键值,并且同时将按键次数清零,反之如果计时按键次数如果大于零,这里按键标志没有为1,为1,会把次数清零,那么现在双击计时器就开始计数,如果超过了双击间隔时间,就把按下次数清零,这里如果进行长按操作,按下次数也会清零,所以如果长按了,这个if也不会满足,那么短按标志位为1然后进入判断,如果长按标志位为1,就是长按,不是就是短按

这样就完成了按键的操作了

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些关于 stm32 按键短按双击的实现方法。 对于单片机按键处理,常见的方法是轮询法和中断法。轮询法是在主循环中不断读取按键状态,判断按键是否按下或者释放,并进行相应的处理;中断法则是通过外部中断或者定时器中断来响应按键事件。 对于按、短按双击事件的处理,一种常见的方法是使用状态机。状态机包括多种状态和转移条件,用于描述按键事件的不同状态和状态之间的转移过程。通过按键状态的变化,可以判断出按键事件的类型,并进行相应的处理。 具体实现方法可以参考以下步骤: 1. 读取按键状态,并判断按键是否按下或者释放。 2. 根据按键状态的变化,更新状态机的状态,并记录按键的按下时间和释放时间。 3. 根据状态机的状态,判断按键事件的类型,并进行相应的处理。例如,当状态机处于“按下”状态时,如果按键持续按下的时间超过一定阈值,则判断为按事件;如果按键持续按下的时间不足阈值,则判断为短按事件;如果在一定时间内连续按下两次按键,则判断为双击事件。 4. 根据按键事件的类型,执行相应的操作。例如,按事件可以用于开启或关闭某个功能;短按事件可以用于切换不同的模式;双击事件可以用于执行快速操作。 总之,实现按键短按双击需要结合具体的硬件平台和软件环境进行综合考虑,根据实际需求选择合适的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值