打印

矩阵键盘为什么按键与否都要执行呢?

[复制链接]
2686|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xichandoujigu|  楼主 | 2018-2-24 15:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
int keyscan(uchar){
int temp;
P0 = 0x0f;                                 
    temp = P0;                                 
    if(temp != 0x0f)
    {
          delay_qudou(5);
        if(temp!= 0x0f)                    
        {
                set_time=set_time+1; //这里无论按键与否都要执行,不知道为什么。
                key_value=2;  
                     
            switch(temp)                     
            {
                case 0x0e :key_value += 0; break;  
                case 0x0d :key_value += 1; break;   
                case 0x0b :key_value += 2; break;   
                case 0x07 :key_value += 3;break;  
            }   
        }   
        P0 = 0xf0;                                
        temp = P0;
        if(temp != 0xf0)
        {
            switch(temp)
            {
                case 0xe0 : key_value =1 ; break;  
                case 0xd0 : key_value =5 ; break;
                case 0xb0 : key_value =9 ; break;
                case 0x70 : key_value =13 ; break;  
            }


        }

我是参考的这篇**
http://blog.csdn.net/xiaocheng_sky/article/details/52133639

相关帖子

沙发
xichandoujigu|  楼主 | 2018-2-24 15:47 | 只看该作者
甚至p0什么都不接也是一样

使用特权

评论回复
板凳
caijie001| | 2018-2-24 16:00 | 只看该作者
可能是51单片机p0无法输出高电平,需要上拉电阻

使用特权

评论回复
评论
xch 2018-2-26 22:22 回复TA
正确 
地板
caijie001| | 2018-2-24 16:00 | 只看该作者
还有写程序要规范点,多看看别人的规范代码

使用特权

评论回复
5
gujiamao12345| | 2018-2-24 16:09 | 只看该作者
啥片子呀

使用特权

评论回复
6
dirtwillfly| | 2018-2-24 21:03 | 只看该作者
接到带外部中断的io上,等按键触发再执行就可以

使用特权

评论回复
7
xichandoujigu|  楼主 | 2018-2-24 21:41 | 只看该作者

stc12c5A60S2

使用特权

评论回复
8
xichandoujigu|  楼主 | 2018-2-24 21:43 | 只看该作者
dirtwillfly 发表于 2018-2-24 21:03
接到带外部中断的io上,等按键触发再执行就可以

这个键盘扫描程序我是写在中断里的。
void is_key(void) interrupt 0 using 1 //stop clok
   {
            miao_di=0;
       miao_gao=0;
       fen_di=0;
       fen_gao=0;
           shi_di=0;
           shi_gao=0;
           set_time=0;


           stp_clk=1;
           while(1)
           {
                      keyscan();
               display(shi_gao,shi_di,fen_gao,fen_di);
                   if (set_time==4)
                   break;
                 }         
            
}

使用特权

评论回复
9
xichandoujigu|  楼主 | 2018-2-24 21:43 | 只看该作者
caijie001 发表于 2018-2-24 16:00
还有写程序要规范点,多看看别人的规范代码

是指哪里不规范呢?谢谢。

使用特权

评论回复
10
xichandoujigu|  楼主 | 2018-2-24 21:44 | 只看该作者
caijie001 发表于 2018-2-24 16:00
可能是51单片机p0无法输出高电平,需要上拉电阻

我用其它扫描方式就行呢,比如:

   P0= 0xf7; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

       temp =P0;//读回来了

       temp &= 0xf0;//因为我们只是读回来高4位

       while (temp != 0xf0){

            delay_qudou(5);//消除抖动的

            temp=P0;

            temp &= 0xf0;

          while(temp != 0xf0){ //确实不等于0xf0有按键按下

             temp = P0;//我们这个时候只是把P0口的值赋给了temp

             switch (temp){ //检测P0口。

                  case 0xe7:

                      num =3 ;

                      break;

                 case 0xd7:

                     num=4;

                     break;

                 case 0xb7:

                     num=5;

                     break;

                 case 0x77:

                    num=6;

                    break;

             }

使用特权

评论回复
11
dirtwillfly| | 2018-2-24 21:47 | 只看该作者
xichandoujigu 发表于 2018-2-24 21:43
这个键盘扫描程序我是写在中断里的。
void is_key(void) interrupt 0 using 1 //stop clok
   {

硬件电路支持外部中断触发吗?

使用特权

评论回复
12
xichandoujigu|  楼主 | 2018-2-24 21:56 | 只看该作者
dirtwillfly 发表于 2018-2-24 21:47
硬件电路支持外部中断触发吗?

支持,实际我用另外一个方式都可以。

使用特权

评论回复
13
xichandoujigu|  楼主 | 2018-2-24 21:57 | 只看该作者
我用这个代码都可以,代码有点长,可能还有点乱,中间好像还有bug,还没找到,中断扫描16个键有的好用,有的不好用。

#include <REG51.H>  
int shi_gao,shi_di,fen_gao,fen_di,miao_gao,miao_di;        // 秒个位,十位、分个位、十位
unsigned char Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
int num,set_time,time_1,time_2,time_3,time_4;



sbit P11=P1^0;
sbit P12=P1^1;
sbit P13=P1^2;
sbit P14=P1^3;
sbit beep=P1^4;
sbit stp_clk=P1^5;
int zhongduan_cnt;




  //10ms延时子程序(12MHZ)
   void delay_ms(void)
      {  
             int i,j,k;
              for(i=5;i>0;i--)        
                for(j=4;j>0;j--)
                  for(k=248;k>0;k--);
        }

void delay_qudou(int z)
{
  int x,y;
  for(x=z;x>0;x--)
   for(y=110;y>0;y--);
}



void init()
    {   
          TMOD=0x01; //定时器初始化  选择timer0做16位定时器  
           TH0=(65536-50000)/256;  
           TL0=(65536-50000)%256;     
            EA=1;    //开放中断
            ET0=1;  //开放timer0中断  
            TR0=1;  //启动timer0  
                        EX0=1;// 按键外部中断用
             IT0=1; // 按键外部中断用

    }

void display(int shi_gao,shi_di,fen_gao,fen_di)
    {
          P2 = 0X00;
           P14=1;  
           P2=Tab[shi_gao];
           delay_ms() ;
           P14=0;

           P2 = 0X00;
           P13=1;  
           P2=Tab[shi_di];
           delay_ms() ;
           P13=0;

           P2 = 0X00;
           P12=1;  
           P2=Tab[fen_gao];
           delay_ms() ;
           P12=0;

           P2 = 0X00;
           P11=1;  
           P2=Tab[fen_di];
           delay_ms() ;
           P11=0;
    }

void Delay_beep(int x)
     {   int t;   while(x--) for(t=0;t<120;t++);  }   //按周期t发音

void Play(int t)
     {    int i;   for(i=0;i<100;i++)  {   beep=~beep;  Delay_beep(t);  }   beep=0;  }  




void timer0(void) interrupt 1 using 1
    {
           TH0  = (65536-50000)/256;  
          TL0= (65536-50000)%256;   
          zhongduan_cnt++;  
    }



void is_key(void) interrupt 0 using 1 //stop clok
   {
            miao_di=0;
       miao_gao=0;
       fen_di=0;
       fen_gao=0;
           shi_di=0;
           shi_gao=0;
           set_time=0;


           stp_clk=1;
           while(1)
           {
                      keyscan();
               display(shi_gao,shi_di,fen_gao,fen_di);
                   if (set_time==4)
                   break;
                 }         
            
}


//用uchar keyscan() 带返回值的函数

int keyscan(uchar){

int temp;


       P0= 0xf7; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

       temp =P0;//读回来了

       temp &= 0xf0;//因为我们只是读回来高4位

       while (temp != 0xf0){

            delay_qudou(5);//消除抖动的

            temp=P0;

            temp &= 0xf0;

          while(temp != 0xf0){ //确实不等于0xf0有按键按下

             temp = P0;//我们这个时候只是把P3口的值赋给了temp

             switch (temp){ //检测P3口。

                  case 0xe7:

                      num =3 ;

                      break;

                 case 0xd7:

                     num=4;

                     break;

                 case 0xb7:

                     num=5;

                     break;

                 case 0x77:

                    num=6;

                    break;

             }

                        set_time=set_time+1;
            if (set_time==1)
                          {
                            if (num>2)
                                {set_time=set_time-1;}
                                else
                                shi_gao=num;
                          }
                         

            if (set_time==2)
                          if  (shi_gao==2 && num>3)
                          {set_time=set_time-1;}
                          else                            
                              shi_di=num;


                        if (set_time==3)
                          {
                            if (num>5)
                                {set_time=set_time-1;}
                                else
                                fen_gao=num;
                          }

                    if (set_time==4)
                         fen_di=num;


            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

                {
                   temp = P0;
                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0
                }//下面就显示一下  退出整个4行循环。不加松手检测会退不出去循环
        //到这里是把第4行检测了。

        }

     }


       P0= 0xfb; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

       temp =P0;//读回来了

       temp &= 0xf0;//因为我们只是读回来高4位

       while (temp != 0xf0){

            delay_qudou(5);//消除抖动的

            temp=P0;

            temp &= 0xf0;

          while(temp != 0xf0){ //确实不等于0xf0有按键按下

             temp = P0;//我们这个时候只是把P3口的值赋给了temp

             switch (temp){ //检测P3口。

                  case 0xeb:

                      num =9;

                      break;

                 case 0xdb:

                     num=0;

                     break;

                 case 0xbb:

                     num=1;

                     break;

                 case 0x7b:

                    num=2;

                    break;

             }

                        set_time=set_time+1;
            if (set_time==1)
                          {
                            if (num>2)
                                {set_time=set_time-1;}
                                else
                                shi_gao=num;
                          }
                         

            if (set_time==2)
                          if  (shi_gao==2 && num>3)
                          {set_time=set_time-1;}
                          else                            
                              shi_di=num;


                        if (set_time==3)
                          {
                            if (num>5)
                                {set_time=set_time-1;}
                                else
                                fen_gao=num;
                          }

                    if (set_time==4)
                         fen_di=num;

            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

                {

                   temp = P0;

                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

                        

                }//下面就显示一下  退出整个3行的循环。  不加松手检测会退不出去循环     

     

        //到这里是把第3行检测了。

        }

     }



      P0= 0xfd; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

       temp =P0;//读回来了

       temp &= 0xf0;//因为我们只是读回来高4位

       while (temp != 0xf0){

            delay_qudou(5);//消除抖动的

            temp=P0;

            temp &= 0xf0;

          while(temp != 0xf0){

             temp = P0;

             switch (temp){

                  case 0xed:

                      num = 5;

                      break;

                 case 0xdd:

                     num=6;

                     break;

                 case 0xbd:

                     num=7;

                     break;

                 case 0x7d:

                    num=8;

                    break;

             }

                        set_time=set_time+1;
            if (set_time==1)
                          {
                            if (num>2)
                                {set_time=set_time-1;}
                                else
                                shi_gao=num;
                          }
                         

            if (set_time==2)
                          if  (shi_gao==2 && num>3)
                          {set_time=set_time-1;}
                          else                            
                              shi_di=num;


                        if (set_time==3)
                          {
                            if (num>5)
                                {set_time=set_time-1;}
                                else
                                fen_gao=num;
                          }

                    if (set_time==4)
                         fen_di=num;



            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

                {

                   temp = P0;

                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0
                }
        //到这里是把第2行检测了。
        }

     }




   P0= 0xfe; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

       temp =P0;//读回来了

       temp &= 0xf0;//因为我们只是读回来高4位

       while (temp != 0xf0){ //下面的几个while循环判断可以用if好理解。只看到第一行就行了。有按键按下可能是不等于的,不加松手检测会退不出去循环

              delay_qudou(5);//消除抖动的

            temp=P0;

            temp &= 0xf0;

          while(temp != 0xf0){ //确实不等于0xf0有按键按下

             temp = P0;//我们这个时候只是把P0口的值赋给了temp

             switch (temp){ //检测P0口。

                  case 0xee:

                      num = 1;

                      break;

                 case 0xde:

                     num=2;

                     break;

                 case 0xbe:

                     num=3;

                     break;

                 case 0x7e:

                    num=4;

                    break;

             }

                        set_time=set_time+1;
            if (set_time==1)
                          {
                            if (num>2)
                                {set_time=set_time-1;}
                                else
                                shi_gao=num;
                          }
                         

            if (set_time==2)
                          if  (shi_gao==2 && num>3)
                          {set_time=set_time-1;}
                          else                            
                              shi_di=num;


                        if (set_time==3)
                          {
                            if (num>5)
                                {set_time=set_time-1;}
                                else
                                fen_gao=num;
                          }

                    if (set_time==4)
                         fen_di=num;


                             while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

                {

                   temp = P0;

                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0
                }

        //到这里是把第一行检测了。以下下是其他几行检测的代码

        }  
                   }

  }





  /*********主程序********************/
void main()
  {
       beep=0;
       miao_di=0;
       miao_gao=0;
       fen_di=5;
       fen_gao=0;
           shi_di=7;
           shi_gao=0;
       zhongduan_cnt=0;
           stp_clk=0;
          

       P11=0;  
       P12=0;
       P13=0;
       P14=0;

       init();

          while(1)
             {
                   if(zhongduan_cnt>19) //如果到了1S
                        {
                            zhongduan_cnt=0; //清零
                                                          if(shi_gao==0 && shi_di==7 && fen_gao==0 &&  fen_di==0 && stp_clk==0)         //0700始响
                                    { Play(2);}

                                                           if (shi_gao==2 && shi_di==3 && fen_gao==5 && fen_di==9)          //是否跨天
                                                                     {
                                                                            shi_gao=0 ;
                                                                            shi_di=0        ;
                                                                            fen_gao=0;
                                                                            fen_di=0;
                                                                     }
                                                        else
                                                        {
                                                                       miao_di++; //秒数累加
                                                       
                                                               if (miao_di>9)
                                     {
                                       miao_gao=miao_gao+1;
                                       miao_di=0;
                                      }

                              if (miao_gao>5)
                                     {
                                        fen_di=fen_di+1;
                                       miao_gao=0;
                                    }

                           if (fen_di>9)
                                 {
                                     fen_gao=fen_gao+1;
                                    fen_di=0;
                                  }

                           if (fen_gao>5)
                                  {
                                      shi_di=shi_di+1;
                                      fen_gao=0;
                                    }

                           if (shi_di>9)
                                  {
                                     shi_gao=shi_gao+1;
                                     shi_di=0;
                                               }                                                               
                                         }


                           
               }

     
display(shi_gao,shi_di,fen_gao,fen_di);         

      }
  }
       

使用特权

评论回复
14
xichandoujigu|  楼主 | 2018-2-24 22:00 | 只看该作者
本帖最后由 xichandoujigu 于 2018-2-24 22:08 编辑

上三张图,实际用的单片机是STC12C5A60S2












使用特权

评论回复
15
caijie001| | 2018-2-24 22:36 | 只看该作者
xichandoujigu 发表于 2018-2-24 21:43
是指哪里不规范呢?谢谢。

首先,传入参数请命名,如uchar num
int类型的函数结束后请返回一个int类型的值
return 0;等

使用特权

评论回复
16
qinlu123| | 2018-2-25 11:57 | 只看该作者
可以试试我这个

矩阵键盘驱动.rar

2.93 KB

使用特权

评论回复
17
xichandoujigu|  楼主 | 2018-2-25 18:21 | 只看该作者

谢谢!

使用特权

评论回复
18
ddllxxrr| | 2018-2-25 21:41 | 只看该作者
每次都执行一定是硬件的事,前提是你的软件是没有毛病的

使用特权

评论回复
19
caijie001| | 2018-2-27 15:16 | 只看该作者
ddllxxrr 发表于 2018-2-25 21:41
每次都执行一定是硬件的事,前提是你的软件是没有毛病的

硬件是51单片机的p0,可能是无法输出高电平,需要上拉电阻

使用特权

评论回复
20
caijie001| | 2018-2-27 15:17 | 只看该作者
ddllxxrr 发表于 2018-2-25 21:41
每次都执行一定是硬件的事,前提是你的软件是没有毛病的

逻辑是没啥毛病的吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

96

帖子

2

粉丝