覺得這份資料對初學者很有用,希望對初學的人有所幫助。
7. I/O并行口直接驅動LED顯示
1. 實驗任務
如圖13所示,利用AT89S51單片機的P0端口的P0.0-P0.7連接到一個共陰數碼管的a-h的筆段上,數碼管的公共端接地。在數碼管上循環顯示0-9數字,時間間隔0.2秒。
2. 電路原理圖
圖4.7.1
3. 系統板上硬件連線
把“單片機系統”區域中的P0.0/AD0-P0.7/AD7端口用8芯排線連接到“四路靜態數碼顯示模塊”區域中的任一個數碼管的a-h端口上;要求:P0.0/AD0與a相連,P0.1/AD1與b相連,P0.2/AD2與c相連,……,P0.7/AD7與h相連。
4. 程序設計內容
(1. LED數碼顯示原理
七段LED顯示器內部由七個條形發光二極管和一個小圓點發光二極管組成,根據各管的極管的接線形式,可分成共陰極型和共陽極型。
LED數碼管的g~a七個發光二極管因加正電壓而發亮,因加零電壓而不以發亮,不同亮暗的組合就能形成不同的字形,這種組合稱之為字形碼,下面給出共陰極的字形碼見表2
“0” |
3FH |
|
“8” |
7FH |
|
“1” |
06H |
|
“9” |
6FH |
|
“2” |
5BH |
|
“A” |
77H |
|
“3” |
4FH |
|
“b” |
7CH |
|
“4” |
66H |
|
“C” |
39H |
|
“5” |
6DH |
|
“d” |
5EH |
|
“6” |
7DH |
|
“E” |
79H |
|
“7” |
07H |
|
“F” |
71H |
|
(2. 由于顯示的數字0-9的字形碼沒有規律可循,只能采用查表的方式來完成我們所需的要求了。這樣我們按著數字0-9的順序,把每個數字的筆段代碼按順序排好!建立的表格如下所示:TABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
5.程序框圖
圖4.7.2
6. 匯編源程序 ORG 0 START: MOV R1,#00H NEXT: MOV A,R1 MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A LCALL DELAY INC R1 CJNE R1,#10,NEXT LJMP START DELAY: MOV R5,#20 D2: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,D2 RET TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END 7. C語言源程序 #include <AT89X51.H> unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char dispcount;
void delay02s(void) { unsigned char i,j,k; for(i=20;i>0;i--) for(j=20;j>0;j--) for(k=248;k>0;k--); }
void main(void) { while(1) { for(dispcount=0;dispcount<10;dispcount++) { P0=table[dispcount]; delay02s(); } } }
8. 按鍵識別方法之一
1. 實驗任務
每按下一次開關SP1,計數值加1,通過AT89S51單片機的P1端口的P1.0到P1.3顯示出其的二進制計數值。
2. 電路原理圖
圖4.8.1
3. 系統板上硬件連線
(1. 把“單片機系統”區域中的P3.7/RD端口連接到“獨立式鍵盤”區域中的SP1端口上;
(2. 把“單片機系統”區域中的P1.0-P1.4端口用8芯排線連接到“八路發光二極管指示模塊”區域中的“L1-L8”端口上;要求,P1.0連接到L1,P1.1連接到L2,P1.2連接到L3,P1.3連接到L4上。
4. 程序設計方法
(1. 其實,作為一個按鍵從沒有按下到按下以及釋放是一個完整的過程,也就是說,當我們按下一個按鍵時,總希望某個命令只執行一次,而在按鍵按下的過程中,不要有干擾進來,因為,在按下的過程中,一旦有干擾過來,可能造成誤觸發過程,這并不是我們所想要的。因此在按鍵按下的時候,
圖4.8.2
要把我們手上的干擾信號以及按鍵的機械接觸等干擾信號給濾除掉,一般情況下,我們可以采用電容來濾除掉這些干擾信號,但實際上,會增加硬件成本及硬件電路的體積,這是我們不希望,總得有個辦法解決這個問題,因此我們可以采用軟件濾波的方法去除這些干擾
信號,一般情況下,一個按鍵按下的時候,總是在按下的時刻存在著一定的干擾信號,按下之后就基本上進入了穩定的狀態。具體的一個按鍵從按下到釋放的全過程的信號圖如上圖所示:
從圖中可以看出,我們在程序設計時,從按鍵被識別按下之后,延時5ms以上,從而避開了干擾信號區域,我們再來檢測一次,看按鍵是否真得已經按下,若真得已經按下,這時肯定輸出為低電平,若這時檢測到的是高電平,證明剛才是由于干擾信號引起的誤觸發,CPU就認為是誤觸發信號而舍棄這次的按鍵識別過程。從而提高了系統的可靠性。
由于要求每按下一次,命令被執行一次,直到下一次再按下的時候,再執行一次命令,因此從按鍵被識別出來之后,我們就可以執行這次的命令,所以要有一個等待按鍵釋放的過程,顯然釋放的過程,就是使其恢復成高電平狀態。
(1. 對于按鍵識別的指令,我們依然選擇如下指令JB BIT,REL指令是用來檢測BIT是否為高電平,若BIT=1,則程序轉向REL處執行程序,否則就繼續向下執行程序。或者是 JNB BIT,REL指令是用來檢測BIT是否為低電平,若BIT=0,則程序轉向REL處執行程序,否則就繼續向下執行程序。
(2. 但對程序設計過程中按鍵識別過程的框圖如右圖所示: 圖4.8.3
5. 程序框圖
圖4.8.4
6. 匯編源程序 ORG 0 START: MOV R1,#00H ;初始化R1為0,表示從0開始計數 MOV A,R1 ; CPL A ;取反指令 MOV P1,A ;送出P1端口由發光二極管顯示 REL: JNB P3.7,REL ;判斷SP1是否按下 LCALL DELAY10MS ;若按下,則延時10ms左右 JNB P3.7,REL ;再判斷SP1是否真得按下 INC R1 ;若真得按下,則進行按鍵處理,使 MOV A,R1 ;計數內容加1,并送出P1端口由 CPL A ;發光二極管顯示 MOV P1,A ; JNB P3.7,$ ;等待SP1釋放 SJMP REL ;繼續對K1按鍵掃描 DELAY10MS: MOV R6,#20 ;延時10ms子程序 L1: MOV R7,#248 DJNZ R7,$ DJNZ R6,L1 RET END
7. C語言源程序 #include <AT89X51.H>
unsigned char count;
void delay10ms(void) { unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); }
void main(void) { while(1) { if(P3_7==0) { delay10ms(); if(P3_7==0) { count++; if(count==16) { count=0; } P1=~count; while(P3_7==0); } } } }
9. 一鍵多功能按鍵識別技術
1.實驗任務
如圖4.9.1所示,開關SP1接在P3.7/RD管腳上,在AT89S51單片機的P1端口接有四個發光二極管,上電的時候,L1接在P1.0管腳上的發光二極管在閃爍,當每一次按下開關SP1的時候,L2接在P1.1管腳上的發光二極管在閃爍,再按下開關SP1的時候,L3接在P1.2管腳上的發光二極管在閃爍,再按下開關SP1的時候,L4接在P1.3管腳上的發光二極管在閃爍,再按下開關SP1的時候,又輪到L1在閃爍了,如此輪流下去。
2.電路原理圖
圖4.9.1
3.系統板上硬件連線
(1. 把“單片機系統”區域中的P3.7/RD端口連接到“獨立式鍵盤”區域中的SP1端口上;
(2. 把“單片機系統”區域中的P1.0-P1.4端口用8芯排線連接到“八路發光二極管指示模塊”區域中的“L1-L8”端口上;要求,P1.0連接到L1,P1.1連接到L2,P1.2連接到L3,P1.3連接到L4上。
4.程序設計方法
(1. 設計思想由來
在我們生活中,我們很容易通過這個叫張三,那個叫李四,另外一個是王五;那是因為每個人有不同的名子,我們就很快認出,同樣,對于要通過一個按鍵來識別每種不同的功能,我們給每個不同的功能模塊用不同的ID號標識,這樣,每按下一次按鍵,ID的值是不相同的,所以單片機就很容易識別不同功能的身份了。
(2. 設計方法
從上面的要求我們可以看出,L1到L4發光二極管在每個時刻的閃爍的時間是受開關SP1來控制,我們給L1到L4閃爍的時段定義出不同的ID號,當L1在閃爍時,ID=0;當L2在閃爍時,ID=1;當L3在閃爍時,ID=2;當L4在閃爍時,ID=3;很顯然,只要每次按下開關K1時,分別給出不同的ID號我們就能夠完成上面的任務了。下面給出有關程序設計的框圖。
5.程序框圖
圖4.9.2
6. 匯編源程序 ID EQU 30H SP1 BIT P3.7 L1 BIT P1.0 L2 BIT P1.1 L3 BIT P1.2 L4 BIT P1.3 ORG 0 MOV ID,#00H START: JB K1,REL LCALL DELAY10MS JB K1,REL INC ID MOV A,ID CJNE A,#04,REL MOV ID,#00H REL: JNB K1,$ MOV A,ID CJNE A,#00H,IS0 CPL L1 LCALL DELAY SJMP START IS0: CJNE A,#01H,IS1 CPL L2 LCALL DELAY SJMP START IS1: CJNE A,#02H,IS2 CPL L3 LCALL DELAY SJMP START IS2: CJNE A,#03H,IS3 CPL L4 LCALL DELAY SJMP START IS3: LJMP START DELAY10MS: MOV R6,#20 LOOP1: MOV R7,#248 DJNZ R7,$ DJNZ R6,LOOP1 RET DELAY: MOV R5,#20 LOOP2: LCALL DELAY10MS DJNZ R5,LOOP2 RET END 7. C語言源程序 #include <AT89X51.H> unsigned char ID; void delay10ms(void) { unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); }
void delay02s(void) { unsigned char i; for(i=20;i>0;i--) {delay10ms(); } }
void main(void) { while(1) { if(P3_7==0) {delay10ms(); if(P3_7==0) { ID++; if(ID==4) { ID=0; } while(P3_7==0); } } switch(ID) { case 0: P1_0=~P1_0; delay02s(); break; case 1: P1_1=~P1_1; delay02s(); break; case 2: P1_2=~P1_2; delay02s(); break; case 3: P1_3=~P1_3; delay02s(); break; } } }
10. 00-99計數器
1. 實驗任務
利用AT89S51單片機來制作一個手動計數器,在AT89S51單片機的P3.7管腳接一個輕觸開關,作為手動計數的按鈕,用單片機的P2.0-P2.7接一個共陰數碼管,作為00-99計數的個位數顯示,用單片機的P0.0-P0.7接一個共陰數碼管,作為00-99計數的十位數顯示;硬件電路圖如圖19所示。
2. 電路原理圖
圖4.10.1
3. 系統板上硬件連線
(1. 把“單片機系統”區域中的P0.0/AD0-P0.7/AD7端口用8芯排線連接到“四路靜態數碼顯示模塊”區域中的任一個a-h端口上;要求:P0.0/AD0對應著a,P0.1/AD1對應著b,……,P0.7/AD7對應著h。
(2. 把“單片機系統”區域中的P2.0/A8-P2.7/A15端口用8芯排線連接到“四路靜態數碼顯示模塊”區域中的任一個數碼管的a-h端口上;
(3. 把“單片機系統”區域中的P3.7/RD端口用導線連接到“獨立式鍵盤”區域中的SP1端口上;
4. 程序設計內容
(1. 單片機對按鍵的識別的過程處理
(2. 單片機對正確識別的按鍵進行計數,計數滿時,又從零開始計數;
(3. 單片機對計的數值要進行數碼顯示,計得的數是十進數,含有十位和個位,我們要把十位和個位拆開分別送出這樣的十位和個位數值到對應的數碼管上顯示。如何拆開十位和個位我們可以把所計得的數值對10求余,即可得個位數字,對10整除,即可得到十位數字了。
(4. 通過查表方式,分別顯示出個位和十位數字。
5.程序框圖
圖4.10.2
6. 匯編源程序 Count EQU 30H SP1 BIT P3.7 ORG 0 START: MOV Count,#00H NEXT: MOV A,Count MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A WT: JNB SP1,WT WAIT: JB SP1,WAIT LCALL DELY10MS JB SP1,WAIT INC Count MOV A,Count CJNE A,#100,NEXT LJMP START DELY10MS: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END 7. C語言源程序 #include <AT89X51.H> unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char Count;
void delay10ms(void) { unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); }
void main(void) { Count=0; P0=table[Count/10]; P2=table[Count%10]; while(1) { if(P3_7==0) { delay10ms(); if(P3_7==0) { Count++; if(Count==100) { Count=0; } P0=table[Count/10]; P2=table[Count%10]; while(P3_7==0); } } } }
11. 00-59秒計時器(利用軟件延時)
1. 實驗任務
如下圖所示,在AT89S51單片機的P0和P2端口分別接有兩個共陰數碼管,P0口驅動顯示秒時間的十位,而P2口驅動顯示秒時間的個位。
2. 電路原理圖
圖4.11.1
3. 系統板上硬件連線
(1. 把“單片機系統”區域中的P0.0/AD0-P0.7/AD7端口用8芯排線連接到“四路靜態數碼顯示模塊”區域中的任一個a-h端口上;要求:P0.0/AD0對應著a,P0.1/AD1對應著b,……,P0.7/AD7對應著h。
(2. 把“單片機系統”區域中的P2.0/A8-P2.7/A15端口用8芯排線連接到“四路靜態數碼顯示模塊”區域中的任一個a-h端口上;要求:P2.0/A8對應著a,P2.1/A9對應著b,……,P2.7/A15對應著h。
4. 程序設計內容
(1. 在設計過程中我們用一個存儲單元作為秒計數單元,當一秒鐘到來時,就讓秒計數單元加1,當秒計數達到60時,就自動返回到0,重新秒計數。
(2. 對于秒計數單元中的數據要把它十位數和個數分開,方法仍采用對10整除和對10求余。
(3. 在數碼上顯示,仍通過查表的方式完成。
(4. 一秒時間的產生在這里我們采用軟件精確延時的方法來完成,經過精確計算得到1秒時間為1.002秒。
DELY1S: MOV R5,#100
D2: MOV R6,#20
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
DJNZ R5,D2
RET
5. 程序框圖
圖4.11.2
6. 匯編源程序 Second EQU 30H ORG 0 START: MOV Second,#00H NEXT: MOV A,Second MOV B,#10 DIV AB MOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,A MOV A,B MOVC A,@A+DPTR MOV P2,A LCALL DELY1S INC Second MOV A,Second CJNE A,#60,NEXT LJMP START DELY1S: MOV R5,#100 D2: MOV R6,#20 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,D2 RET TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH END 7. C語言源程序 #include <AT89X51.H> unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char Second;
void delay1s(void) { unsigned char i,j,k; for(k=100;k>0;k--) for(i=20;i>0;i--) for(j=248;j>0;j--); }
void main(void) { Second=0; P0=table[Second/10]; P2=table[Second%10]; while(1) { delay1s(); Second++; if(Second==60) { Second=0; } P0=table[Second/10]; P2=table[Second%10]; } }
12. 可預置可逆4位計數器
1. 實驗任務
利用AT89S51單片機的P1.0-P1.3接四個發光二極管L1-L4,用來指示當前計數的數據;用P1.4-P1.7作為預置數據的輸入端,接四個撥動開關K1-K4,用P3.6/WR和P3.7/RD端口接兩個輕觸開關,用來作加計數和減計數開關。具體的電路原理圖如下圖所示
2. 電路原理圖
圖4.12.1
3. 系統板上硬件連線
(1. 把“單片機系統”區域中的P1.0-P1.3端口用8芯排線連接到“八路發光二極管指示模塊”區域中的L1-L4上;要求:P1.0對應著L1,P1.1對應著L2,P1.2對應著L3,P1.3對應著L4;
(2. 把“單片機系統”區域中的P3.0/RXD,P3.1/TXD,P3.2/INT0,P3.3/INT1用導線連接到“四路撥動開關”區域中的K1-K4上;
(3. 把“單片機系統”區域中的P3.6/WR,P3.7/RD用導線連接到“獨立式鍵盤”區域中的SP1和SP2上;
4. 程序設計內容
(1. 兩個獨立式按鍵識別的處理過程;
(2. 預置初值讀取的問題
(3. LED輸出指示
5. 程序框圖
圖4.12.2
6. 匯編源程序 COUNT EQU 30H ORG 00H START: MOV A,P3 ANL A,#0FH MOV COUNT,A MOV P1,A SK2: JB P3.6,SK1 LCALL DELY10MS JB P3.6,SK1 INC COUNT MOV A,COUNT CJNE A,#16,NEXT MOV A,P3 ANL A,#0FH MOV COUNT,A NEXT: MOV P1,A WAIT: JNB P3.6,WAIT LJMP SK2 SK1: JB P3.7,SK2 LCALL DELY10MS JB P3.7,SK2 DEC COUNT MOV A,COUNT CJNE A,#0FFH,NEX MOV A,P3 ANL A,#0FH MOV COUNT,A NEX: MOV P1,A WAIT2: JNB P3.7,WAIT2 LJMP SK2 DELY10MS: MOV R6,#20 MOV R7,#248 D1: DJNZ R7,$ DJNZ R6,D1 RET END 7. C語言源程序 #include <AT89X51.H>
unsigned char curcount;
void delay10ms(void) { unsigned char i,j; for(i=20;i>0;i--) for(j=248;j>0;j--); }
void main(void) { curcount=P3 & 0x0f; P1=~curcount; while(1) { if(P3_6==0) { delay10ms(); if(P3_6==0) { if(curcount>=15) { curcount=15; } else { curcount++; } P1=~curcount; while(P3_6==0); } } if(P3_7==0) { delay10ms(); if(P3_7==0) { if(curcount<=0) { curcount=0; } else { curcount--; } P1=~curcount; while(P3_7==0); } } } }
13. 動態數碼顯示技術
1. 實驗任務
如圖4.13.1所示,P0端口接動態數碼管的字形碼筆段,P2端口接動態數碼管的數位選擇端,P1.7接一個開關,當開關接高電平時,顯示“12345”字樣;當開關接低電平時,顯示“HELLO”字樣。
2. 電路原理圖
圖4.13.1
3. 系統板上硬件連線
(1. 把“單片機系統”區域中的P0.0/AD0-P0.7/AD7用8芯排線連接到“動態數碼顯示”區域中的a-h端口上;
(2. 把“單片機系統”區域中的P2.0/A8-P2.7/A15用8芯排線連接到“動態數碼顯示”區域中的S1-S8端口上;
(3. 把“單片機系統”區域中的P1.7端口用導線連接到“獨立式鍵盤”區域中的SP1端口上;
4. 程序設計內容
(1. 動態掃描方法
動態接口采用各數碼管循環輪流顯示的方法,當循環顯示頻率較高時,利用人眼的暫留特性,看不出閃爍顯示現象,這種顯示需要一個接口完成字形碼的輸出(字形選擇),另一接口完成各數碼管的輪流點亮(數位選擇)。
(2. 在進行數碼顯示的時候,要對顯示單元開辟8個顯示緩沖區,每個顯示緩沖區裝有顯示的不同數據即可。
(3. 對于顯示的字形碼數據我們采用查表方法來完成。
5. 程序框圖
圖4.13.2
6. 匯編源程序 ORG 00H START: JB P1.7,DIR1 MOV DPTR,#TABLE1 SJMP DIR DIR1: MOV DPTR,#TABLE2 DIR: MOV R0,#00H MOV R1,#01H NEXT: MOV A,R0 MOVC A,@A+DPTR MOV P0,A MOV A,R1 MOV P2,A LCALL DAY INC R0 RL A MOV R1,A CJNE R1,#0DFH,NEXT SJMP START DAY: MOV R6,#4 D1: MOV R7,#248 DJNZ R7,$ DJNZ R6,D1 RET TABLE1: DB 06H,5BH,4FH,66H,6DH TABLE2: DB 78H,79H,38H,38H,3FH END 7. C語言源程序 #include <AT89X51.H>
unsigned char code table1[]={0x06,0x5b,0x4f,0x66,0x6d}; unsigned char code table2[]={0x78,0x79,0x38,0x38,0x3f}; unsigned char i; unsigned char a,b; unsigned char temp;
void main(void) { while(1) { temp=0xfe; for(i=0;i<5;i++) { if(P1_7==1) { P0=table1; } else { P0=table2; } P2=temp; a=temp<<(i+1); b=temp>>(7-i); temp=a|b; for(a=4;a>0;a--) for(b=248;b>0;b--); } }
|