zoukankan      html  css  js  c++  java
  • 矩阵按键的组合按键触发

    /*在做产品时,硬件电路设计中,除了四路输入的要加上拉电阻,四路列输出也应该串入一个470欧左右的限流电阻,否则当同一行的两个按键按下时,很容易烧坏单片机的IO口*/

    /***12个按键,每一个按键都会让蜂鸣器发出“嘀”的一声,同时按下S1和S12会点亮一个LED灯,同时按下S4和S9会熄灭LED灯***/
    #include "REG52.H"
    #define const_voice_short 40
    #define const_key_time 12
    #define const_key_time_comb 14 //组合按键去抖动延时时间
    void initial_myself();
    void initial_peripheral();
    void delay_long(unsigned int uiDelaylong);
    void T0_time();
    void key_service();
    void key_scan();
     
    /*
     任意两个组合按键不能处于同一行,否则触发性能大打折扣。
     做产品的时候,在硬件电路设计中,除了四路行输入要加上拉电阻外,
     四路列输出也应该串入一个470欧左右的限流电阻,否则当一行的两个
     按键同时按下时,很容易烧坏单片机的IO口。
    */
    sbit key_sr1=P0^1; //第一行输入
    sbit key_sr2=P0^2; //第二行输入
    sbit key_sr3=P0^3; //第三行输入
    sbit key_dr1=P0^4; //第一列输出
    sbit key_dr2=P0^5; //第二列输出
    sbit key_dr3=P0^6; //第三列输出
    sbit key_dr4=P0^7; //第四列输出
    sbit led_dr=P3^5; //LED灯
    sbit beep_dr=P1^5;
    unsigned char ucKeyStep=1; //按键扫描步骤变量
    unsigned char ucKeySec=0; //被触发的按键编号
    unsigned int uiKeyTimeCnt[12]=0; //12个按键去抖动延时计数器
    unsigned char ucKeyLock[12]=0; //12个按键触发后自锁的变量标志
    unsigned int uiKeyTimeCnt_01_12=0; //S1和S12组合按键去抖动延时计数器
    unsigned char ucKeyLock_01_12=0; //S1和S12组合按键触发后自锁的变量标志
    unsigned int uiKeyTimeCnt_04_09=0; //S4和S9组合按键去抖动延时计数器
    unsigned char ucKeyLock_04_09=0; //Ss和S9组合按键触发后自锁的变量标志
    unsigned int uiListRecord=1; //记录当前扫描到了第几列
    unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的时间计数器
    unsigned int uiKeyStatus=0xfff; //此变量每一位代表一个按键的状态,共12个按键。1代表没有被按下,0代表被按下
    void main()
    {
     initial_myself();
     delay_long(100);
     initial_peripheral();
     while(1)
     {
      key_service();
     }
    }
    void key_scan()  //按键扫描函数,放到定时中断里
    {
     /*
      第一步:先把16个按键翻译成独立按键。
      第二步:再按独立按键的去抖动方式进行按键识别
      第三步:参考独立按键的方式,来实现组合按键
     */
     switch(ucKeyStep)
     {
      case 1: //把12个按键的状态快速记录在uiKeyStatus变量的每一位中,相当于把矩阵键盘翻译成独立按键
       for(uiListRecord=1;uiListRecord<5;uiListRecord++)
       {
        if(uiListRecord==1) //第一列低电平
        {
      key_dr1=0;
      key_dr2=1;
      key_dr3=1;
      key_dr4=1;
       //如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
       if(key_sr1==0)
        uiKeyStatus=uiKeyStatus&0xffe; //S1被按下
       
       if(key_sr2==0)
        uiKeyStatus=uiKeyStatus&0xfef; //S5被按下
       
       if(key_sr3==0)
        uiKeyStatus=uiKeyStatus&0xeff; //S9被按下  
        }
       
        else if(uiListRecord==2) //第二列低电平
        {
      key_dr1=1;
      key_dr2=0;
      key_dr3=1;
      key_dr4=1;
       //如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
       if(key_sr1==0)
        uiKeyStatus=uiKeyStatus&0xffd; //S2被按下
       
       if(key_sr2==0)
        uiKeyStatus=uiKeyStatus&0xfdf; //S6被按下
       
       if(key_sr3==0)
        uiKeyStatus=uiKeyStatus&0xdff; //S10被按下  
        }
       
        else if(uiListRecord==3) //第三列低电平
        {
      key_dr1=1;
      key_dr2=1;
      key_dr3=0;
      key_dr4=1;
       //如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
       if(key_sr1==0)
        uiKeyStatus=uiKeyStatus&0xffb; //S3被按下
       
       if(key_sr2==0)
        uiKeyStatus=uiKeyStatus&0xfbf; //S7被按下
       
       if(key_sr3==0)
        uiKeyStatus=uiKeyStatus&0xbff; //S11被按下  
        }
       
        else  //第四列低电平
        {
      key_dr1=1;
      key_dr2=1;
      key_dr3=1;
      key_dr4=0;
       //如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
       if(key_sr1==0)
        uiKeyStatus=uiKeyStatus&0xff7; //S4被按下
       
       if(key_sr2==0)
        uiKeyStatus=uiKeyStatus&0xf7f; //S8被按下
       
       if(key_sr3==0)
        uiKeyStatus=uiKeyStatus&0x7ff; //S12被按下  
        }
       }
      ucKeyStep=2; //切换到下一运行步骤
      break;
      
     case 2:  //像独立按键一样进行去抖动和翻译。
      if((uiKeyStatus&0x001)==0x001) //说明1号按键没有被按下
      {
       uiKeyTimeCnt[0]=0;
       ucKeyLock[0]=0;
      }
      else if(ucKeyLock[0]==0)
      {
       uiKeyTimeCnt[0]++;
       if(uiKeyTimeCnt[0]>const_key_time)
       {
        uiKeyTimeCnt[0]=0;
        ucKeyLock[0]=1; //自锁按键,防止不断触发
        ucKeySec=1;  //触发号按键
       }
      }
      
      if((uiKeyStatus&0x002)==0x002) //说明2号按键没有被按下
      {
       uiKeyTimeCnt[1]=0;
       ucKeyLock[1]=0;
      }
      else if(ucKeyLock[1]==0)
      {
       uiKeyTimeCnt[1]++;
       if(uiKeyTimeCnt[1]>const_key_time)
       {
        uiKeyTimeCnt[1]=0;
        ucKeyLock[1]=1; //自锁按键,防止不断触发
        ucKeySec=2;  //触发2号按键
       }
      }
      
      if((uiKeyStatus&0x004)==0x004) //说明3号按键没有被按下
      {
       uiKeyTimeCnt[2]=0;
       ucKeyLock[2]=0;
      }
      else if(ucKeyLock[2]==0)
      {
       uiKeyTimeCnt[2]++;
       if(uiKeyTimeCnt[2]>const_key_time)
       {
        uiKeyTimeCnt[2]=0;
        ucKeyLock[2]=1; //自锁按键,防止不断触发
        ucKeySec=3;  //触发3号按键
       }
      }
      
      if((uiKeyStatus&0x008)==0x00) //说明4号按键没有被按下
      {
       uiKeyTimeCnt[3]=0;
       ucKeyLock[3]=0;
      }
      else if(ucKeyLock[3]==0)
      {
       uiKeyTimeCnt[3]++;
       if(uiKeyTimeCnt[3]>const_key_time)
       {
        uiKeyTimeCnt[3]=0;
        ucKeyLock[3]=1; //自锁按键,防止不断触发
        ucKeySec=4;  //触发4号按键
       }
      }
      
      if((uiKeyStatus&0x010)==0x010) //说明5号按键没有被按下
      {
       uiKeyTimeCnt[4]=0;
       ucKeyLock[4]=0;
      }
      else if(ucKeyLock[4]==0)
      {
       uiKeyTimeCnt[4]++;
       if(uiKeyTimeCnt[4]>const_key_time)
       {
        uiKeyTimeCnt[4]=0;
        ucKeyLock[4]=1; //自锁按键,防止不断触发
        ucKeySec=5;  //触发5号按键
       }
      }
      
      if((uiKeyStatus&0x020)==0x020) //说明6号按键没有被按下
      {
       uiKeyTimeCnt[5]=0;
       ucKeyLock[5]=0;
      }
      else if(ucKeyLock[5]==0)
      {
       uiKeyTimeCnt[5]++;
       if(uiKeyTimeCnt[5]>const_key_time)
       {
        uiKeyTimeCnt[5]=0;
        ucKeyLock[5]=1; //自锁按键,防止不断触发
        ucKeySec=6;  //触发6号按键
       }
      }
      
      if((uiKeyStatus&0x040)==0x040) //说明7号按键没有被按下
      {
       uiKeyTimeCnt[6]=0;
       ucKeyLock[6]=0;
      }
      else if(ucKeyLock[6]==0)
      {
       uiKeyTimeCnt[6]++;
       if(uiKeyTimeCnt[6]>const_key_time)
       {
        uiKeyTimeCnt[6]=0;
        ucKeyLock[6]=1; //自锁按键,防止不断触发
        ucKeySec=7;  //触发7号按键
       }
      }
      
      if((uiKeyStatus&0x080)==0x080) //说明8号按键没有被按下
      {
       uiKeyTimeCnt[7]=0;
       ucKeyLock[7]=0;
      }
      else if(ucKeyLock[7]==0)
      {
       uiKeyTimeCnt[7]++;
       if(uiKeyTimeCnt[7]>const_key_time)
       {
        uiKeyTimeCnt[7]=0;
        ucKeyLock[7]=1; //自锁按键,防止不断触发
        ucKeySec=8;  //触发8号按键
       }
      }
      
      if((uiKeyStatus&0x100)==0x100) //说明9号按键没有被按下
      {
       uiKeyTimeCnt[8]=0;
       ucKeyLock[8]=0;
      }
      else if(ucKeyLock[8]==0)
      {
       uiKeyTimeCnt[8]++;
       if(uiKeyTimeCnt[8]>const_key_time)
       {
        uiKeyTimeCnt[8]=0;
        ucKeyLock[8]=1; //自锁按键,防止不断触发
        ucKeySec=9;  //触发9号按键
       }
      }
      
      if((uiKeyStatus&0x200)==0x200) //说明10号按键没有被按下
      {
       uiKeyTimeCnt[9]=0;
       ucKeyLock[9]=0;
      }
      else if(ucKeyLock[9]==0)
      {
       uiKeyTimeCnt[9]++;
       if(uiKeyTimeCnt[9]>const_key_time)
       {
        uiKeyTimeCnt[9]=0;
        ucKeyLock[9]=1; //自锁按键,防止不断触发
        ucKeySec=10;  //触发10号按键
       }
      }
      
      if((uiKeyStatus&0x400)==0x400) //说明11号按键没有被按下
      {
       uiKeyTimeCnt[10]=0;
       ucKeyLock[10]=0;
      }
      else if(ucKeyLock[10]==0)
      {
       uiKeyTimeCnt[10]++;
       if(uiKeyTimeCnt[10]>const_key_time)
       {
        uiKeyTimeCnt[10]=0;
        ucKeyLock[10]=1; //自锁按键,防止不断触发
        ucKeySec=11;  //触发11号按键
       }
      }
      
      if((uiKeyStatus&0x800)==0x800) //说明12号按键没有被按下
      {
       uiKeyTimeCnt[11]=0;
       ucKeyLock[11]=0;
      }
      else if(ucKeyLock[11]==0)
      {
       uiKeyTimeCnt[11]++;
       if(uiKeyTimeCnt[11]>const_key_time)
       {
        uiKeyTimeCnt[11]=0;
        ucKeyLock[11]=1; //自锁按键,防止不断触发
        ucKeySec=12;  //触发12号按键
       }
      }
      
      
      if((uiKeyStatus&0x801)==0x000) //S1和S12的组合按键被按下
      {
       if(ucKeyLock_01_12==0)
       {
        uiKeyTimeCnt_01_12++;
        if(uiKeyTimeCnt_01_12>const_key_time_comb)
        {
         uiKeyTimeCnt_01_12=0;
         ucKeyLock_01_12=1;
         ucKeySec=13; //触发13号组合按键
        }
       }
      }
      
      else
      {
       uiKeyTimeCnt_01_12=0;
       ucKeyLock_01_12=0;
      }
      
      if((uiKeyStatus&0x108)==0x000) //S4和S9的组合按键被按下
      {
       if(ucKeyLock_04_09==0)
       {
        uiKeyTimeCnt_04_09++;
        if(uiKeyTimeCnt_04_09>const_key_time_comb)
        {
         uiKeyTimeCnt_04_09=0;
         ucKeyLock_04_09=1;
         ucKeySec=14; //触发14号组合按键
        }
       }
      }
      
      else
      {
       uiKeyTimeCnt_04_09=0;
       ucKeyLock_04_09=0;
      }
      
      
      uiKeyStatus=0xfff; //及时恢复状态,方便下一次扫描
      ucKeyStep=1; //返回第一步
      break;
     }
    }

    void key_service() //第三区,按键服务应用程序
    {
     switch(ucKeySec)
     {
      case 1:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      
      case 2:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 3:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 4:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 5:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 6:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 7:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 8:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 9:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 10:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      
      case 11:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 12:
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 13:
       led_dr=0; //LED亮
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;
      case 14:
       led_dr=1; //LED灭
       uiVoiceCnt=const_voice_short;
       ucKeySec=0;
       break;   
      
     }
    }
    void T0_time() interrupt 1
    {
     TF0=0;
     TR0=0;
     
     key_scan();
     
     if(uiVoiceCnt!=0)
     {
      uiVoiceCnt--;
      beep_dr=0;
     }
     else
     {
      ;
      beep_dr=1;
     }
     
     TH0=0xf8;
     TL0=0x2f;
     TR0=1;
    }
    void delay_long(unsigned int uiDelayLong)
    {
     unsigned int i;
     unsigned int j;
     for(i=0;i<uiDelayLong;i++)
      for(j=0;j<500;j++)
       ;
    }
    void initial_myself()
    {
     beep_dr=1;
     TMOD=0x01;
     TH0=0xf8;
     TL0=0x2f;
    }
    void initial_peripheral()
    {
     EA=1;
     ET0=1;
     TR0=1;
    }
  • 相关阅读:
    值传递和引用传递(不是引用类型的传递)的区别
    字符串一旦定义,就表示开辟好了指定的空间,其内容就不可改变
    String类的直接赋值和构造方法赋值的区别
    字符串常量是String类的匿名对象
    Integer和int的区别(转)
    final的好处
    数组引用传递
    构造代码块
    ==和equals()的不同点
    Redis数据类型底层实现
  • 原文地址:https://www.cnblogs.com/TheFly/p/12003797.html
Copyright © 2011-2022 走看看