矩阵按键扫描并且识长按与短按

5 篇文章 0 订阅
5 篇文章 0 订阅

在单片机IO口不够用、又需要较多的按键时,我们经常采取的解决办法是矩阵扫描按键,从而提高按键的数量,但有些时候我们想既要实现短按,又要实现长按,碍于是矩阵轮询扫描的方式,这就有点麻烦了,因为这两个键值比较容易冲突。

网上关于矩阵按键的教程有很多,关于长按短按识别也很多,但是关于矩阵按键扫描并且识长按与短按的例子比较少,所以我决定再次贴上自己的代码,该代码是从网上找来的程序基础上修改而来的,经测试可正常使用。
(如有更优秀的方法,欢迎讨论和指正)
注:该代码所扫描的按键是7行*3列,常驻高电平,按下为低电平。

//长短键判断函数,调用按键扫描函数
uint8 Discern_KeyScan(void)
{
    static uint8 Old_key   = 0;//上次按键值
    static uint8 Key_buf   = 0;//按键有效保存
    static uint8 Press_CNT = 0;//按键按下时间,根据调用时间间隔确定
    static uint8 longkey   = 0;//记录长按键值
    uint8 New_key          = 0;//当前按键值
    uint8 KEY              = 0;//待返回的按键值
     
    New_key = KeyScan();       //扫描一次键盘状态
    
    if((s_TimerATCB.Delay10MS_Flag == true))  //10mS消抖   
    {
      s_TimerATCB.Delay10MS_Flag = false;     //按下后10MS标志位清零 
      if(New_key == Old_key)
      {
        if(New_key != 0)   //建议keyscan返回0的那个值改为其他值,方便这里判断
        {
            Key_buf = New_key;
            if(Press_CNT < 0xff)
            {
                Press_CNT ++;
            }
            if(Press_CNT >= 100)//调用时间间隔确定 * 100为长按时间,
            {
                KEY = Key_buf + 100;       //将短键+100作长键区分 
                if(KEY==longkey)return 0;  //连续长按只执行一次长按
                longkey=KEY;               //记录长按键值
                Press_CNT = 0;             //按键时间清0
                Key_buf   = 0;             //按键缓冲清0
            }
            else if(Press_CNT < 100)       //短按弹起
            {
               if(KeyScan()==0)            //如果按键已经松开
               {
                  KEY = Key_buf;  //短按值
                  Key_buf = 0;    //清按键缓冲
                  longkey = 0;    //清除上一次长按 
                  Press_CNT = 0;  //按键弹起或按其他按键,将长按时间清0
               }
            }
        }
        else //无按键操作或长按弹起
        {       
            if(Key_buf==longkey-100)
            {
               Press_CNT = 0;  //按键弹起或按其他按键,将长按时间清0
               Key_buf = 0;    //清按键缓冲
               return 0;       //防止长按后又执行一次短按   
            }
            if(Key_buf)
            {   
                KEY = Key_buf; //将缓冲值送将返回的值
                Key_buf = 0;   //清按键缓冲
            }
            longkey = 0;       //清除上一次长按 
            Press_CNT = 0;     //按键弹起或按其他按键,将长按时间清0
        }
      }
      Old_key = New_key;       //将新按键赋给下一次的旧按键值
    }  
    return KEY;  //0代表无按键
}

//按键状态扫描,返回键值
uint8 KeyScan(void)     
{
  uint8 i;
  uint8 keynum=0;
  
  for(i=0;i<=6;i++)  //扫描7行按键
  {
     RowLow(i);      //循环拉低一行
     
     if(line1==1)    //扫描第一列按键
     {
        switch(i)
        {
        case 0:  keynum=3;   break;    //返回键值
        case 1:  keynum=6;   break;    //返回键值
        case 2:  keynum=9;   break;    //返回键值
        case 3:  keynum=12;  break;    //返回键值
        case 4:  keynum=15;  break;    //返回键值
        case 5:  keynum=18;  break;    //返回键值
        case 6:  keynum=21;  break;    //返回键值  
        }
     }
     else if(line2==1)//扫描第二列按键
     {
        switch(i)
        {
        case 0:  keynum=2;   break;    //返回键值
        case 1:  keynum=5;   break;    //返回键值
        case 2:  keynum=8;   break;    //返回键值
        case 3:  keynum=11;  break;    //返回键值
        case 4:  keynum=14;  break;    //返回键值
        case 5:  keynum=17;  break;    //返回键值
        case 6:  keynum=20;  break;    //返回键值  
        }
     }
     else if(line3==1)//扫描第三列按键
     {
        switch(i)
        {
        case 0:  keynum=1;   break;    //返回键值
        case 1:  keynum=4;   break;    //返回键值
        case 2:  keynum=7;   break;    //返回键值
        case 3:  keynum=10;  break;    //返回键值
        case 4:  keynum=13;  break;    //返回键值
        case 5:  keynum=16;  break;    //返回键值
        case 6:  keynum=19;  break;    //返回键值  
        }
     }
  }
  return keynum;
}


//置一行按键为低电平 
void RowLow(uint8 num)
{
   switch(num)
   {
      case 0:
          row1_L;  row2_H;  row3_H;  row4_H;
          row5_H;  row6_H;  row7_H;  break;
      case 1:
          row1_H;  row2_L;  row3_H;  row4_H;
          row5_H;  row6_H;  row7_H;  break;
      case 2:
          row1_H;  row2_H;  row3_L;  row4_H;
          row5_H;  row6_H;  row7_H;  break;
      case 3:
          row1_H;  row2_H;  row3_H;  row4_L;
          row5_H;  row6_H;  row7_H;  break;
      case 4:
          row1_H;  row2_H;  row3_H;  row4_H;
          row5_L;  row6_H;  row7_H;  break;
      case 5:
          row1_H;  row2_H;  row3_H;  row4_H;
          row5_H;  row6_L;  row7_H;  break;
      case 6:
          row1_H;  row2_H;  row3_H;  row4_H;
          row5_H;  row6_H;  row7_L;  break;
   } 
}

在这里插入图片描述
部分代码引用于:https://zhidao.baidu.com/question/584147183.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值