梦的飞翔 发表于 2012-4-8 13:52:42

郭天祥51单片机 矩阵键盘的程序问题,求解

要求如下:在没有键摁下的情况下,数码管没有显示。但是每摁下一个键后,会在六个数码上同时显示相同的数字,释放是数码管灭掉。

下面是我写的一个程序,运行的结果不对,没键摁下是数码管也有显示,键被摁下之后被释放,数码管依然有显示,这个问题要怎么解决呀?进主函数我就把数码管的位选全部关掉了,结果数码管是乱码,怎么回事???求高手解决

#include<reg52.h>
#define uchar unsigned char
#define uintunsigned int
sbit wela=P2^7;
sbit dula=P2^6;
uchar code table[]=
{0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar temp,num;

uchar keyscan();
void display(uchar aa);
void delay(uint z);

//主函数
void main()
{

        wela=1;
        P0=0xc0;    //开所有位选
        wela=0;

        dula=1;
        P0=0x00;
        dula=0;

        while(1)
                {
                        display(keyscan());
                }       
}
//延时函数
void delay(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
//键盘扫描函数
uchar keyscan()
{
                        P3=0xfe;
                        temp=P3;
                        temp=temp&0xf0;
                        if(temp!=0xf0)
                                {
                                        delay(8);                   //去抖
                                        temp=P3;
                                        temp=temp&0xf0;
                                        if(temp!=0xf0)
                                                {
                                                        temp=P3;
                                                        switch(temp)
                                                                {
                                                                        case 0xee:num=0;break;
                                                                        case 0xde:num=1;break;
                                                                        case 0xbe:num=2;break;
                                                                        case 0x7e:num=3;break;       
                                                                }
                                                }
                                }

                        P3=0xfd;
                        temp=P3;
                        temp=temp&0xf0;
                        if(temp!=0xf0)
                                {
                                        delay(8);                   //去抖
                                        temp=P3;
                                        temp=temp&0xf0;
                                        if(temp!=0xf0)
                                                {
                                                        temp=P3;
                                                        switch(temp)
                                                                {
                                                                        case 0xed:num=4;break;
                                                                        case 0xdd:num=5;break;
                                                                        case 0xbd:num=6;break;
                                                                        case 0x7d:num=7;break;       
                                                                }
                                                }
                                }

                        P3=0xfb;
                        temp=P3;
                        temp=temp&0xf0;
                        if(temp!=0xf0)
                                {
                                        delay(8);                   //去抖
                                        temp=P3;
                                        temp=temp&0xf0;
                                        if(temp!=0xf0)
                                                {
                                                        temp=P3;
                                                        switch(temp)
                                                                {
                                                                        case 0xeb:num=8;break;
                                                                        case 0xdb:num=9;break;
                                                                        case 0xbb:num=10;break;
                                                                        case 0x7b:num=11;break;       
                                                                }
                                                }
                                }

                        P3=0xf7;
                        temp=P3;
                        temp=temp&0xf0;
                        if(temp!=0xf0)
                                {
                                        delay(8);                   //去抖
                                        temp=P3;
                                        temp=temp&0xf0;
                                        if(temp!=0xf0)
                                                {
                                                        temp=P3;
                                                        switch(temp)
                                                                {
                                                                        case 0xe7:num=12;break;
                                                                        case 0xd7:num=13;break;
                                                                        case 0xb7:num=14;break;
                                                                        case 0x77:num=15;break;       
                                                                }
                                                }
                                }
        return num;       
}

//数码管显示函数
void display(uchar aa)
{
                dula=1;
                P0=table;
                dula=0;       
}

冷月无声 发表于 2012-4-11 13:14:10

uchar code table[]={。。。。。。0x00};第十七个数设为0x00,num默认为设置为16,主程序如下      while(1)
               {
                         display(keyscan());
                                               display(num);
                                               num=16;
               }

yanshanbao 发表于 2012-6-6 13:19:00

{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}{:smile:}

yao1 发表于 2012-6-6 21:31:19

本帖最后由 yao1 于 2012-6-6 21:35 编辑

看的头大 给你个看看
//////////////////////////////////////////////////////////////////////////////////
//扫描法:逐行扫描查询 一般用在按键比较少的场合
int keyscan()
{
      unsigned char k, k_temp;
      P1=0xf0;      //低位置0,准备查询按键
      k=P1;         //取得当前P1口状态
      if(k!=0xf0)   //如果有变化则表示有按键按下
      {
            delay(10);    //延迟 消抖
            k_temp=p1;
            if(k==k_temp)//确实有键按下
            {
                  k=0xfe;
                  do         //循环扫描每一行
                  {
                         p1=k;
                         if(k!=p1)
                         {
                           switch(P1)//判断按键 并返回键值
                            {
                                     //第1行
                                     case 0x7e:{return 0; break;}
                                     case 0xbe:{return 1; break;}
                                     case 0xde:{return 2; break;}
                                     case 0xee:{return 3; break;}
                                     //第2行
                                     case 0x7d:{return 4; break;}
                                     case 0xbd:{return 5; break;}
                                     case 0xdd:{return 6; break;}
                                     case 0xed:{return 7; break;}
                                     //第3行
                                     case 0x7b:{return 8; break;}
                                     case 0xbb:{return 9; break;}
                                     case 0xdb:{return 10;break;}
                                     case 0xeb:{return 11;break;}
                                     //第4行
                                     case 0x77:{return 12;break;}
                                     case 0xb7:{return 13;break;}
                                     case 0xd7:{return 14;break;}
                                     case 0xe7:{return 15;break;}
                                  }                                                                                 
                            }
                            k=_crol_(k,1);   //移位 进入下一行扫描               
               }
                     while(k!=0xef); //超过列范围 退出扫描                        
          }         
       }
}
////////////////////////////////////////////////////////////////////////////////
//线反转法 :只需2步便可获得按键位置,最常用
unsigned intkeyboar()/*线反转法 */
{
      static unsigned int a=0;
      unsigned char a1=0,b1=0;
    /*行线为输入线,列线为输出线 */
      v1=v2=v3=v4=0;
      h1=h2=h3=h4=1;
      if(P2<0xf0)/*检查行是否有按键按下 */
      {
             delayms(10);
             if(P2<0xf0)
             {
                  /*行线为输入线,列线为输出线 */
                  v1=v2=v3=v4=0;
                  h1=h2=h3=h4=1;
                  a1=P2;
                  /*行线为输出线,列线为输入线 */
                  h1=h2=h3=h4=0;
                  v1=v2=v3=v4=1;
                  b1=P2;
         
                  a=a1|b1;
             }   
       }   
       if       (a==0xe7) {return 1;}
       else if(a==0xeb) { return 2;}
       else if(a==0xed) { return 3;}
       else if(a==0xee) { return 4;}               
      
       else if(a==0xd7) {return 5; }
       else if(a==0xdb) {return 6; }
       else if(a==0xdd) {return 7; }
       else if(a==0xde) {return 8; }   
      
       else if(a==0xb7) {return 9;}
       else if(a==0xbb) {return 10;}
       else if(a==0xbd) {return 11;}
       else if(a==0xbe) {return 12;}
      
       else if(a==0x77) {return 13;}
       else if(a==0x7b) {return 14;}
       else if(a==0x7d) {return 15;}
       else if(a==0x7e) {return 16;}   
      
       else return 17;                  
}

yesful 发表于 2012-6-6 22:27:50

楼主这程序本来就是一直显示的,因为天详的板子的位选是会被锁存住的,你在进入大循环前,就已经P0=0xc0;    //开所有位选了,并且被573锁存住,当初始上电时,num被初始化为0,所以应该显示0,当有键按下,和释放按键之后,num都维持被按下的那个数,所以都会一直显示~~~建议你在keyscan()里,当有键按下时,返回被按下值,没键按下里,返回一个无键按下标志,在display(uchar aa)里,判断aa,如果aa是无键按下标志,则关闭位选,不显示,如果是有键按下,则显示相应值。


yesful 发表于 2012-6-6 22:43:19

uchar num; 51单片机中变量不赋初值,初始化时将是什么值?如果初始化为0,则一开始显示应该是0,如果不是0,是任意一个数,那初始上电,就有可能像你说的那样显示乱码~~~好久没用51了,没有板子测试一下~~希望楼主测试一下~~

掠辰影 发表于 2012-8-24 19:54:29

矩阵键盘超级难理解。。。楼主现在懂了吗?求教啊!

akion78 发表于 2012-8-24 21:51:11

先扫描行,再扫描列
页: [1]
查看完整版本: 郭天祥51单片机 矩阵键盘的程序问题,求解