zoukankan      html  css  js  c++  java
  • 51单片机学习笔记(郭天祥版)(5)——作业讲解、独立键盘、矩阵键盘

    作业讲解

    第三题:

    先用定时器0把流水灯的写出来,再写定时器1的数码管显示,用变量存储765432,再定时器中断函数里自减,当到达7654398时,关闭定时器就不会变化了,这里765是不变的,偷懒,只管432。写完数码管停止和流水灯停止都试验后再写剩下的。改变定时器计时时间这里要记住。

      1 #include<reg51.h>
      2 #include<intrins.h>
      3 
      4 #define uchar unsigned char
      5 #define uint unsigned int
      6     
      7 void Delay1ms();
      8 void delay(int n);
      9 void display(uchar a,uchar b,uchar c,uchar bai,uchar shi,uchar ge);
     10 void init();
     11 sbit WEI=P2^7;
     12 sbit DUAN=P2^6;
     13 
     14 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x76,0x79,0x38,0x3f};
     15 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示 H  E    L    O
     16 uchar flag=0,flag1=0;
     17 uchar t0=0,t1=0;
     18 uint number=432;
     19 uchar bai=0,shi=0,ge=0;
     20 void main()
     21 {
     22     init();
     23     bai=number/100;
     24   shi=number/10%10;
     25   ge=number%10;
     26     while(1)
     27     {
     28         if(flag1!=1)
     29         {
     30             display(7,6,5,bai,shi,ge);
     31         }
     32         else
     33         {
     34             display(17,18,19,19,20,16);
     35         }
     36     }
     37 }
     38 
     39 void delay(int n)
     40 {
     41     while(n--)
     42     {
     43         Delay1ms();
     44     }
     45 }
     46 void Delay1ms()        //@12.000MHz
     47 {
     48     unsigned char i, j;
     49 
     50     i = 2;
     51     j = 239;
     52     do
     53     {
     54         while (--j);
     55     } while (--i);
     56 }
     57 void init()
     58 {
     59     P1=0xfe;
     60     TMOD=0x11;//两个定时器都设置为方式1
     61     TH0=(65536-50000)/256;
     62     TL0=(65536-50000)%256;
     63     TH1=(65536-50000)/256;
     64     TL1=(65536-50000)%256;
     65     EA=1;
     66     ET0=1;
     67     TR0=1;
     68     ET1=1;
     69     TR1=1;
     70 }
     71 void timer1() interrupt 3
     72 {
     73     TH1=(65536-50000)/256;
     74     TL1=(65536-50000)%256;
     75     t1++;
     76     if(t1==2)
     77     {
     78         t1=0;
     79         number--;
     80         bai=number/100;
     81     shi=number/10%10;
     82     ge=number%10;
     83         if(number==398)
     84         {
     85             //定时器0到这个位置还在运行,且TH0和TL0不知道是多少,所以要重新赋值
     86             TR0=0;
     87             
     88             TH0=(65536-50000)/256;
     89             TL0=(65536-50000)%256;
     90             TR0=1;
     91             flag=1;
     92             t0=0;
     93             P1=0xff;
     94             TR1=0;
     95         }
     96     }
     97 }
     98 void timer0() interrupt 1
     99 {
    100     TH0=(65536-50000)/256;
    101     TL0=(65536-50000)%256;
    102     t0++;
    103     if(flag!=1)
    104     {
    105         if(t0==10)
    106         {
    107             t0=0;
    108             P1=_crol_(P1,1);
    109         }
    110     }
    111     else
    112     {
    113         if(t0%4==0)
    114         {
    115             P1=~P1;
    116             if(t0==60)
    117             {
    118                 TR0=0;
    119                 P1=0xff;
    120                 flag1=1;
    121             }
    122         }
    123     }
    124 }
    125 void display(uchar a,uchar b,uchar c,uchar bai,uchar shi,uchar ge)
    126 {
    127     DUAN=1;
    128     P0=Table[a];
    129     DUAN=0;
    130     
    131     P0=0xff;
    132     WEI=1;
    133     P0=0xfe;
    134     WEI=0;
    135     delay(1);
    136     
    137     DUAN=1;
    138     P0=Table[b];
    139     DUAN=0;
    140     
    141     P0=0xff;
    142     WEI=1;
    143     P0=0xfd;
    144     WEI=0;
    145     delay(1);
    146     
    147     DUAN=1;
    148     P0=Table[c];
    149     DUAN=0;
    150     
    151     P0=0xff;
    152     WEI=1;
    153     P0=0xfb;
    154     WEI=0;
    155     delay(1);
    156         
    157         DUAN=1;
    158     P0=Table[bai];
    159     DUAN=0;
    160     
    161     P0=0xff;
    162     WEI=1;
    163     P0=0xf7;
    164     WEI=0;
    165     delay(1);
    166         
    167         DUAN=1;
    168     P0=Table[shi];
    169     DUAN=0;
    170     
    171     P0=0xff;
    172     WEI=1;
    173     P0=0xef;
    174     WEI=0;
    175     delay(1);
    176         
    177         DUAN=1;
    178     P0=Table[ge];
    179     DUAN=0;
    180     
    181     P0=0xff;
    182     WEI=1;
    183     P0=0xdf;
    184     WEI=0;
    185     delay(1);
    186 }

    中断函数不能太长,我们每50ms进入一次中断,如果中断函数长达50ms,那么当下一次中断进入函数时,上一次中断没退出,就会把下一次的丢失,程序就会出错。如何看这个时间呢,一个机器周期1us,指令有单周期指令和双周期指令,一般指令都是单周期指令,一个单周期指令1us,双周期2us,如果函数有1000条指令也才1ms,所以没问题,只要不加延时函数一般没事。


    键盘

     计算机键盘是ps2型的接口,键盘每按下一个值,内部有一个编码器,编码完后发给计算机,计算机有专门给键盘开的中断,优先级比较高,外接的任何响应计算机会立马从中断中收到数据,看出是按得哪一个按键。

    单片机的是非编码键盘。非编码键盘又分为独立键盘和行列式(又称为矩阵式)键盘。

    独立键盘的典型接法。32个IO口都可以作为输入输出,所以在哪个口接键盘都可以,检测按下:P1~P3IO口线内均有固定的上拉电阻,当这三个准双向IO口作输入口使用时,要向该口先写1,然后才能读取这个口的状态。原本P3.4=1,当键盘按下,P3.4接地了,TTL电路中IO口不是高阻态、没有三态状态,它与和它相连的线是线与的关系。如果P3.4变为低电平了就说明按下了。

    类似这两根线,只要有一根线为0,那么整个线路就是低电平。还有一种是线或的关系,当某一根线和具有三态功能的线相连,当三态IO口处于高阻态状态,和它连接的线产生线或的关系,跟他连接的线是高电平,高阻态就会变为高电平。

     

    单片机中独立键盘和矩阵键盘的接法。


    接下来写个代码试试独立键盘

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit led0=P1^0;
     7 sbit key0=P3^0;
     8 
     9 void main()
    10 {
    11     while(1)
    12     {
    13         if(key0==0)
    14             led0=0;
    15         else
    16             led0=1;
    17     }
    18 }

    这就是单片机的输入了,之前学的全都是单片机的输出。

    但这个代码其实是有毛病的,这样你可能看不出来,接下来再写一个程序看看,数码管初始0,按一下键盘+1,到10归0;

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0;
    15 
    16 void main()
    17 {
    18     WEI=1;
    19     P0=0xfe;
    20     WEI=0;
    21     while(1)
    22     {
    23         if(key0==0)
    24         {
    25             led0=0;
    26             num++;
    27             if(num>9)
    28             {
    29                 num=0;
    30             }
    31         }
    32         else
    33         {
    34             led0=1;
    35         }
    36         DUAN=1;
    37         P0=Table[num];
    38         DUAN=0;
    39     }
    40 }

    你会发现按下键盘,数码管不是+1,而是随机的。

    原因如下:

    右侧为硬件消抖,所以不需要看,有时软件消抖不方便或者不想浪费资源就用硬件消抖

    抖动时就会检测你按了很多次。

    你可能会说上面的代码可能就是按了一下,但是很长时间没抬起,所以进入了很多次if,从而num++许多次,那么我们加上松手检测。

    按键按下时key0=0,那么只要当key0==0时为死循环就可以了

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0;
    15 void Delay1ms();
    16 void delay(int n);
    17 
    18 void main()
    19 {
    20     WEI=1;
    21     P0=0xfe;
    22     WEI=0;
    23     while(1)
    24     {
    25         if(key0==0)
    26         {
    27             led0=0;
    28             num++;
    29             if(num>9)
    30             {
    31                 num=0;
    32             }
    33             while(!key0);
    34         }
    35         else
    36         {
    37             led0=1;
    38         }
    39         DUAN=1;
    40         P0=Table[num];
    41         DUAN=0;
    42     }
    43 }
    44 
    45 void delay(int n)
    46 {
    47     while(n--)
    48     {
    49         Delay1ms();
    50     }
    51 }
    52 void Delay1ms()        //@12.000MHz
    53 {
    54     unsigned char i, j;
    55 
    56     i = 2;
    57     j = 239;
    58     do
    59     {
    60         while (--j);
    61     } while (--i);
    62 }

    这样就能证明存在抖动的现象。

    我们只去除按下时的抖动,松开时的不需要,如何去呢?用延时函数,当按下去时我们延时10ms,按键按下抖动大约5ms左右,那么为了稳定我们可以写10ms,低电平保持的时间大约有20ms,所以消抖用掉5ms,还剩15ms,我们完全可以侧得到。

    下面是消抖的代码:

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0;
    15 void Delay1ms();
    16 void delay(int n);
    17 
    18 void main()
    19 {
    20     WEI=1;
    21     P0=0xfe;
    22     WEI=0;
    23     while(1)
    24     {
    25         if(key0==0)
    26         {
    27             delay(10);
    28             if(key0==0)
    29             {
    30                 led0=0;
    31                 num++;
    32                 if(num>9)
    33                 {
    34                     num=0;
    35                 }
    36             }
    37             while(!key0);
    38         }
    39         else
    40         {
    41             led0=1;
    42         }
    43         DUAN=1;
    44         P0=Table[num];
    45         DUAN=0;
    46     }
    47 }
    48 
    49 void delay(int n)
    50 {
    51     while(n--)
    52     {
    53         Delay1ms();
    54     }
    55 }
    56 void Delay1ms()        //@12.000MHz
    57 {
    58     unsigned char i, j;
    59 
    60     i = 2;
    61     j = 239;
    62     do
    63     {
    64         while (--j);
    65     } while (--i);
    66 }

    这样就没有问题了,这里最后的松手检测放在第二层if(key0==0)里面和外面都一样。

    有时为了更加稳定会在末尾再加上一次消抖,如下:

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0;
    15 void Delay1ms();
    16 void delay(int n);
    17 
    18 void main()
    19 {
    20     WEI=1;
    21     P0=0xfe;
    22     WEI=0;
    23     while(1)
    24     {
    25         if(key0==0)
    26         {
    27             delay(10);
    28             if(key0==0)
    29             {
    30                 led0=0;
    31                 num++;
    32                 if(num>9)
    33                 {
    34                     num=0;
    35                 }
    36             }
    37             while(!key0);
    38             delay(10);
    39             while(!key0);
    40         }
    41         else
    42         {
    43             led0=1;
    44         }
    45         DUAN=1;
    46         P0=Table[num];
    47         DUAN=0;
    48     }
    49 }
    50 
    51 void delay(int n)
    52 {
    53     while(n--)
    54     {
    55         Delay1ms();
    56     }
    57 }
    58 void Delay1ms()        //@12.000MHz
    59 {
    60     unsigned char i, j;
    61 
    62     i = 2;
    63     j = 239;
    64     do
    65     {
    66         while (--j);
    67     } while (--i);
    68 }

    延时去抖改为5ms也是可以的,尽量不要让cpu有过多的等待。


    接下来是矩阵键盘

    这是典型的矩阵键盘的接法(总线方式):

    你也可以自己仿照做成2*2,3*3,甚至4*5的,这时一组IO口不够用,那就接到别的IO口,检测的原理都是一样的。

    检测原理:

    其实和独立键盘都是一样的,都是检测低电平,但是四行四列全部连得IO口,没有接地的,所以低电平由你写程序给予。

    先给P3.0~3.3这样赋值,然后读取P3.4~3.7的数据,如果第一个键按下去了,那么P3.4就是0(线与的关系,没忘吧?),同一时刻你只能按下一个键,检测时都是有先后顺序的。那么P3的值就是如下:

    如果是按下的第1行第2列的键,那么就会如下:

    以此类推。如果都没按下去,那么P3.4~P3.7都是1。我们就根据每一次读取的值判断按下去的是哪一个键。这就是第一行的检测,矩阵键盘的检测要依次对四行进行扫描,第一次P3.0=0,然后读取四列,如果没有按下去,那么下一次就是把P3.1=0,其它三个为1,也是这样判断。只要有任何一个键被按下,就跳出整个大循环,直接退出扫描程序。如果你是两个一起按下去的,也是有先后顺序的,那么后面的也检测不到。

    先让P3=0xfe,在定义一个变量temp,保存P3的值(temp=P3),接下来我们要读的实际上是P3的高4位,只想知道高4位什么状态,然后再让temp&0xf0(按位与),如果一个都没按下,那么高4位全是1,低4位不管(任何数和0与都是0),那么temp&0xf0的结果还是0xf0,如果不是0xf0就是有键按下,如果第一个键按下了,那么P3.7~3.4就是1110,后面低4位不管,那么和0xf0与的时候就是1110 0000,不等于0xf0(1111 0000),就知道有键按下了,之后延时一下,再检测一遍,如果还是这个数,0xe0,那么就知道第一个键按下去了,用一个变量num,num=1,标记第一个键。一共扫描16次(第一行赋值0,扫描4列,第二行0,扫描4列......)。

    再举一下例子:

    例如按下去的是第一行第二列的键。

    那么第一次赋值P3=1111 1110后,temp就会为1101 1110,temp&0xfe=1101 0000,然后和0xfe比较即可,之后num=按下去的键的值。


    写程序看看,按下键盘,数码管显示对应的值,键盘的值分别为,第一行:0123,只检测第一行的。

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0,temp;
    15 void Delay1ms();
    16 void delay(int n);
    17 
    18 void main()
    19 {
    20     DUAN=1;
    21     P0=0x00;
    22     DUAN=0;
    23     WEI=1;
    24     P0=0xfe;
    25     WEI=0;
    26     while(1)
    27     {
    28         P3=0xfe;
    29         temp=P3;
    30         temp=temp&0xf0;
    31         while(temp!=0xf0)
    32         {
    33             delay(5);
    34             temp=P3;
    35             temp=temp&0xf0;
    36             while(temp!=0xf0)
    37             {
    38                 temp=P3;
    39                 switch(temp)
    40                 {
    41                     case 0xee:num=1;break;
    42                     case 0xde:num=2;break;
    43                     case 0xbe:num=3;break;
    44                     case 0x7e:num=4;break;
    45                 }
    46                 DUAN=1;
    47                 P0=Table[num-1];
    48                 DUAN=0;
    49             }
    50         }
    51     }
    52 }
    53 
    54 void delay(int n)
    55 {
    56     while(n--)
    57     {
    58         Delay1ms();
    59     }
    60 }
    61 void Delay1ms()        //@12.000MHz
    62 {
    63     unsigned char i, j;
    64 
    65     i = 2;
    66     j = 239;
    67     do
    68     {
    69         while (--j);
    70     } while (--i);
    71 }

    明明用if更简单,郭天祥竟然用while

     1 #include<reg51.h>
     2 
     3 #define uchar unsigned char
     4 #define uint unsigned int
     5 
     6 sbit WEI=P2^7;
     7 sbit DUAN=P2^6;
     8 
     9 sbit led0=P1^0;
    10 sbit key0=P3^0;
    11 
    12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
    13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
    14 uchar num=0,temp;
    15 void Delay1ms();
    16 void delay(int n);
    17 
    18 void main()
    19 {
    20     DUAN=1;
    21     P0=0x00;
    22     DUAN=0;
    23     WEI=1;
    24     P0=0xfe;
    25     WEI=0;
    26     while(1)
    27     {
    28         P3=0xfe;
    29         temp=P3;
    30         temp=temp&0xf0;
    31         if(temp!=0xf0)
    32         {
    33             delay(5);
    34             temp=P3;
    35             temp=temp&0xf0;
    36             if(temp!=0xf0)
    37             {
    38                 switch(temp)
    39                 {
    40                     case 0xe0:num=1;break;
    41                     case 0xd0:num=2;break;
    42                     case 0xb0:num=3;break;
    43                     case 0x70:num=4;break;
    44                 }
    45                 DUAN=1;
    46                 P0=Table[num-1];
    47                 DUAN=0;
    48             }
    49         }
    50     }
    51 }
    52 
    53 void delay(int n)
    54 {
    55     while(n--)
    56     {
    57         Delay1ms();
    58     }
    59 }
    60 void Delay1ms()        //@12.000MHz
    61 {
    62     unsigned char i, j;
    63 
    64     i = 2;
    65     j = 239;
    66     do
    67     {
    68         while (--j);
    69     } while (--i);
    70 }

    然后我们再把剩下四行也加上看看

      1 #include<reg51.h>
      2 
      3 #define uchar unsigned char
      4 #define uint unsigned int
      5 
      6 sbit WEI=P2^7;
      7 sbit DUAN=P2^6;
      8 
      9 sbit led0=P1^0;
     10 sbit key0=P3^0;
     11 
     12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
     13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
     14 uchar num=0,temp;
     15 void Delay1ms();
     16 void delay(int n);
     17 
     18 void main()
     19 {
     20     DUAN=1;
     21     P0=0x00;
     22     DUAN=0;
     23     WEI=1;
     24     P0=0xfe;
     25     WEI=0;
     26     while(1)
     27     {
     28         //第一行
     29         P3=0xfe;
     30         temp=P3;
     31         temp=temp&0xf0;
     32         while(temp!=0xf0)
     33         {
     34             delay(5);
     35             temp=P3;
     36             temp=temp&0xf0;
     37             while(temp!=0xf0)
     38             {
     39                 temp=P3;
     40                 switch(temp)
     41                 {
     42                     case 0xee:num=1;break;
     43                     case 0xde:num=2;break;
     44                     case 0xbe:num=3;break;
     45                     case 0x7e:num=4;break;
     46                 }
     47                 
     48                 /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
     49                 有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
     50                 while(temp!=0xf0)
     51                 {
     52                     temp=P3;
     53                     temp=temp&0xf0;
     54                 }
     55                 DUAN=1;
     56                 P0=Table[num-1];
     57                 DUAN=0;
     58             }
     59         }
     60         
     61         //第二行
     62         P3=0xfd;
     63         temp=P3;
     64         temp=temp&0xf0;
     65         while(temp!=0xf0)
     66         {
     67             delay(5);
     68             temp=P3;
     69             temp=temp&0xf0;
     70             while(temp!=0xf0)
     71             {
     72                 temp=P3;
     73                 switch(temp)
     74                 {
     75                     case 0xed:num=5;break;
     76                     case 0xdd:num=6;break;
     77                     case 0xbd:num=7;break;
     78                     case 0x7d:num=8;break;
     79                 }
     80                 while(temp!=0xf0)
     81                 {
     82                     temp=P3;
     83                     temp=temp&0xf0;
     84                 }
     85                 DUAN=1;
     86                 P0=Table[num-1];
     87                 DUAN=0;
     88             }
     89         }
     90         
     91         //第三行
     92         P3=0xfb;
     93         temp=P3;
     94         temp=temp&0xf0;
     95         while(temp!=0xf0)
     96         {
     97             delay(5);
     98             temp=P3;
     99             temp=temp&0xf0;
    100             while(temp!=0xf0)
    101             {
    102                 temp=P3;
    103                 switch(temp)
    104                 {
    105                     case 0xeb:num=9;break;
    106                     case 0xdb:num=10;break;
    107                     case 0xbb:num=11;break;
    108                     case 0x7b:num=12;break;
    109                 }
    110                 while(temp!=0xf0)
    111                 {
    112                     temp=P3;
    113                     temp=temp&0xf0;
    114                 }
    115                 DUAN=1;
    116                 P0=Table[num-1];
    117                 DUAN=0;
    118             }
    119         }
    120         
    121         //第四行
    122         P3=0xf7;
    123         temp=P3;
    124         temp=temp&0xf0;
    125         while(temp!=0xf0)
    126         {
    127             delay(5);
    128             temp=P3;
    129             temp=temp&0xf0;
    130             while(temp!=0xf0)
    131             {
    132                 temp=P3;
    133                 switch(temp)
    134                 {
    135                     case 0xe7:num=13;break;
    136                     case 0xd7:num=14;break;
    137                     case 0xb7:num=15;break;
    138                     case 0x77:num=16;break;
    139                 }
    140                 while(temp!=0xf0)
    141                 {
    142                     temp=P3;
    143                     temp=temp&0xf0;
    144                 }
    145                 DUAN=1;
    146                 P0=Table[num-1];
    147                 DUAN=0;
    148             }
    149         }
    150     }
    151 }
    152 
    153 void delay(int n)
    154 {
    155     while(n--)
    156     {
    157         Delay1ms();
    158     }
    159 }
    160 void Delay1ms()        //@12.000MHz
    161 {
    162     unsigned char i, j;
    163 
    164     i = 2;
    165     j = 239;
    166     do
    167     {
    168         while (--j);
    169     } while (--i);
    170 }

    我们可以把扫描改为函数,方便移植到别的程序

      1 #include<reg51.h>
      2 
      3 #define uchar unsigned char
      4 #define uint unsigned int
      5 
      6 sbit WEI=P2^7;
      7 sbit DUAN=P2^6;
      8 
      9 sbit led0=P1^0;
     10 sbit key0=P3^0;
     11 
     12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
     13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
     14 uchar num=17,temp;//num一开始为17,这样-1后就是不显示,用于最初没有按键按下时的情况
     15 void Delay1ms();
     16 void delay(int n);
     17 uchar keyscan();
     18 void main()
     19 {
     20     DUAN=1;
     21     P0=0x00;
     22     DUAN=0;
     23     WEI=1;
     24     P0=0xfe;
     25     WEI=0;
     26     while(1)
     27     {
     28         DUAN=1;
     29         P0=Table[keyscan()-1];
     30         DUAN=0;
     31     }
     32 }
     33 
     34 void delay(int n)
     35 {
     36     while(n--)
     37     {
     38         Delay1ms();
     39     }
     40 }
     41 void Delay1ms()        //@12.000MHz
     42 {
     43     unsigned char i, j;
     44 
     45     i = 2;
     46     j = 239;
     47     do
     48     {
     49         while (--j);
     50     } while (--i);
     51 }
     52 
     53 uchar keyscan()
     54 {
     55     //第一行
     56     P3=0xfe;
     57     temp=P3;
     58     temp=temp&0xf0;
     59     while(temp!=0xf0)
     60     {
     61         delay(5);
     62         temp=P3;
     63         temp=temp&0xf0;
     64         while(temp!=0xf0)
     65         {
     66             temp=P3;
     67             switch(temp)
     68             {
     69                 case 0xee:num=1;break;
     70                 case 0xde:num=2;break;
     71                 case 0xbe:num=3;break;
     72                 case 0x7e:num=4;break;
     73             }
     74             
     75             /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
     76             有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
     77             while(temp!=0xf0)
     78             {
     79                 temp=P3;
     80                 temp=temp&0xf0;
     81             }
     82             //放入函数里有就不需要这个显示了
     83 //            DUAN=1;
     84 //            P0=Table[num-1];
     85 //            DUAN=0;
     86         }
     87     }
     88     
     89     //第二行
     90     P3=0xfd;
     91     temp=P3;
     92     temp=temp&0xf0;
     93     while(temp!=0xf0)
     94     {
     95         delay(5);
     96         temp=P3;
     97         temp=temp&0xf0;
     98         while(temp!=0xf0)
     99         {
    100             temp=P3;
    101             switch(temp)
    102             {
    103                 case 0xed:num=5;break;
    104                 case 0xdd:num=6;break;
    105                 case 0xbd:num=7;break;
    106                 case 0x7d:num=8;break;
    107             }
    108             while(temp!=0xf0)
    109             {
    110                 temp=P3;
    111                 temp=temp&0xf0;
    112             }
    113 //            DUAN=1;
    114 //            P0=Table[num-1];
    115 //            DUAN=0;
    116         }
    117     }
    118     
    119     //第三行
    120     P3=0xfb;
    121     temp=P3;
    122     temp=temp&0xf0;
    123     while(temp!=0xf0)
    124     {
    125         delay(5);
    126         temp=P3;
    127         temp=temp&0xf0;
    128         while(temp!=0xf0)
    129         {
    130             temp=P3;
    131             switch(temp)
    132             {
    133                 case 0xeb:num=9;break;
    134                 case 0xdb:num=10;break;
    135                 case 0xbb:num=11;break;
    136                 case 0x7b:num=12;break;
    137             }
    138             while(temp!=0xf0)
    139             {
    140                 temp=P3;
    141                 temp=temp&0xf0;
    142             }
    143 //            DUAN=1;
    144 //            P0=Table[num-1];
    145 //            DUAN=0;
    146         }
    147     }
    148     
    149     //第四行
    150     P3=0xf7;
    151     temp=P3;
    152     temp=temp&0xf0;
    153     while(temp!=0xf0)
    154     {
    155         delay(5);
    156         temp=P3;
    157         temp=temp&0xf0;
    158         while(temp!=0xf0)
    159         {
    160             temp=P3;
    161             switch(temp)
    162             {
    163                 case 0xe7:num=13;break;
    164                 case 0xd7:num=14;break;
    165                 case 0xb7:num=15;break;
    166                 case 0x77:num=16;break;
    167             }
    168             while(temp!=0xf0)
    169             {
    170                 temp=P3;
    171                 temp=temp&0xf0;
    172             }
    173 //            DUAN=1;
    174 //            P0=Table[num-1];
    175 //            DUAN=0;
    176         }
    177     }
    178     return num;
    179 }

    同样的也可以把显示用函数封装起来。这里就不给代码了。

    接下来我们看下用if不用while的。(末尾加上松手检测比while好多了)

      1 #include<reg51.h>
      2 
      3 #define uchar unsigned char
      4 #define uint unsigned int
      5 
      6 sbit WEI=P2^7;
      7 sbit DUAN=P2^6;
      8 
      9 sbit led0=P1^0;
     10 sbit key0=P3^0;
     11 
     12 uchar code Table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
     13 //                    0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F   无显示
     14 uchar num=0,temp;
     15 void Delay1ms();
     16 void delay(int n);
     17 
     18 void main()
     19 {
     20     DUAN=1;
     21     P0=0x00;
     22     DUAN=0;
     23     WEI=1;
     24     P0=0xfe;
     25     WEI=0;
     26     while(1)
     27     {
     28         //第一行
     29         P3=0xfe;
     30         temp=P3;
     31         temp=temp&0xf0;
     32         if(temp!=0xf0)
     33         {
     34             delay(5);
     35             temp=P3;
     36             temp=temp&0xf0;
     37             if(temp!=0xf0)
     38             {
     39                 temp=P3;
     40                 switch(temp)
     41                 {
     42                     case 0xee:num=1;break;
     43                     case 0xde:num=2;break;
     44                     case 0xbe:num=3;break;
     45                     case 0x7e:num=4;break;
     46                 }
     47                 
     48 //                /*没有这里的话,如果按下某一行,就会一直进入上面这个while循环,即使松手也出不来,
     49 //                有了它,不松手就一直在下面的循环,松手后就会改变temp的值,变为0xf0*/
     50 //                while(temp!=0xf0)
     51 //                {
     52 //                    temp=P3;
     53 //                    temp=temp&0xf0;
     54 //                }
     55                 DUAN=1;
     56                 P0=Table[num-1];
     57                 DUAN=0;
     58             }
     59         }
     60         
     61         //第二行
     62         P3=0xfd;
     63         temp=P3;
     64         temp=temp&0xf0;
     65         if(temp!=0xf0)
     66         {
     67             delay(5);
     68             temp=P3;
     69             temp=temp&0xf0;
     70             if(temp!=0xf0)
     71             {
     72                 temp=P3;
     73                 switch(temp)
     74                 {
     75                     case 0xed:num=5;break;
     76                     case 0xdd:num=6;break;
     77                     case 0xbd:num=7;break;
     78                     case 0x7d:num=8;break;
     79                 }
     80 //                while(temp!=0xf0)
     81 //                {
     82 //                    temp=P3;
     83 //                    temp=temp&0xf0;
     84 //                }
     85                 DUAN=1;
     86                 P0=Table[num-1];
     87                 DUAN=0;
     88             }
     89         }
     90         
     91         //第三行
     92         P3=0xfb;
     93         temp=P3;
     94         temp=temp&0xf0;
     95         if(temp!=0xf0)
     96         {
     97             delay(5);
     98             temp=P3;
     99             temp=temp&0xf0;
    100             if(temp!=0xf0)
    101             {
    102                 temp=P3;
    103                 switch(temp)
    104                 {
    105                     case 0xeb:num=9;break;
    106                     case 0xdb:num=10;break;
    107                     case 0xbb:num=11;break;
    108                     case 0x7b:num=12;break;
    109                 }
    110 //                while(temp!=0xf0)
    111 //                {
    112 //                    temp=P3;
    113 //                    temp=temp&0xf0;
    114 //                }
    115                 DUAN=1;
    116                 P0=Table[num-1];
    117                 DUAN=0;
    118             }
    119         }
    120         
    121         //第四行
    122         P3=0xf7;
    123         temp=P3;
    124         temp=temp&0xf0;
    125         if(temp!=0xf0)
    126         {
    127             delay(5);
    128             temp=P3;
    129             temp=temp&0xf0;
    130             if(temp!=0xf0)
    131             {
    132                 temp=P3;
    133                 switch(temp)
    134                 {
    135                     case 0xe7:num=13;break;
    136                     case 0xd7:num=14;break;
    137                     case 0xb7:num=15;break;
    138                     case 0x77:num=16;break;
    139                 }
    140 //                while(temp!=0xf0)
    141 //                {
    142 //                    temp=P3;
    143 //                    temp=temp&0xf0;
    144 //                }
    145                 DUAN=1;
    146                 P0=Table[num-1];
    147                 DUAN=0;
    148             }
    149         }
    150     }
    151 }
    152 
    153 void delay(int n)
    154 {
    155     while(n--)
    156     {
    157         Delay1ms();
    158     }
    159 }
    160 void Delay1ms()        //@12.000MHz
    161 {
    162     unsigned char i, j;
    163 
    164     i = 2;
    165     j = 239;
    166     do
    167     {
    168         while (--j);
    169     } while (--i);
    170 }

     不过这个矩阵键盘方法太麻烦了,浪费资源,看看清翔的或者别人的,都比这个简洁。

  • 相关阅读:
    观后感(追番记)...
    网络流24题
    动物园
    [HNOI2016]网络
    部落战争(最小路径点覆盖)
    P4313 文理分科(最小割)
    P2774 方格取数问题(最小割)
    P2472 [SCOI2007]蜥蜴(最大流)
    P1231 教辅的组成(最大流)
    最短路计数(SPFA× Dijkstra√)
  • 原文地址:https://www.cnblogs.com/IceHowe/p/10664389.html
Copyright © 2011-2022 走看看