51单片机独立和矩阵按键(有无中断定时器)待补充ing

本文详细介绍了四种单片机按键处理方法:无中断定时器独立按键、无中断定时器矩阵按键、有中断定时器独立按键及有中断定时器矩阵按键。探讨了按键状态检测、消除抖动、矩阵编码等关键技术,适用于嵌入式系统设计中按键控制的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


——————鄙人萌新,欢迎交流,完善代码。

一、无中断定时器独立按键

if不能嵌套,我之前嵌套一下,后来发现当key0==0(按下)
是不允许有key==1(弹起),如果按下里面有弹起则视为抖动,
所以不能嵌套。

void key()
    {
      if(key0==0&&flag==0)
      {
        flag=1;
      }
      if(flag==1&&key0==1)
      {
          num++;
          flag=0;         
      }      
    }

二、无中断定时器矩阵按键

用矩阵编码形式进行赋值传递 0x0f 和 0xf0 
分别作为L低位H高位的初始值
edb7和edb7的排列组合
1111 0000 :0xf0
0000 1111 :0x0f
按下即为0(分别判断L位和H位)
void key_scan()
  {     unsigned char temp0=0,temp1=0,temp=0;
        P1=0xf0;
     if(P1!=0xf0)
     {
        delay(20);
        temp0=P1;
        P1=0x0f;
        if(P1!=0x0f)
        {
           temp1=P1;
        }
     }  
        temp=temp0+temp1;
      if(temp==0xee)
    {
       num=0;
    }
    if(temp==0xed)
    {
       num=1;
    }
    if(temp==0xeb)
    {
       num=2;
    }
    if(temp==0xe7)
    {
       num=3;
    }
    if(temp==0xde)
    {
       num=4;
    }

三、有中断定时器独立按键

bit keysta = 1;//当前值
 bit backup = 1; //前次备份值
   void key()
   {       
     if(keysta != backup) //说明按键有动作
     {     
       if(backup == 0)//前次值为0,则当前值为1(弹起动作)
       {
         num++;         
         if(num>=10)
         {
           num = 0;
         }  
         P2 = str[num];              
       }  
         backup = keysta;//更新备份值为当前值,循环时进行比较 
     }  
   }

/* T0 中断服务函数,用于按键状态的扫描并消抖 */
   void InterruptTime0() interrupt 1
   {
     static unsigned char keybuf = 0xff;//按键抖动扫描缓冲区8位,
                                       //保留16ms里面的缓冲扫描值
     TH0 = 0xF8; //重新加载初值2ms
     TL0 = 0xCD;
     keybuf = (keybuf<<1)|key0;//(0000000key0|xxxxxxx0) → key0
                             //是1就是1,是0就是0(或运算)
     if(keybuf == 0x00)  //八位16ms都是0
     {
       keysta = 0;
     }
     else if(keybuf == 0xFF)
     {
       keysta = 1;
     }
     else
     {}//其余情况代表未稳定,不做判断
   }

四、有中断定时器矩阵按键

矩阵行和列检测是否按下,每一行进行4ms,4行全部检测时间16ms
void key()
  {    
    for(i=0;i<4;i++)
    {
      for(j=0;j<4;j++)
      {
        if(backup[i][j] != keysta[i][j])
        {
          if(backup[i][j] == 0)
          {
            P2 = str[i*4+j];
          }
            backup[i][j] = keysta[i][j];
        }
      }
    }
  }
void InterruptTime0() interrupt 1
  {
     static unsigned char keybuf[4][4] = {
      {0xFF, 0xFF, 0xFF, 0xFF},
      {0xFF, 0xFF, 0xFF, 0xFF},
      {0xFF, 0xFF, 0xFF, 0xFF},
      {0xFF, 0xFF, 0xFF, 0xFF}};
     static unsigned char keyout = 0;
     unsigned char k ;
     TH0 = 0xFC;
     TL0 = 0x67;
     keybuf[keyout][0] = (keybuf[keyout][0] << 1) | L0;
     keybuf[keyout][1] = (keybuf[keyout][1] << 1) | L1;
     keybuf[keyout][2] = (keybuf[keyout][2] << 1) | L2;
     keybuf[keyout][3] = (keybuf[keyout][3] << 1) | L3;
  //检测 L 列 + 选择 H 行
  for(k=0;k<4;k++)
    {
      if((keybuf[keyout][k] & 0x0F) == 0x00)
      {
        keysta[keyout][k] = 0;
      }
      if((keybuf[keyout][k] & 0x0F) == 0x0F)
      {
        keysta[keyout][k] = 1;
      }
    }
    keyout++;
    keyout = keyout & 0x03;//小技巧:到四归零
    switch(keyout)//选择H行
    {
      case 0: H0 = 0; H3 = 1;break;
      case 1: H1 = 0; H0 = 1;break; 
      case 2: H2 = 0; H1 = 1;break;
      case 3: H3 = 0; H2 = 1;break;
      default:break; 
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值