找回密码
 立即注册
查看: 484|回复: 10

[分享]简单的按键扫描程序

[复制链接]
  • TA的每日心情
    奋斗
    4 小时前
  • 签到天数: 133 天

    [LV.7]常住居民III

    26

    主题

    1302

    回帖

    4061

    积分

    论坛元老

    积分
    4061
    发表于 2024-1-25 14:02:19 | 显示全部楼层 |阅读模式
    分享一个简单的按键扫描程序,方便有需要的用户搜索参考。
    例程使用定时器分时调度,定时每毫秒检测一次按键状态,有按键时累加计数器,没有按键时清除计数器。
    连续计数50次表明按键按下并持续50ms(防抖),设置按键有效状态标志:
    1.     if(!KEY1)
    2.     {
    3.         if(!Key1_Flag)
    4.         {
    5.             Key1_cnt++;
    6.             if(Key1_cnt >= 50)                //50ms防抖
    7.             {
    8.                 Key1_Flag = 1;                        //设置按键状态,防止重复触发
    9.                 Key1_Function = 1;
    10.             }
    11.         }
    12.     }
    13.     else
    14.     {
    15.         Key1_cnt = 0;
    16.         Key1_Flag = 0;
    17.     }
    复制代码

    检测连续1s为低电平则判定按键长按有效;连续低电平时间大于50ms并小于1s则判定为按键短按有效:
    1.     if(!KEY2)
    2.     {
    3.         if(!Key2_Flag)
    4.         {
    5.             Key2_cnt++;
    6.             if(Key2_cnt >= 1000)                //长按1s
    7.             {
    8.                 Key2_Short_Flag = 0;        //清除短按标志
    9.                 Key2_Long_Flag = 1;                //设置长按标志
    10.                 Key2_Flag = 1;                                //设置按键状态,防止重复触发
    11.                 Key2_Long_Function = 1;
    12.             }
    13.             else if(Key2_cnt >= 50)                //50ms防抖
    14.             {
    15.                 Key2_Short_Flag = 1;                //设置短按标志
    16.             }
    17.         }
    18.     }
    19.     else
    20.     {
    21.         if(Key2_Short_Flag)                        //判断是否短按
    22.         {
    23.             Key2_Short_Flag = 0;        //清除短按标志
    24.             Key2_Short_Function = 1;
    25.         }
    26.         Key2_cnt = 0;
    27.         Key2_Flag = 0;        //按键释放
    28.     }
    29. }
    复制代码


    此外,推荐一份社区大神分享的按键扫描方法介绍的帖子:
    【分享】按键程序,大道至简,按键扫描 + 累计主循环次数去抖动/不占用定时器
    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=5936
    (出处: 国芯论坛-STC全球32位8051爱好者互助交流社区)

    IO口做按键扫描.zip

    9.37 KB, 下载次数: 26

    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    半小时前
  • 签到天数: 127 天

    [LV.7]常住居民III

    4

    主题

    45

    回帖

    274

    积分

    中级会员

    积分
    274
    发表于 2024-1-25 14:42:46 | 显示全部楼层
    这种长按程序和短按程序是相互独立的,且长按程序在每次长按操作中只执行一次。(希望没有分析错误)
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    12 小时前
  • 签到天数: 142 天

    [LV.7]常住居民III

    15

    主题

    542

    回帖

    1978

    积分

    金牌会员

    打工人

    积分
    1978
    发表于 2024-1-25 17:30:30 | 显示全部楼层
    这种写法是不是受程序周期影响啊,程序周期不固定怎么办
    打工人
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    4 小时前
  • 签到天数: 133 天

    [LV.7]常住居民III

    26

    主题

    1302

    回帖

    4061

    积分

    论坛元老

    积分
    4061
     楼主| 发表于 2024-1-25 18:52:07 | 显示全部楼层
    zhudean11 发表于 2024-1-25 17:30
    这种写法是不是受程序周期影响啊,程序周期不固定怎么办

    那需要估算一下多长时间调用一次按键扫描程序,检测次数*检测周期=20~50ms左右。
    这个帖子有介绍如何检测循环周期:
    【分享】按键程序,大道至简,按键扫描 + 累计主循环次数去抖动/不占用定时器
    https://www.stcaimcu.com/forum.php?mod=viewthread&tid=5936
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    12 小时前
  • 签到天数: 142 天

    [LV.7]常住居民III

    15

    主题

    542

    回帖

    1978

    积分

    金牌会员

    打工人

    积分
    1978
    发表于 2024-1-26 08:54:57 | 显示全部楼层
    乘风飞扬 发表于 2024-1-25 18:52
    那需要估算一下多长时间调用一次按键扫描程序,检测次数*检测周期=20~50ms左右。
    这个帖子有介绍如何检测 ...

    感谢分享,学习一下,谢谢!
    打工人
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    5 小时前
  • 签到天数: 125 天

    [LV.7]常住居民III

    12

    主题

    315

    回帖

    886

    积分

    高级会员

    积分
    886
    发表于 2024-1-26 09:03:41 | 显示全部楼层
    感谢分享
    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 小时前
  • 签到天数: 160 天

    [LV.7]常住居民III

    0

    主题

    46

    回帖

    267

    积分

    中级会员

    积分
    267
    发表于 2024-1-27 08:15:54 | 显示全部楼层
    学习了
    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:46
  • 签到天数: 117 天

    [LV.6]常住居民II

    8

    主题

    67

    回帖

    690

    积分

    高级会员

    积分
    690
    发表于 2024-2-2 13:40:43 | 显示全部楼层
    typedef union{
            u8 dat;
            struct{
                    u8 bit0:1;
                    u8 bit1:1;
                    u8 bit2:1;
                    u8 bit3:1;
                    u8 bit4:1;
                    u8 bit5:1;
                    u8 bit6:1;
                    u8 bit7:1;
            } bits;
    }Key_data;

    #define   Key1  ( P70 )
    #define   Key2  ( P71 )
    #define   Key3  ( P72 )
    #define   Key4  ( P73 )
    #define   Key5  ( P41 )
    #define   Key6  ( P42 )
    void  Key_scan(void)
    {
            u8 i,n;
           
            keydat.dat = 0xFF;
            Write_Key();
            NOP40();
            Read_Key();
            if( keydat.dat != 0xFF)                        //有按键按下
            {
                    Key.flag = 1;
                    n = keydat.dat;
                    for(i=0; i<6; i++)                        //轮询找出哪个按键被按下
                    {
                            if((n & 0x01) == 0)
                            {
                            //        Key.state[i] = 1;        //状态
                                    Key.value[i] = 2;        //有效值
                            }
                            else
                            {
                            //        Key.state[i] = 0;        //状态
                                    Key.value[i] = 0;        //有效值
                                    Key.count[i] = 0;        //次数清零                       
                            }
                            n = n>>1;                                //数据移位
                    }       
            }
            else                                                        //没有按键按下
            {
                    Key.flag = 0;                                //没有按键按下
                    for(i=0; i<6; i++)               
                            Key.value[i] = 0;
            }
    }



    void Read_Key(void)
    {
            keydat.bits.bit0 = Key1;
            keydat.bits.bit1 = Key2;
            keydat.bits.bit2 = Key3 ;
            keydat.bits.bit3 = Key4;
            keydat.bits.bit4 = Key5;
            keydat.bits.bit5 = Key6;
    }


    void Write_Key(void)
    {
            Key1 = keydat.bits.bit0;
            Key2 = keydat.bits.bit1;
            Key3 = keydat.bits.bit2;
            Key4 = keydat.bits.bit3;
            Key5 = keydat.bits.bit4;
            Key6 = keydat.bits.bit5;
    }
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:46
  • 签到天数: 117 天

    [LV.6]常住居民II

    8

    主题

    67

    回帖

    690

    积分

    高级会员

    积分
    690
    发表于 2024-2-2 13:41:40 | 显示全部楼层
    小坤 发表于 2024-2-2 13:40
    typedef union{
            u8 dat;
            struct{

    typedef struct {
            u8 flag;
        u8 state[6];
            u8 value[6];
            u16 count[6];
            u16 Time[6];
    }xdata Key_conf;
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    5 小时前
  • 签到天数: 56 天

    [LV.5]常住居民I

    11

    主题

    28

    回帖

    251

    积分

    中级会员

    积分
    251
    发表于 2024-4-3 18:12:47 | 显示全部楼层
    一楼的我认为不能使用。首先 计数没有清零!这个不是问题好解决。但是如果第一个延时到了  标志变成1.但是这个时候如果按键放开了,进入中断的时候直接进入else  标志被清零。我实际测试这个也是  根本没法使用
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-6 13:39 , Processed in 0.074555 second(s), 68 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表