hsh829 发表于 2015-5-21 11:21:40

矩阵键盘扫描偶尔经常死机,重启电源就好了

最近做个矩阵键盘扫描的程序,但偶尔会死机(按键无反应),重新关+开电源又可以按了,按键扫描取消松手检测,是用标志位(flag_hsh)判定的,PA口高4位加了10K上拉电阻,请帮忙分析一下
uchar key_press(void)
{
   uchar i;
   DDRA = 0XFF;
       PORTA = 0XF0;
       DDRA = 0X0F;
          _NOP();
       i = PINA;
       if(i==0XF0)
       {
           DDRA=0XFF;
           flag_hsh=1;      //没有键按下,按键标志位置1
           return 0;
       }
       else
       {
           DDRA=0XFF;
           return 1;
       }
}

uchar key_scan(void)
{
   uchar keycode=0x12,i=0X7F,j,k1=0x13,k2=0x14,k3=0x15,k4=0x16,k5=0x17,k6=0x18,k7=0x19,k8=0x20,a=0,k=0x21;
   delayms(50);
          if(key_press()&(flag_hsh==1))
                               {
                                         flag_hsh=0;   //把按键按键标志位置0,防止按键没松开时重复进入扫描程序。
                                         delayms(2);
                                  if(key_press())
                                  {
                                          delayms(4);
                                     if(key_press())
                                      {
                                              delayms(5);
                                     if(key_press())
                                        {
                                                delayms(6);
                                                   if(key_press())
                                                                                       {
                                                                                       for(a=0;a<8;a++)    //再重复检测8次,看看每次是否每次检测到的值都一样
                                                                                              {
                                                                                                  do
                                                                                                                {
                                                                                                                       i=(i<<1|i>>7);
                                                                                                                       PORTA=i;
                                                                                                                       DDRA=0X0F;
                                                                                                                       _NOP();
                                                                                                                       k=PINA;
                                                                                                                       j=k&0XF0;
                                                                                                  }while(j==0XF0);//此处下面取消松手检测
                                                                                                  switch(a)
                                                                                                  {
                                                                                                          case 0: k1=k;break;
                                                                                                          case 1: k2=k;break;
                                                                                                          case 2: k3=k;break;
                                                                                                          case 3: k4=k;break;
                                                                                                          case 4: k5=k;break;
                                                                                                          case 5: k6=k;break;
                                                                                                          case 6: k7=k;break;
                                                                                                          case 7: k8=k;break;
                                                                                                          default:break;
                                                                                                  }
                                                                                                  delayms(2);
                                                                                           }
                                                                                  if((k1==k2)&&(k2==k3)&&(k3==k4))   //检测8次看看每次是否每次检测到的值都一样
                                                                                          {
                                                                                                  if((k4==k5)&&(k5==k6)&&(k6==k7)&&(k7==k8))//检测8次看看是否每次检测到的值都一样
                                                                                                          {
                                                                                                                          keycode=k8;
                                                                                                                          if(open_num==0)//设置标志位,只在第一次按键的时候执行下面的语句,按下结束按键时open_num已清零
                                                                                                                                          {
                                                                                                                                                  PORTB=0x00;
                                                                                                                                                  PORTD=0x04;      //INT0口设置为高电平
                                                                                                                                                  led_zong=0;
                                                                                                                                                led_fen=0;
                                                                                                                                                led_dianya=0;
                                                                                                                                                  TCCR1B = 0x02;//启动定时器
                                                                                                                                          }
                                                                                                                                  open_num=1;
                                                                                                          }
                                                                                          }
                                                                                  }
                                                                                  }
                                                                  }
                                                               }
                                                        }
                return keycode;
}

hsh829 发表于 2015-5-21 11:22:30

自己先检查一下,谢谢大家

xiaodao35 发表于 2015-5-21 11:45:19

我是在在2mS定时器中断中加这个

本帖最后由 xiaodao35 于 2015-5-21 11:48 编辑

        tempport=LPC_GPIO0->FIOPIN2&0x0e;                        //读取key0-key2数据(p0.17,18,19)
        tempport=tempport>>1;
        for(temp=0;temp<3;temp++)
        {
                keynum++;                                //假设按键按下
                if( (tempport & (1<<temp)) == 0 )                //没有按键按下
                keynum=0;       
        }
        for(temp=0;temp<9;temp++)
        {
                if(keynum>MAXKEY)                                        //按键计数到
                {
                        keynum=0;       
                        keybuf=temp;                                                //得到键值                                       
                       break;
                }
        }

        scankey=(scankey+1)%3;
        temp=Keyscan;
        LPC_GPIO0->FIOPIN2 = (LPC_GPIO0->FIOPIN2 & 0x8f) | temp;                        //扫描输出

编辑原因,贴的程序注释乱了

Firman 发表于 2015-5-21 13:14:45

矩阵扫描,输出品一般要选OPEN-DRAIN模式,
若没有OPEN-DRAIN模式,那么逐行扫描时,只有一个输出口,其它输出口的改为输入模式.

你想,若PUSH-PULL输出,一个口输出高,一个口输出低,按它们短路,单片机会怎么样?

hsh829 发表于 2015-5-21 20:49:23

继续学习
页: [1]
查看完整版本: 矩阵键盘扫描偶尔经常死机,重启电源就好了