標題: 幾個單片機匯編語言教學例程及詳細分析 [打印本頁]
作者: 17865163539 時間: 2018-4-10 09:32
標題: 幾個單片機匯編語言教學例程及詳細分析
最近,我們在課上講了幾個小例子,在此再把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 ;程序結束
作者: zirenqi 時間: 2018-6-15 22:54
很不錯,太棒了
作者: gwffg 時間: 2018-10-26 20:57
學習一下!!!
作者: xiexugang 時間: 2019-2-13 13:48
都是很好的例子,學習了。
作者: zhouchuantao 時間: 2019-2-19 03:20
在MAIN:MOV P1,#0FFH 增加此命令
作者: wusenlin 時間: 2019-3-22 18:18
有沒有初級學習的 實例教的全套
作者: 飛將軍 時間: 2019-3-31 23:34
這些例子很經典,值得認真學習一下
作者: liyijiang 時間: 2019-5-30 09:18
學習一下!!!
作者: Neo——zyc 時間: 2019-7-1 14:21
程序二有一個小錯誤,應該是mov tmod #02h
作者: 海上狂飆 時間: 2019-10-10 18:22
謝謝樓主分享,不錯的基礎學習資料
作者: Daniel008 時間: 2020-1-6 14:15
謝謝樓主分享,不錯的基礎學習資料
作者: 番茄呀 時間: 2020-4-24 11:39
謝謝樓主分享,很好的學習資料。
作者: GCG51hei 時間: 2020-4-24 14:55
謝謝分享,學習了。
作者: jms101 時間: 2020-5-26 16:23
謝謝分享


作者: 湖南孵化 時間: 2020-6-20 18:09
這個寫得真好,謝謝
歡迎光臨 (http://www.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |