最近,我們在課上講了幾個小例子,在此再把Proteus圖及程序的詳細解釋列出來,供大家參考。 - 應用查詢方式,對連接在P1.4管腳上的按鍵次數進行計數,每5次在P1.0上連接的紅色LED亮或不亮。
本題考慮點: - 應用查詢方式,即讀和檢測P1.4管腳的狀態,是1或0;
- 每5次翻轉一次,因此可設一個寄存器作為計數器,看是否到了5次,5次后清零;
- P1.0上的LED亮或不亮,即狀態翻轉,CPL P1.0。
Proteus圖 應用元器件:單片機80C51(或80C52)、按鍵Button、電阻Res、LED 圖1 找元器件的方法 單片機屬于微處理器庫里面的,因此,應再點擊Microprocessor ICS,后同。 圖2. 1題圖 程序: ORG 0H ;程序從程序存儲器的0單元開始存放 MAIN: MOV R0,#0 ;設R0為計數器,賦初始值0,注意,在這兒不賦值0,單片機一上電R0也等于0 LOOP: JB P1.4,$ ;若P1.4為高,表明沒鍵按下,等待 JNB P1.4,$ ;若P1.4為低,表明有鍵按下,等待該鍵的彈起 INC R0 ;按鍵彈起后,表明按鍵一次,計數器加1 CJNE R0,#6,LOOP ;若R0不等于6,表明還沒按夠5次,繼續查詢按鍵信息 MOV R0,#0 ;若R0=6,表明已經被按下5次,計數器清零 CPL P1.0 ;P1.0翻轉,即LED的狀態轉換 AJMP LOOP ;進入下一個循環 END ;程序結束 圖3 調試狀態
- 應用定時器,控制從P1.0和P1.1輸出周期為300us和600us的方波程序。
本題考慮點: 首先明確為應用定時器,且輸出波形為方波,周期300us和600us,也就是說,如果用這兩個管腳輸出波形的話,其翻轉的時間分別為150us和300us。 然后確定應用定時器的工作方式,對于6MHz的晶振來說,對于12分頻的單片機的機器周期為2us,即對機器周期的計數分別為75和150,都小于256,因此,可用8位定時器,并且300us是150us的整數倍,因此可用一個定時器解決。在此選用自動裝入的8位定時器,即工作方式2,設用T0。 則TMOD的取值為: 先看TMOD的各位: GATE C\T M1 M0 GATE C\T M1 M0 因為用T0來計時,且在本題目中T1不用,因此,TMOD的取值可為:00000010B , 16進制:02H 初始值的計算,應用公式: 計算得:X=106,16進制為6AH,即TH0和TL0的賦值都為6AH(因方式2位自動裝入模式) Proteus圖: 圖4 題2圖及調出示波器的位置 程序及解釋: ORG 0H ;程序從程序存儲器的0單元開始存放 AJMP MAIN ;跳轉至以MAIN為標號的主程序
ORG 0BH ;0B是定時器0的中斷子程序入口 AJMP T0INT ;跳轉到以T0INT為標號的中斷子程序
ORG 30H ;主程序從30H單元開始存放 MAIN: MOV TMOD,#20H ;設置定時器的工作方式,采用工作方式2即自動裝入的8位 MOV TH0,#8AH ;給TH0賦初值 MOV TL0,#8AH ;給TL0賦初值 SETB EA ;打開總中斷 SETB ET0 ;打開T0的中斷 SETB TR0 ;讓T0開始工作 SJMP $ ;踏步,等待中斷
T0INT: CPL P1.0 ;時間到,翻轉P1.0 INC R0 ;因為300us正好是150us的整數倍,因而可用一個定時器 CJNE R0,#2,GOON ;用R0作為中斷幾次的計數器,若中斷2次既達到150us的兩倍 MOV R0,#0 ;若達到了兩倍,翻轉,計數器清零 CPL P1.1 ;P1.1翻轉 GOON: RETI ;中斷子程序返回
END ;程序結束
圖5 波形圖 - 應用164帶3只數碼管,顯示從000-999的單個跳數;
本題考慮點: 164是移位寄存器,因此最好直接用串口,與164連接; 3位數,可把三位數設為一個計數器,設從30H-32H,其中30H為最低位,31H為中間位,32H為最高位,然后從30H開始加1,當30H加到10后,30H清零,31H再加1,31H為10后,變為零,32H再加1,當32H為10后,清零。 把顯示部分編寫為一個子程序,30-32H內的數每改變一次,調用一次顯示; 由于人的視力跟不上單片機一條指令的運算時間,因此需要延時。 因此,在軟件設計上可分為三部分:一是加數部分,一是顯示部分,一是延時部分。 Proteus圖: 圖6 題3圖 (注意RXD、TXD的接法,以及后兩只164的接法) 程序: ORG 0H ;程序從程序存儲器的0單元開始存放 AJMP MAIN ;跳轉到主程序
ORG 30H ;主程序從程序存儲器的30H單元開始存放 MAIN: MOV 30H,#0 ;給30H單元賦初始值0 MOV 31H,#0 ;給31H單元賦初始值0 MOV 32H,#0 ;給32H單元賦初始值0
LOOP: INC 30H ;30H單元內的數加1 MOV R1,30H ;將30H單元內的數賦值給R1,以便應用 CJNE Rn,#DATA,REL語言判斷并跳轉 CJNE R1,#10,NEXT ;若30H內的數不是10則跳轉到調用顯示 MOV 30H,#0 ;若30H內的數是10,則清零 INC 31H ;上位30H的數等于10時,下一位31H加1 MOV R1,31H ;將31H內的數賦值給R1 CJNE R1,#10,NEXT ;間接地判斷31H內的數是否等于10,如不是,轉顯示 MOV 31H,#0 ;若31H等于10,則清零,將32H加1 INC 32H ;32H加1(此為最高位) MOV R1,32H ;判斷32H的數值 CJNE R1,#10,NEXT ;間接判斷32H內的數是否等于10,不是轉顯示 MOV 32H,#0 ;若是32H清零 NEXT: ACALL DISPLAY ;調用顯示子程序 ACALL DELAY ;調用延時子程序 SJMP LOOP ;跳轉到加1部分,循環
DISPLAY:MOV R0,#30H ;將顯示數據的存放首單元賦值給R0,以便調用循環將數值賦值給A MOV DPTR,#TAB ;將顯示碼的首地址賦值給DPTR DISLOP:MOV A,@R0 ;將以R0內的數30H內的數值賦值給A MOVC A,@A+DPTR ;查表語句,將顯示碼賦值給A MOV SBUF,A ;將顯示碼通過串行口送出去 JNB TI,$ ;如果TI不等于1,表明還沒送出去,等待 CLR TI ;若TI=1表明數據已經送走,將送走的標志位TI清零,以便進行下次輸送 INC R0 ;指向下一單元 CJNE R0,#33H,DISLOP ;判斷是否將3個單元(30H,31H,32H)的數據都送完 RET ;子程序返回
DELAY: MOV R7,#0 ;延時子程序,給R7賦值0(相當于256) DEL1: MOV R6,#0 ;給R6賦值0 DJNZ R6,$ ;若R6-1不等于0,在此語句循環 DJNZ R7,DEL1 ;如R0=0則判斷R7-1是否為零,不為零則跳轉到DEL1,給R6重新賦值 RET ;子程序返回
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;顯示碼表 END ;程序結束 圖7 運行狀態圖
- 應用雙機通訊,實現在A機上的數碼管數字加到按另一鍵時的將該數發送到B機的數碼管上顯示。
本題考慮點: 雙機通訊,串行口的通訊方式設置; 設采用串行口方式1,則需要設置波特率,應用T1的工作方式2; 雙機都帶一只數碼管; 主機帶3只按鍵。 Proteus圖: 此處由于用P0口帶數碼管,因此因在P0各管腳上加上拉電阻,此處用排阻respack-8;公共端接高。 圖8 題4圖 編程考慮: 波特率生成器用T1的工作模式2,波特率選用9600,晶振6MHz,則TH1和TL1的賦值為0F4H,SCON選用工作模式1,且可接收。 TMOD= #20H
SCON=50H
編程: 主機程序: ORG 0H ;程序從程序存儲器的0單元開始存放 AJMP MAIN ;跳轉到以MAIN為標號的程序去 ORG 30H ;以下程序從程序存儲器的30H開始存放 MAIN: MOV TMOD,#20H ;選用定時器2工作模式,即自動賦初始值的8位定時器 MOV TH1,#0F4H ;給TH1賦值0F4H; MOV TL1,#0F4H ;給TL1賦值0F4H; SETB EA ;打開總中斷允許位; SETB ET1 ;打開定時器1的中斷允許位; SETB TR1 ;使定時器1運行 MOV SCON,#50H ;設置串行口的工作模式,采用模式1
MOV DPTR,#TAB ;賦值顯示碼表的首地址 MOV R0,#0 ;設置R0為顯示數字的計數器 MOV R1,#0 ;R1設置為訊顯示碼的中轉寄存器
KEYSCAN:JB P1.0,KEY1 ;若按鍵1沒有被按下,轉去查詢鍵2 JNB P1.0,$ ;如鍵1被按下,則等待鍵1彈起 INC R0 ;鍵1彈起后,顯示數加1 CJNE R0,#10,NEXT ;如顯示數等于10,則從0開始 MOV R0,#0 ;清零 NEXT: MOV A,R0 ;將顯示的數給A MOVC A,@A+DPTR ;查表取顯示的碼值 MOV R1,A ;將碼值給R1暫存 MOV P0,A ;將顯示碼值給P0顯示 key1: JB P1.1,KEYSCAN ;檢測第二個按鍵按下沒有 JNB P1.1,$ ;按下了等待彈起 MOV A,R1 ;將顯示碼給A MOV SBUF,A ;將顯示碼送去串行口 JNB TI,$ ;若TI不等于1,表明正在發送中 CLR TI ;TI=1,則表明已經發送完畢,將標志位清零,以便下次發送 SJMP KEYSCAN ;繼續檢測有按鍵是否被按下
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;顯示碼 END ;程序結束
從機程序: ORG 0H ;程序從程序存儲器的0單元開始存放 AJMP MAIN ;跳轉到以MAIN為標號的程序去 ORG 30H ;以下程序從程序存儲器的30H開始存放 MAIN: MOV TMOD,#20H ;選用定時器2工作模式,即自動賦初始值的8位定時器 MOV TH1,#0F4H ;給TH1賦值0F4H; MOV TL1,#0F4H ;給TL1賦值0F4H; SETB EA ;打開總中斷允許位; SETB ET1 ;打開定時器1的中斷允許位; SETB TR1 ;使定時器1運行 MOV SCON,#50H ;設置串行口的工作模式,采用模式1
LOOP: JNB RI,$ ;若RI不等于1,表明無數據通過串行口送入 CLR RI ;如RI=1,表明有數據送入,將RI清零,以便下次接收 MOV A,SBUF ;將串行口接收到的數據給A MOV P0,A ;A將接收到的數據傳送給P0,顯示 SJMP LOOP ;繼續等待接收到數據
END ;程序結束 圖9 題4運行狀態圖
- 應用外部中斷,對連接在P3.2管腳上的按鍵次數進行計數,每5次在P1.0上連接的綠色LED亮或不亮。
本題考慮點: 要求應用外部中斷,則必須應用中斷子程序,且在子程序內計數,滿5次讓P1.0翻轉。 Proteus圖: 圖10 題5圖 編程: ORG 0H ;程序從程序存儲器的0單元開始存放 AJMP MAIN ;跳轉到以標號為MAIN處
ORG 03H ;外部中斷0的9子程序入口 AJMP INT0 ;調用外部中斷子程序INT0
ORG 30H ;主程序從程序存儲器的30H單元開始存放 MAIN: SETB EA ;打開總中斷 SETB EX0 ;打開外部中斷0的中斷 SETB IT0 ;將外部中斷0的觸發信號設置為下降沿 SJMP $ ;在此等待中斷發生
INT0: INC R0 ;用R0作為計數器,每中斷一次加1 CJNE R0,#5,NEXT ;若沒中斷5次返回,等待下一次 MOV R0,#0 ;將計數器清零 CPL P1.0 ;將P1.0翻轉 NEXT: RETI ;中斷子程序返回
END ;程序結束
圖11 題5運行狀態圖
- 應用計數器,對連接在P3.4管腳上的按鍵次數進行計數,每5次在P1.0上連接的黃色LED亮或不亮。
本題考慮點: 題意用計數器,且在P3.4管腳上,即應用計數器T0; 未說明用查詢還是中斷方式,本題選用中斷方式。 Proteus圖: 圖12 題6圖 程序: ORG 0H ;主程序入口 AJMP MAIN ;跳轉到以MAIN為標號的程序
ORG 0BH ;計數器中斷0的子程序入口 AJMP INT0 ;調用外部中斷子程序INT0
ORG 30H ;主程序從程序存儲器的30H單元開始存放 MAIN: MOV TMOD,#06H ;設置計數器為8位自動裝入模式 MOV TH0,#251 ;設置TH0初始值為256-5=251 MOV TL0,#251 ;設置TL0同上 SETB EA ;打開總中斷 SETB ET0 ;打開計數器0的中斷 SETB TR0 ;將計數器0打開 MOV R0,#0 ;給R0賦值0 SJMP $ ;在此等待中斷發生
INT0: CPL P1.0 ;將P1.0翻轉 NEXT: RETI ;中斷子程序返回
END ;程序結束
|