作業講解
第三題:
先用定時器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 }
不過這個矩陣鍵盤方法太麻煩了,浪費資源,看看清翔的或者別人的,都比這個簡潔。