打印
[应用方案]

单片机实现按键短按双击长按程序

[复制链接]
1177|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dspmana|  楼主 | 2023-11-27 22:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*-----------------------------------------------
  名称:按键
------------------------------------------------*/
#include"key.h"
extern unsigned char keyvalue;

unsigned char keyscan()
{
        unsigned char keynumber;
        if(!KEY1) keynumber = 1;                                                                        //!!!修改此处,可以增加/减少按键数量
        else if(!KEY2) keynumber = 2;                                                        //!!!修改此处,可以增加/减少按键数量
        else if(!KEY3) keynumber = 3;                                                        //!!!修改此处,可以增加/减少按键数量
        else if(!KEY4) keynumber = 4;                                                        //!!!修改此处,可以增加/减少按键数量
        else keynumber = 0;
        return keynumber;
}

unsigned char key_multi(void)
{
        static uchar key_state;                                                                         //按键状态变量
        static uint key_time;                                                                                 //按键计时变量
        static uchar key_press_nums;                                                        //按键次数变量               
        static uint key_time_double;                                                        //按键双击时间
        static uchar keynum;                                                                                        //键值
        static uchar new_keynum;                                                                        //新的键值
        uchar key_press, key_return;                                                        //键值和返回值
      
        key_return = None_click;                                                                         //清除返回按键值
      
        switch(keyscan())
        {
                case 1:key_press = KEY1;new_keynum = 1;break;                //!!!修改此处,可以增加/减少按键数量
                case 2:key_press = KEY2;new_keynum = 2;break;                //!!!修改此处,可以增加/减少按键数量
                case 3:key_press = KEY3;new_keynum = 3;break;                //!!!修改此处,可以增加/减少按键数量
                case 4:key_press = KEY4;new_keynum = 4;break;                //!!!修改此处,可以增加/减少按键数量
                default:key_press = 1;break;
        }
        if(key_press_nums > 0)                                                                                 //按键次数大于0,说明有按键
        {
                key_time_double++;                                                                                        //是否开始双击计
                if(key_time_double >= DOUBLE_KEY_TIME && key_time_double < LONG_KEY_TIME) key_state = KEY_STATE_2;//如果时间到了在双击和长按之间,切换到状态2
        }
        switch (key_state)
        {
                case KEY_STATE_0:                                                                                         //按键状态0:判断有无按键按下
                {
                        if (!key_press)                                                                                         //是否有按键按下,没有按下就退出
                        {
                                key_time = 0;                                                                                         //清零时间间隔计数
                                key_state = KEY_STATE_1;                                                 //然后进入 按键状态1
                        }
                }break;
                case KEY_STATE_1:                                                                                         //按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。
                {
                        if (!key_press)
                        {
                                key_time++;                                                                                                 //一次10ms
                                if(key_time>=SINGLE_KEY_TIME)                         //消抖时间为:SINGLE_KEY_TIME*10ms = 10ms;
                                {
                                        key_state = KEY_STATE_2;                                         //如果按键时间超过 消抖时间,即判定为按下的按键有效。进入按键状态2,继续判定到底是单击、双击还是长按
                                        key_press_nums++;                                                                        //按键次数+1
                                }
                        }
                        else key_state = KEY_STATE_0;                                 //如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
                }break;
                case KEY_STATE_2:                                                                                         //按键状态2:判定按键有效的种类:是单击,双击,还是长按
                {
                        if(key_press)                                                                                                 //如果按键在 设定的双击时间内释放,则判定为单击/双击
                        {
                                if(key_time_double < DOUBLE_KEY_TIME ) key_state = KEY_STATE_0;                                                        //双击时间达到前,再次扫描按键,看还有没有按键按下
                                if(key_time_double >= DOUBLE_KEY_TIME && key_time_double < LONG_KEY_TIME)         //达到双击设定时间后,如果时间超过双击的时间则判断按键按下的次数
                                {
                                        if(key_press_nums == 1) key_return = Single_click + new_keynum*10;                                 //判断只按了1次,返回有效按键值:单击,通过不同的值判断是哪个按键按下的单击
                                        else if(key_press_nums ==2 && new_keynum == keynum) key_return = Double_click + new_keynum*10;         //判断按了2次和两次按键按的一样,返回有效按键值:双击,通过不同的值判断是哪个按键按下的双击
                                        key_state = KEY_STATE_0;                                         //返回 按键状态0,继续等待按键
                                        key_press_nums = 0;                                                                //清空按键次数
                                        key_time_double = 0;                                                        //清空双击计时
                                }
                                if(key_time_double >LONG_KEY_TIME ) key_state = KEY_STATE_3;        //如果长按之后才松开的,则切换到状态3清0
                        }
                        else
                        {      
                                key_time++;                                                                                                        //按键一直按着的话,长按计时
                                if(key_time >= LONG_KEY_TIME)                         //如果按键时间超过 设定的长按时间(LONG_KEY_TIME*10ms=80*10ms=800ms), 则判定为 长按
                                {
                                        key_return = Long_click + new_keynum*10;         //返回有效键值值:长按,通过不同的值判断是哪个按键按下的长按了
                                        //key_state = KEY_STATE_3;                                         //去状态3,等待按键释放
                                }
                        }
                }break;
                case KEY_STATE_3:                                                                                         //等待按键释放
                {
                        if (key_press)
                        {
                                key_state = KEY_STATE_0;                                                 //按键释放后,进入 按键状态0 ,进行下一次按键的判定
                                key_press_nums = 0;                                                                        //清空按键次数
                                key_time_double = 0;                                                                //清空双击计时
                        }
                }break;
                default:key_state = KEY_STATE_0;break;        //特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
        }
        keynum = new_keynum;                                                                                        //将新获取的键值赋值给键值
        return key_return;                                                                                                 //返回 按键值
}


使用特权

评论回复
沙发
kkzz| | 2023-12-5 12:13 | 只看该作者
按键状态判断的函数              

使用特权

评论回复
板凳
burgessmaggie| | 2023-12-5 14:56 | 只看该作者
判断长按和短按,可以利用定时器。

使用特权

评论回复
地板
jonas222| | 2023-12-5 16:02 | 只看该作者
在检测按键状态之前,需要设计去抖动电路或使用软件去抖动算法

使用特权

评论回复
5
abotomson| | 2023-12-5 17:04 | 只看该作者
在实现按键的短按和长按时,需要保证系统的稳定性

使用特权

评论回复
6
hearstnorman323| | 2023-12-5 19:37 | 只看该作者
需要根据按键的输入状态来判断按键是被按下、弹起还是被长按

使用特权

评论回复
7
alvpeg| | 2023-12-6 18:41 | 只看该作者
在实现双击功能时,需要记录按键的按下和弹起的时间,然后根据时间间隔来判断按键是否被双击

使用特权

评论回复
8
gygp| | 2023-12-8 08:24 | 只看该作者
中断可以在按键状态改变时立即处理,而轮询则需要定期检查按键状态。

使用特权

评论回复
9
linfelix| | 2023-12-8 22:12 | 只看该作者
对于短按和双击操作,可以使用电容触发方式;而对于长按操作,可以使用电感触发方式。

使用特权

评论回复
10
abotomson| | 2023-12-9 10:01 | 只看该作者
对于不同的按键状态(如未按、短按、长按、双击),需要定义清晰的状态及其转换条件。

使用特权

评论回复
11
updownq| | 2023-12-9 14:31 | 只看该作者
定义短按、双击、长按的操作方式,例如短按的时间长度、连续按下几次为双击、长按的时间长度等。

使用特权

评论回复
12
adolphcocker| | 2023-12-9 15:06 | 只看该作者
防止按键的误触发,可以在每次检测到按键状态变化后,等待一段时间(比如10ms)再检查一次按键状态

使用特权

评论回复
13
plsbackup| | 2023-12-9 21:00 | 只看该作者
在按下和释放时会有一定的抖动,这可能会导致误操作。

使用特权

评论回复
14
mmbs| | 2023-12-10 18:09 | 只看该作者
在按键按下时,需要等待按键弹起后再进行下一次判断

使用特权

评论回复
15
lzbf| | 2023-12-10 22:34 | 只看该作者
避免使用过多的嵌套结构或重复代码

使用特权

评论回复
16
pentruman| | 2023-12-13 12:51 | 只看该作者
除了软件上的处理,还需要注意硬件上的设计

使用特权

评论回复
17
wengh2016| | 2023-12-13 13:31 | 只看该作者
按键在按下和释放时可能会产生抖动,需要采用滤波或消抖的方式进行处理

使用特权

评论回复
18
alvpeg| | 2023-12-13 15:46 | 只看该作者
按键在按下和弹起时会产生抖动,需要对按键进行消抖处理

使用特权

评论回复
19
fengm| | 2023-12-13 16:41 | 只看该作者
采用外部中断或定时器中断的方式进行检测。

使用特权

评论回复
20
jonas222| | 2023-12-13 17:18 | 只看该作者
使用中断还是轮询机制来检测按键状态,取决于系统的实时性和处理能力需求。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

2420

帖子

2

粉丝