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 }

 不過這個矩陣鍵盤方法太麻煩了,浪費資源,看看清翔的或者別人的,都比這個簡潔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM