乘风飞扬 发表于 2024-1-25 14:02:19

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

分享一个简单的按键扫描程序,方便有需要的用户搜索参考。
例程使用定时器分时调度,定时每毫秒检测一次按键状态,有按键时累加计数器,没有按键时清除计数器。
连续计数50次表明按键按下并持续50ms(防抖),设置按键有效状态标志:
    if(!KEY1)
    {
      if(!Key1_Flag)
      {
            Key1_cnt++;
            if(Key1_cnt >= 50)                //50ms防抖
            {
                Key1_Flag = 1;                        //设置按键状态,防止重复触发
                Key1_Function = 1;
            }
      }
    }
    else
    {
      Key1_cnt = 0;
      Key1_Flag = 0;
    }
检测连续1s为低电平则判定按键长按有效;连续低电平时间大于50ms并小于1s则判定为按键短按有效:
    if(!KEY2)
    {
      if(!Key2_Flag)
      {
            Key2_cnt++;
            if(Key2_cnt >= 1000)                //长按1s
            {
                Key2_Short_Flag = 0;      //清除短按标志
                Key2_Long_Flag = 1;                //设置长按标志
                Key2_Flag = 1;                              //设置按键状态,防止重复触发
                Key2_Long_Function = 1;
            }
            else if(Key2_cnt >= 50)                //50ms防抖
            {
                Key2_Short_Flag = 1;                //设置短按标志
            }
      }
    }
    else
    {
      if(Key2_Short_Flag)                        //判断是否短按
      {
            Key2_Short_Flag = 0;      //清除短按标志
            Key2_Short_Function = 1;
      }
      Key2_cnt = 0;
      Key2_Flag = 0;      //按键释放
    }
}

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

遥指杏花村 发表于 2024-1-25 14:42:46

这种长按程序和短按程序是相互独立的,且长按程序在每次长按操作中只执行一次。(希望没有分析错误)

zhudean11 发表于 2024-1-25 17:30:30

这种写法是不是受程序周期影响啊,程序周期不固定怎么办

乘风飞扬 发表于 2024-1-25 18:52:07

zhudean11 发表于 2024-1-25 17:30
这种写法是不是受程序周期影响啊,程序周期不固定怎么办

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

zhudean11 发表于 2024-1-26 08:54:57

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

感谢分享,学习一下,谢谢!

jwg 发表于 2024-1-26 09:03:41

感谢分享

yinds 发表于 2024-1-27 08:15:54

{:4_174:}学习了

小坤 发表于 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 )
voidKey_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 = 1;        //状态
                                Key.value = 2;        //有效值
                        }
                        else
                        {
                        //        Key.state = 0;        //状态
                                Key.value = 0;        //有效值
                                Key.count = 0;        //次数清零                       
                        }
                        n = n>>1;                                //数据移位
                }       
        }
        else                                                        //没有按键按下
        {
                Key.flag = 0;                                //没有按键按下
                for(i=0; i<6; i++)               
                        Key.value = 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;
}

小坤 发表于 2024-2-2 13:41:40

小坤 发表于 2024-2-2 13:40
typedef union{
        u8 dat;
        struct{


typedef struct {
        u8 flag;
    u8 state;
        u8 value;
        u16 count;
        u16 Time;
}xdata Key_conf;

zhang32568 发表于 2024-4-3 18:12:47

一楼的我认为不能使用。首先 计数没有清零!这个不是问题好解决。但是如果第一个延时到了标志变成1.但是这个时候如果按键放开了,进入中断的时候直接进入else标志被清零。我实际测试这个也是根本没法使用
页: [1] 2 3
查看完整版本: [分享]简单的按键扫描程序