找回密码
 立即注册
查看: 1986|回复: 20

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

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 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, 下载次数: 153

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-05-01 14:39:53
已绑定手机

5

主题

49

回帖

1179

积分

金牌会员

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:487
  • 最近打卡:2025-05-01 15:22:54
已绑定手机

27

主题

693

回帖

1950

积分

金牌会员

打工人

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

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

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:487
  • 最近打卡:2025-05-01 15:22:54
已绑定手机

27

主题

693

回帖

1950

积分

金牌会员

打工人

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

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2025-04-29 08:28:43

12

主题

319

回帖

2017

积分

金牌会员

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:430
  • 最近打卡:2025-04-30 08:03:31
已绑定手机

0

主题

56

回帖

506

积分

高级会员

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

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:375
  • 最近打卡:2025-04-26 15:51:33
已绑定手机

27

主题

301

回帖

822

积分

高级会员

积分
822
发表于 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;
}
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:375
  • 最近打卡:2025-04-26 15:51:33
已绑定手机

27

主题

301

回帖

822

积分

高级会员

积分
822
发表于 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;
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:385
  • 最近打卡:2025-05-01 08:05:45

25

主题

113

回帖

725

积分

高级会员

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

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 19:49 , Processed in 0.226591 second(s), 122 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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