版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第4章MCS-51單片機匯編程序設計4.1匯編語言程序設計概述
4.2程序設計的基本結構及常用子程序
4.3編程及開發(fā)環(huán)境
本章小結
練習與思考題
4.1匯編語言程序設計概述
4.1.1匯編語言以及匯編語言程序設計特點
1.匯編語言的特點
以助記符標識指令的程序設計語言,就是計算機的匯編語言,一條指令就是匯編語言的一條語句。其特點如下:
(1)助記符指令和機器指令一一對應,所以用匯編語言編寫的程序效率高,占用存儲空間小,運行速度快,因此匯編語言能編寫出最優(yōu)秀的程序。
(2)使用匯編語言編程比使用高級語言困難。因為匯編語言是面向計算機的語言,匯編語言的程序設計人員必須對計算機硬件有相當深入的了解。
(3)匯編語言能直接訪問存儲器及接口電路,也能處理中斷,因此匯編語言程序能直接管理和控制硬件設備。
(4)匯編語言缺乏通用型,程序不易移植,各種計算機都有自己的匯編語言,不同計算機的匯編語言之間不能
通用。
2.匯編語言程序設計的特點
所謂程序設計就是編寫計算機程序。匯編語言程序設計就是使用匯編指令來編寫計算機程序。在進行單片機的匯編語言程序設計時請注意以下要點:
(1)在程序中要對數(shù)據(jù)的存放、寄存器和工作單元的使用等做出具體安排。
(2)設計人員必須對所使用的單片機的硬件結構有較為詳細的了解,特別是對各類寄存器、端口、定時器/計數(shù)器、中斷等內(nèi)容更應了如指掌,以便在程序設計中熟練使用。
4.1.2MCS-51匯編語言偽指令
計算機一般都配備匯編語言,每一條語句就是一條指令,命令CPU執(zhí)行一定的操作,完成規(guī)定的功能。但是用匯編語言編寫的源程序,計算機不能直接執(zhí)行,因為計算機只認識機器指令(二進制編碼)。因此必須把匯編語言源程序通過匯編程序翻譯成機器語言程序(稱為目標程序),計算機才能執(zhí)行,這個翻譯過程稱為匯編。匯編程序?qū)τ脜R編語言寫的源程序進行匯編時,還要提供一些匯編用的控制指令,例如要指定程序或數(shù)據(jù)存放的起始地址;要給一些連續(xù)存放的數(shù)據(jù)確定單元等。但是,這些指令在匯編時并不產(chǎn)生目標代碼,不影響程序的執(zhí)行,所以稱為偽指令。常用的偽指令有下列幾種:
1.ORG(Origin,起點)
ORG偽指令總是出現(xiàn)在每段源程序或數(shù)據(jù)塊的開始,它指明此語句后面的程序或數(shù)據(jù)塊的起始地址。其一般格式為
ORGnn(絕對地址或標號)
在匯編時由nn確定此語句后面第一條指令(或第一個數(shù)據(jù))的地址。該段源程序(或數(shù)據(jù)塊)就連續(xù)存放在以后的地址內(nèi),直到遇到另一個ORGnn語句為止。例4-1
ORG 8000H
MOV R0,#50H
MOV A,R4
ADD A,@R0
MOV R3,A
ORG偽指令說明其后面源程序的目標代碼在存儲器中存放的起始地址是8000H,即:
2.DB(DefineByte,定義字節(jié))
一般格式為
[標號:]DB字節(jié)常數(shù)或字符或表達式
其中,標號區(qū)段可有可無;字節(jié)常數(shù)或字符是指一個字節(jié)數(shù)據(jù),或用逗號分開的字節(jié)串,或用引號括起來的ASCII碼字符串(一個ASCII字符相當于一個字節(jié))。此偽指令的功能是把字節(jié)常數(shù)或字節(jié)串存入內(nèi)存連續(xù)單元中。例4-2
ORG9000H
DATA1:DB73H,01H,90H
DATA2:DB02H
偽指令ORG9000H指定了標號DATA1的地址為9000H,偽指令DB指定了數(shù)據(jù)73H,01H、90H順序地存放在從9000H開始的單元中,DATA2也是一個標號,它的地址與前一條偽指令DB連續(xù),為9003H,因此數(shù)據(jù)02H存放在9003H單元中,即:
3.DW(DwfineWord,定義一個字)
一般格式為
[標號碼]DW字或字符串
DW偽指令的功能與DB相似,其區(qū)別在于DB用以定義一個字節(jié),而DW用以定義一個字(規(guī)定為兩個字節(jié),即16位二進制數(shù)),故DW主要用來定義地址。存放時一個字需兩個單元。例如:
ORG 0100H
DW 2389H,75H
0100H~0103H單元中分別存放23H、89H、00H和75H。
4.EQU(Equate,等值)
一般格式為
標號EQU操作數(shù)
EQU偽指令的功能是將操作數(shù)賦予標號,使兩邊的兩個量等值。例如:
AREAEQU1000H
給標號AREA賦值為1000H,
STKEQUAREA
相當于STK?=?AREA。若AREA已賦值為1000H,則STK也為1000H。
使用EQU偽指令給一個標號賦值后,這個標號在整個源程序中的值是固定的。也就是說,在一個源程序中,任何一個標號只能賦值一次。
5.END(匯編結束)
一般格式為
[標號:]END[地址或標號]
其中標號以及操作數(shù)字段的地址或標號不是必要的。
END偽指令是一個結束標志,用來指示匯編語言源程序段在此結束。因此,在一個源程序中只允許出現(xiàn)一個END語句,并且它必須放在整個程序(包括偽指令)的最后面,是源程序模塊的最后一個語句。如果END語句出現(xiàn)在中間,則匯編程序?qū)⒉粎R編END后面的語句。例4-3
ORG8400H
PRG0EQU8450H
PRG1EQU80H
PRG2EQUB0H
MOVA,R2
MOVDPTR,#TBJ3
MOVCA,@A+DPTR
JMP@A+DPTR
TBJ3:DWPRG0
DBPRG1
DBPRG2
END上述程序中偽指令規(guī)定:程序存放在8400H開始的單元中,字節(jié)數(shù)據(jù)放在標號地址TBJ3開始的單元中,與程序區(qū)緊連著。標號PRG0賦值為8450H,PRG1賦值為80H,PRG2賦值為B0H。4.1.3匯編語言的程序設計
1.編制程序的步驟
1)任務分析
首先要對單片機應用系統(tǒng)所要完成的任務進行分析,明確系統(tǒng)的設計要求、功能要求和技術指標,然后還要對系統(tǒng)的硬件資源和工作環(huán)境進行分析,確定硬件系統(tǒng)資源。
2)算法優(yōu)化
算法是解決問題的具體方法。一個應用系統(tǒng)經(jīng)過分析、研究后,利用嚴密的數(shù)學方法或數(shù)學模型來描述,從而將一個實際的問題轉(zhuǎn)化成計算機進行處理的問題。同一個問題的算法可以多樣,結果也可能不盡相同,所以應對各種算法進行分析比較,并進行合理的優(yōu)化。
3)程序總體構思
經(jīng)過任務分析、算法優(yōu)化后,就可以進行程序的總體構思,確定程序的結構和數(shù)據(jù)形式,并考慮資源的分配和參數(shù)的計算等。根據(jù)總體構思編制程序流程圖。
程序流程圖可以分為總體流程圖和局部流程圖??傮w流程圖側重反映程序的邏輯結構和各程序模塊之間的相互關系。局部流程圖反映程序模塊的具體實施細節(jié)。
在此基礎上,一般還應編制一個資源分配表,包括數(shù)據(jù)結構和形式、參數(shù)計算、通信協(xié)議、各自程序的入口和出口說明等。
4)編制源程序
根據(jù)所用計算機的指令系統(tǒng),按照已編制的程序框圖用匯編語言編制出源程序。
5)上機調(diào)試
將編制出的程序在計算機上調(diào)試,直至實現(xiàn)預定的
功能。
2.編制程序的方法和技巧
1)采用模塊化設計
計算機應用系統(tǒng)一般由多個模塊組成,其中包括一個主程序和多個子程序模塊。每一個模塊都完成一個明確的任務,實現(xiàn)某個具體的功能,如發(fā)送、延時、顯示等。采用模塊化程序設計方法,就是將任務細化,分別設計具有能完成具體單一任務的獨立程序并分別調(diào)試,最后將這些模塊程序裝配成整體程序并進行聯(lián)調(diào)。模塊化程序設計把一個功能復雜的程序劃分成若干個單一的程序模塊,有利于程序的設計和調(diào)試,有利于程序的優(yōu)化和分工,有利于修改,提高了程序的可讀性,通用性較強,使程序的結構一目了然。所以進行程序設計學習時,一開始就要建立程序模塊化的設計思想。
2)采用循環(huán)結構和子程序
循環(huán)結構和子程序可減少程序容量,節(jié)省程序存儲空間,提高程序代碼利用效率。對于多重循環(huán),要注意各重循環(huán)的初值和循環(huán)結束的條件,避免出現(xiàn)程序無休止循環(huán)的“死循環(huán)”現(xiàn)象。對于通用的子程序,除了用于存放子程序入口參數(shù)的寄存器外,子程序中用到的其他寄存器的內(nèi)容應壓入堆棧保護現(xiàn)場,并要特別注意堆棧操作的壓入和彈出的順序。對于中斷處理子程序,除了要保護處理程序中用到的寄存器外,還要保護標志寄存器。這是由于在中斷處理過程中難免對標志位產(chǎn)生影響,而中斷處理結束返回主程序時可能會遇到以中斷前的狀態(tài)標志為依據(jù)的條件轉(zhuǎn)移指令,如果標志位被破壞,則整個程序就亂了。
4.2程序設計的基本結構及常用子程序
一般把程序結構分為3種形式,即順序結構、分支結構和循環(huán)結構。下面介紹這3種結構程序設計的基本方法。
4.2.1順序程序結構
順序程序結構是指計算機按指令在存儲器中存放的先后次序來執(zhí)行程序,除非用特殊指令讓它跳轉(zhuǎn)。例4-4
編寫1?+?2的程序。
首先用ADDA,Rn指令,該指令是將寄存器Rn中的數(shù)與累加器A中的數(shù)相加,結果存于A中,這就要求先將1和2分別送到A中和寄存器Rn中,而Rn有4組,每組有8個單元R0~R7。首先要知道Rn在哪組,默認值(不設定值)是第0組,在同一個程序中,同組中的Rn不能重復使用,不然會數(shù)據(jù)出錯,唯獨A可反復使用,不出問題。明確了這些后,可寫出程序如下: ORG0000H ;首地址
MOVR2,#02 ;(R2)=02H
MOVA,#01 ;(A)=01H
ADDA,R2 ;(A)=(A)+(R2)=03H
END ;程序結束標志,必不可少的
程序到此編寫完成,然后在仿真軟件中調(diào)試、驗證,若不對,反復修改程序,直到完全正確為止。
該程序若用ADDA,direct指令編程時,可寫出如下程序: ORG 0000H
MOV 30H,#02 ;(30H)=02H
MOV A,#01 ;(A)=01H
ADD A,30H ;(A)=(A)+(30H)=03H
END
該程序若用ADDA,#data指令編程時,可寫出如下程序:
ORG 0000H
MOV A,#01 ;(A)=01H
ADD A,#02 ;(A)=(A)+02H=03H
END從以上例子可見,同一個程序有多種編寫方法,思路不同編出來的程序不同,但結果都一樣。我們認為最后一個程序較好。
以上加法程序是最簡單的形式,加法有多種:無進位加法、進位加法、有符號加法、無符號加法,還有浮點數(shù)的加法、單字節(jié)加法、雙字節(jié)加法、多字節(jié)加法,等等。一般編寫程序時,編成通用的程序。在調(diào)用通用程序之前,先判斷是哪一種類型,再調(diào)相應的子程序。如以上1+2的程序也可以這樣編寫:先將加數(shù)和被加數(shù)分別送入40H、41H單元,加完后和送入42H單元。它的完整程序是: ORG0000H
MOV40H,#01H
MOV41H,#02H
AD1:MOVR0,#40H ;設R0為數(shù)據(jù)指針
MOVA,@R0 ;取N1
INCR0 ;修改指針
ADDA,@R0 ;N1+N2
INCR0
MOV@R0,A ;存結果
流程圖如圖4-1所示。圖4-1單字節(jié)加法程序流程圖例4-5
將兩個半字節(jié)數(shù)合并成一個1字節(jié)數(shù)。
設片內(nèi)RAM50H,51H單元各存放1個8位二進制數(shù),要求取出兩個單元中的低半字節(jié),合并成一個字節(jié)后,存入52H單元(50H單元的內(nèi)容為86H,51H單元的內(nèi)容為73H,結果52H單元的內(nèi)容為63H),程序流程圖如圖4-2所示。
程序如下:
ORG0000H
START:MOV R1,#50H;(R1)=50H
MOV A,@R1;(A)=((R1))=(50H)=86H
ANL A,#0FH;取第一個半字節(jié),
(A)=06H
SWAP A;(A)=60H
INC R1;(R1)=51H
XCHA,@R1;取第二字節(jié),(A)=73H(51H)
=60H
ANLA,#0FH;取第二個半字節(jié),(A)=03H
ORL A,@R1;拼字,(A)=63H
INC R1
MOV @R1,A;存放結果
END
此例相反的過程是將字節(jié)拆開分成兩個半字節(jié),例如將50H單元中的內(nèi)容拆開后分別送51H、52H單元中。
圖4-2半字節(jié)處理程序流程圖4.2.2分支程序結構
在處理實際事務中,只用簡單程序設計的方法是不夠的。因為大部分程序總包含有判斷、比較等情況,并根據(jù)判斷、比較的結果轉(zhuǎn)向不同的分支。下面舉兩個分支程序的例子。
例4-6
兩個無符號數(shù)比較大小。
設在兩個連續(xù)外部RAM單元ST1(8040H)和ST2(8041H)中存放兩個不帶符號的二進制數(shù),找出其中的大數(shù)存入ST3(8042H)單元中。程序流程圖如圖4-3所示。圖4-3例4-6程序流程圖程序如下:
ORG8000H
ST1 EQU8040H
START1:CLRC;進位位清0
MOVDPTR,#ST1;設數(shù)據(jù)指針
MOVXA,@DPTR;取第一數(shù)
MOVR2,A ;暫存R2
INCDPTR
MOVXA,@DTPR;取第二個數(shù)
MOV R3,A ;暫存
SUBBA,R2 ;兩數(shù)比較
MOV A,R3
JNCBIG0
MOVA,R2;第一數(shù)大
BIG0:INCDPTR
MOVX@DPTR,A;存大數(shù) SJMP$上面程序中,用減法指令SUBB來比較兩數(shù)的大小。由于這是一條帶借位的減法指令,在執(zhí)行該指令前,先把進位位清0。用減法指令通過借位(CY)的狀態(tài)判斷兩數(shù)的大小,是兩個無符號數(shù)比較大小時常用的方法。設兩數(shù)X,Y,當X≥Y時,X-Y無借位(CY)產(chǎn)生;反之借位為1,表示X<Y。用減法指令比較大小,會破壞累加器中的內(nèi)容,故做減法前先保存累加器中的內(nèi)容。執(zhí)行JNC指令后,形成了分支。執(zhí)行SJMP指令后,實現(xiàn)程序的轉(zhuǎn)移。
例4-7
將ASCII碼表的ASCII碼轉(zhuǎn)換為十六進制數(shù),如果ASCII碼不能轉(zhuǎn)換成十六進制數(shù),用戶標志位置1。
由ASCII碼表可知,30H~39H為0~9的ASCII碼,41H~46H為A~F的ASCII碼。在這一范圍內(nèi)的ASCII碼減30H或37H就可以獲得對應的十六進制數(shù)。設ASCII碼放在累加器A中,轉(zhuǎn)換結果放回A中。程序流程圖如圖4-4所示。圖4-4ASCII碼轉(zhuǎn)換為十六進制數(shù)程序流程圖程序如下:
ORG0000H
START:CLRC;CY清0
SUBBA,#30H;A=(A)-30H-CY
JCNASC;(A)<0,不是十
六進制數(shù)
CJNEA, #0AH,MM ;(A)與0AH比較
大小
MM:JC ASC ;0≤(A)<0AH,
是十六進制數(shù)
SUBB
A,#07H;A=(A)-07H-CY(A>09H)
CJNEA,#10H,NN;(A)與10H比較大小
NN:JC ASC;(A)<10H
NASC:SETB F0
ASC: SJMP ASC例4-8
求單字節(jié)有符號二進制數(shù)的補碼。
正數(shù)補碼是其本身,負數(shù)的補碼是其反碼加1。因此,程序首先判斷被轉(zhuǎn)換數(shù)的符號,負數(shù)進行轉(zhuǎn)換,正數(shù)即為補碼。設二進制數(shù)放在累加器A中,其補碼放回到A中。程序如下:
ORG
0000H
CMPT:JNB
ACC.7,NCH;(A)>0,不需轉(zhuǎn)換
CPL
A;A求反
ADD A,#1;A加1
SETB ACC.7;保存符號
NCH: SJMP NCH
分支程序在實際使用中用處很大,除了用于比較數(shù)的大小之外,常用于控制子程序的轉(zhuǎn)移。4.2.3循環(huán)程序結構
在程序設計中,只有簡單程序和分支程序是不夠的。因為簡單程序的每條指令只執(zhí)行一次,而分支程序則根據(jù)條件的不同,會跳過一些指令,執(zhí)行另一些指令。它們的特點是,每一條指令至多執(zhí)行一次。在處理實際事務時,有時會遇到多次重復處理的問題,用循環(huán)程序的方法來解決就比較合適。循環(huán)程序中的某些指令可以反復執(zhí)行多次。采用循環(huán)程序,使程序縮短,節(jié)省存儲單元。重復次數(shù)越多,循環(huán)程序的優(yōu)越性就越明顯。但是程序的執(zhí)行時間并不節(jié)省。由于要有循環(huán)準備、結束判斷等指令,速度要比簡單程序稍慢些。
1.循環(huán)程序的組成部分
循環(huán)程序一般由5部分組成:
(1)初始化部分:為循環(huán)程序做準備。如:設置循環(huán)次數(shù)計數(shù)器的初值,地址指針置初值,為循環(huán)變量賦初值等。
(2)處理部分:為反復執(zhí)行的程序段,是循環(huán)程序的實體。
(3)修改部分:每執(zhí)行一次循環(huán)體后,對指針作一次修改,使指針指向下一個數(shù)據(jù)所在位置,為進入下一輪處理做準備。
(4)控制部分:根據(jù)循環(huán)次數(shù)計數(shù)器的狀態(tài)或循環(huán)條件,檢查循環(huán)是否能繼續(xù)進行,若循環(huán)次數(shù)到或循環(huán)條件不滿足,應控制退出循環(huán),否則繼續(xù)循環(huán)。
通常(2)、(3)、(4)部分又稱為循環(huán)體。
(5)結束部分:分析及存放執(zhí)行結果。
2.循環(huán)程序的結構形式
循環(huán)程序有如下兩種形式:
(1)先進入處理部分,再控制循環(huán)。即至少執(zhí)行一次循環(huán)體。如圖4-5(a)所示。
(2)先控制循環(huán),后進入處理部分。即先根據(jù)判斷結果,控制循環(huán)的執(zhí)行與否,有時可以不進入循環(huán)體就退出循環(huán)程序,如圖4-5(b)所示。圖4-5循環(huán)程序流程圖循環(huán)結構的程序,不論是先處理后判斷,還是先判斷后處理,其關鍵是控制循環(huán)的次數(shù)。根據(jù)需要解決問題的實際情況,對循環(huán)次數(shù)的控制有多種。循環(huán)次數(shù)已知,用計數(shù)器來控制循環(huán);循環(huán)次數(shù)未知,可以按條件控制循環(huán)。
3.循環(huán)程序的分類
循環(huán)程序分為單循環(huán)程序和多循環(huán)程序。
1)單循環(huán)程序
單循環(huán)程序又可分為兩種。
(1)循環(huán)次數(shù)已知的循環(huán)程序。例4-9
工作單元清0。
在程序設計時,有時需要將存儲器中的部分地址作為工作單元,存放程序執(zhí)行的中間值和結果,此時常需要對這些工作單元清0。例如:將40H為起點的8個單元清“0”的程序段如下:
ORG 0000H
CLEAR:CLR A ;A清0
MOV R0,#40H ;確定清0單元起 始地址
MOV R7,#08 ;確定要清除的單元個數(shù)
LOOP: MOV @R0,A ;清單元
INC R0 ;指向下一個單元
DJNZ R7,LOOP ;控制循環(huán)
SJMP $
此程序的2~4句為設定循環(huán)初值,5~7句為循環(huán)體。
此程序也可寫成通用子程序形式(使用時只要給定入口參數(shù)及被清0單元個數(shù),調(diào)用此子程序就行):
ORG 0100H
CLEAR: CLR A
LOOP: MOV @R0,A
INC R0 ;修改地址指針
DJNZ R2,LOOP ;控制循環(huán)
RET若要求調(diào)用該子程序,則必須給R0、R2賦值。入口參數(shù)是由實際需要而定,若要清50H為起點的16個單元,則需編制下列程序:
ORG 0000H
MOV
R0,#50H
MOV
R2,#10H
ACALL
CLEAR
SJMP$
入口參數(shù)由實際需要而定,若要清40H為起點的20個單元,只要改動前面兩句就行。例4-10
多個單字節(jié)數(shù)據(jù)求和。
已知有n個單字節(jié)數(shù)據(jù),依次存放在片內(nèi)RAM40H單元開始的連續(xù)單元中。要求把計算結果存入R2、R3中(高位存R2,低位存R3)。
程序如下:NUNEQU0AH
ORG1000H
SAD:MOVR0,#40H ;設數(shù)據(jù)指針
MOVR5,#NUN ;計數(shù)值0AH→R5
SAD1:CLR A ;A清0
MOVR2,A ;和的高8位清0
LOOP:ADDA,@R0
JNCLOOP1 ;
INCR2 ;有進位,和的高8位+1
LOOP1:INCR0 ;指向下一數(shù)據(jù)地址
DJNZR5,LOOP
MOVR3,A
SJMP$
上述程序中,用R0作間址寄存器,每做一次加法,R0加1,數(shù)據(jù)指針指向下一數(shù)據(jù)地址。R5為循環(huán)次數(shù)計數(shù)器,控制循環(huán)的次數(shù)。
(2)循環(huán)次數(shù)未知的循環(huán)程序。以上介紹的幾個循環(huán)程序的例子,它們的循環(huán)次數(shù)都是已知的,適合用計數(shù)器置初值的方法。而有些循環(huán)程序事先不知道循環(huán)次數(shù),不能用以上方法。這時需要根據(jù)判斷循環(huán)條件的成立與否,或用建立標志的方法,控制循環(huán)程序的
結果。例4-11測試字符串長度。
設有一串字符依次存放在從40H單元開始的連續(xù)單元中,該字符串以回車符為結束標志,測得的字符串長度存入R2中。
測字符串長度程序是將該字符串中的每一個字符依次與回車符相比:若比較不相等,則統(tǒng)計字符串長度的計數(shù)器加1,繼續(xù)比較;若比較相等,則表示該字符串結束,計數(shù)器中的值就是字符串的長度。程序如下:
ORG0000H
CONT:MOVR2,#0FFH;初始長度設置
LMOV R0,#3FH;數(shù)據(jù)指針R0置初值
LOOP1: INC R0
INC R2
NEXT: CJNE@R0,#0DH,LOOP
;((R0))=0DH?
SJMP $待測字符以ASCII碼形式存放在片內(nèi)RAM中,回車符的ASCII碼為0DH,程序中用一條CJNE@R0,#0DH,LOOP指令實現(xiàn)字符比較及控制循環(huán)的任務。當循環(huán)結束時,R2的內(nèi)容為字符串長度。
2)多重循環(huán)程序
如果在一個循環(huán)體中又包含了其他的循環(huán)程序,即循環(huán)中還套著循環(huán),這種程序稱為多重循環(huán)程序。
例4-12
10s延時程序。
延時程序與MCS-51執(zhí)行指令的時間有關,如果使用6MHz晶振,一個機器周期為2μs,計算出執(zhí)行一條指令以至一個循環(huán)所需要的時間,給出相應的循環(huán)次數(shù),便能達到延時的目的。
程序如下:
ORG 1000H
DEL: MOV R5,#100
DEL0:MOV R6,#200
DEL1:MOV R7,#248
DEL2:DJNZ R7,DEL2 ;248*2
DJNZ R6,DEL1 ;(248*2+3)*200
DJNZ R5,DEL0 ;((248*2+3)*200+3)*100 RET 上例延時程序?qū)嶋H延時為10.000406s,它是一個三重循環(huán)程序。利用程序嵌套的方法對時間實行延遲是程序設計中常用的方法。使用多重循環(huán)程序時,必須注意以下幾點:
(1)循環(huán)嵌套必須層次分明,不允許產(chǎn)生內(nèi)外層循環(huán)交叉。
(2)外循環(huán)可以層層向內(nèi)循環(huán)進入,結束時由里往外層層退出。
(3)內(nèi)循環(huán)體可以直接轉(zhuǎn)入外循環(huán)體,實現(xiàn)一個循環(huán)由多個條件控制的循環(huán)結構方式。4.2.4程序設計舉例
1.BCD碼轉(zhuǎn)換為ASCII碼
例4-13請編寫能把20H單元內(nèi)兩個BCD數(shù)變換成相應ASCII碼,放在22H(高位BCD數(shù)的ASCII碼)和21H(低位BCD數(shù)的ASCII碼)單元的程序。
根據(jù)ASCII字符表,0~9的BCD數(shù)和它們的ASCII碼之間僅相差30H。因此,僅需把20H單元中兩個BCD數(shù)拆開,分別與30H相加就行了。
程序如下: ORG 0000H
ASCH:MOVR0,#21H ;R0為地址指針,指向21H單元
MOV A,20H;取初值
ANL A,#0FH ;屏蔽高4位
ADD A,#30H ;加30H(即為ASCII碼)
MOV @R0,A ;保存結果在21H單元
MOV A,20H ;取初值
SWAPA ;高4位和低4位交換
ANL A,#0FH ;保留低4位
ORL A,#30H ;相當于加30H
INCR0 ;修改指針
MOV @R0,A ;保存結果
SJMP $
2.加法運算
例4-14無符號的多個單字節(jié)數(shù)加法。多個單字節(jié)數(shù)(假設7個字節(jié))依次存放在片內(nèi)RAM21H開始的連續(xù)單元中,要求將計算結果存放在R1和R2中(假定相加的和為2字節(jié)數(shù)),其中R1為高位,R2為低位。
程序如下:
ORG 2000H
MOV R0,#21H;定義R0為地址指針
MOV R3,#07H;定義字節(jié)數(shù)
MOV R2,#00H;定義和的初值(低字節(jié))
MOV R1,#00H;定義和的初值(高字節(jié))
LOOP:MOVA,@R0 ;取加數(shù)
ADD A,R2 ;加法運算
MOV R2,A;存結果
JNC LOOP1;判斷有進位?
INC R1;有進位高字節(jié)加1
LOOP1:INC R0;修改地址指針
DJNZ R3,LOOP;字節(jié)數(shù)減1,并判斷為零?
JMP $
例4-15無符號的兩個多字節(jié)數(shù)相加。設有兩個多字節(jié)(7個)無符號數(shù)分別存放在片內(nèi)RAM的單元21H和41H開始的單元中,低字節(jié)在前,高字節(jié)在后,和存放在21H開始的單元中,和的總字節(jié)個數(shù)存放在20H單元。
程序如下:
ORG 0000H
NADD:MOV R7,#07H;定義字節(jié)數(shù)
MOV R0,#21H;定義被加數(shù)的地址指針
MOV R1,#41H;定義加數(shù)的地址指針
CLR C ;進位標志清0
MOV R2,#00H
NADD1:MOV A,@R0;讀被加數(shù)
ADDC A,@R1;帶進位的加法運算
MOV @R0,A;存結果
INC R0 ;修改被加數(shù)的地址指針
INC R1 ;修改加數(shù)的地址指針
INC R2 ;字節(jié)數(shù)加1
DJNZ R7,NADD1
JNC LOOP ;判斷有進位?
MOV @R0,#01H ;保存最高字節(jié)數(shù)運算的 進位
LOOP:MOV 20H,R2
SJMP $
3.查表程序
查表專用指令有:
MOVC A,@A+DPTR
MOVC A,@A+PC
這兩條指令的功能完全相同,它們的共同優(yōu)點在于不改變PC和DPTR的狀態(tài),只根據(jù)A的內(nèi)容就可以查出所需數(shù)據(jù)。
例4-16
將1位十六進制數(shù)轉(zhuǎn)換為ASCII碼子程序。將20H單元的一個2位十六進制數(shù)轉(zhuǎn)換為兩個ASCII代碼,并存放在20H和21H單元。方法1:
ORG 0000H
HASC:MOV R0,#20H ;R0為參數(shù)指針
MOV A,@R0 ;取出參數(shù)
ANL A,#0FH ;取字節(jié)的低4位
ADD A,#0BH ;加偏移量
MOVC A,@A+PC ;查表
XCH A,@R0 ;查表結果放回堆棧中,
重取值
SWAP A ;半字節(jié)交換ANL
A,#0FH ;取字節(jié)的高4位
ADD
A,#03H ;加偏移量
MOVC
A,@A+PC ;查表
INC
R0 ;修改指針
MOV @R0,A ;高位的ASCII碼存放
SJMP $
DB ‘0123456789’
;十六進制數(shù)的ASCII字符表
DB 'ABCDEF'方法2:
ORG 2000H
HTA2:MOV R0,#20H
MOV DPTR,#STB ;表的首地址
MOVA,@R0 ;取出參數(shù)
ANL A,#0FH
MOVCA,@A+DPTR;查表
XCH A,@R0 ;低位HEX的ASCII碼 放入堆棧中
SWAPAANL A,#0FH ;
MOVCA,@A+DPTR
INC R0
MOV @R0,A ;
SJMP $
ORG 2100H
STB: DB '0123456789'
DB 'ABCDEF
4.數(shù)據(jù)極值查找程序(在指定的數(shù)據(jù)區(qū)中找出最大值或最小值)
例4-17片內(nèi)RAM20H單元開始存放10個無符號8位二進制數(shù),找出其中的最大數(shù),并存放在30H單元。極值查找流程圖如圖4-6所示。圖4-6極值查找程序流程程序如下:
ORG 2000H
MOV R0,#20H ;數(shù)組的首地址
MOV R7,#09H ;數(shù)組長度-1
MOV A,@R0 ;讀第一個數(shù)
LOOP:INC R0 ;修改指針
MOV 30H,@R0 ;讀下一個數(shù)
CJNE A,30H,CHK;數(shù)值比較
CHK:JNC LOOP1;A值較大轉(zhuǎn)移
MOV A,@R0 ;較大數(shù)送ALOOP1:DJNZ R7,LOOP ;繼續(xù)
MOV 30H,A ;極值送30H單元
HERE: AJMP HERE
5.數(shù)據(jù)檢索程序(在指定數(shù)據(jù)區(qū)中查找關鍵字)
一般有兩種檢索方法:順序檢索和對分檢索。下面我們只介紹順序檢索。
例4-18
假定數(shù)據(jù)區(qū)首地址是片內(nèi)RAM20H,數(shù)據(jù)的長度為10,關鍵字存放在30H單元中,把檢索成功的數(shù)據(jù)序號放在31H單元中,若數(shù)據(jù)區(qū)中無該關鍵字,則31H單元存放00H標志。
檢索開始應把31H單元設為00H。程序結束后,如31H單元的內(nèi)容還為00H,則表示沒有檢索到關鍵字;否則即為檢索成功,30H單元的內(nèi)容即為關鍵字在數(shù)據(jù)區(qū)中的序號。程序如下:
ORG 2000H
MOV R0,#20H ;數(shù)據(jù)區(qū)的首地址
MOV R7,#0AH ;數(shù)據(jù)個數(shù)
MOV R2,#00H ;序號初值
MOV 30H,#KEY ;關鍵字
NEXT: INC R2
MOV A,30H ;取關鍵字
SUBB A,@R0 ;與關鍵字比較
JZ ENDP ;相同則轉(zhuǎn)
INC
R0;修改指針
DJNZR7,NEXT;繼續(xù)
MOVR2,#00H
ENDP:MOV31H,R2 ;送檢索結果
HERE:AJMPHERE
4.2.5常用子程序
在實際程序中,常常會多次進行一些相同的計算和操作,如數(shù)制轉(zhuǎn)換、函數(shù)式計算等。如果每次都從頭開始編制一段程序,不僅麻煩,而且浪費存儲空間。因此對一些常用的程序段,以子程序的形式,事先存放在存儲器的某一區(qū)域。當主程序運行到需要用子程序時,只需執(zhí)行調(diào)用子程序的指令,使程序轉(zhuǎn)至子程序執(zhí)行即可。子程序處理完畢,返回主程序,繼續(xù)進行以后的操作。調(diào)用子程序有如下優(yōu)點:
(1)避免對相同程序段的重復編制。
(2)簡化程序的邏輯結構,同時也便于主程序調(diào)試。
(3)節(jié)省存儲器空間。
MCS-51指令系統(tǒng)中,提供了兩條調(diào)用子程序指令ACALL及LCALL,和一條返回主程序的指令RET。
調(diào)用子程序時,主程序應先把有關的參數(shù)(入口參數(shù))存放在約定的位置。子程序執(zhí)行時,可以從約定的位置取得參數(shù)。當子程序執(zhí)行完,將得到的結果(出口參數(shù))存入約定的位置,返回主程序后,主程序可以從這些約定的位置上取到需要的結果,這就是參數(shù)的傳遞。
例4-19
多字節(jié)BCD碼加法。標號:BCDA。
入口條件:字節(jié)數(shù)在R7中,被加數(shù)在R0中,加數(shù)在R1中,多字節(jié)的存放高字節(jié)在前,低字節(jié)在后。出口信息:和在R0中,最高位進位在CY中。影響資源:PSW、A。BCDA: MOV A,R7
;取字節(jié)數(shù)至R2中
ADD
A,R0
;初始化數(shù)據(jù)指針
MOV
R0,A
MOV
A,R7
ADD
A,R1
MOV
R1,A
CLR
CBCD1:DEC
R0
;調(diào)整數(shù)據(jù)指針
DEC
R1
MOV
A,@R0
ADDC
A,@R1
;按字節(jié)相加
DA
A
;十進制調(diào)整
MOV
@R0,A
;和存入R0內(nèi)容為地址的單
元中
DJNZ
R2,BCD1
;處理完所有字節(jié)
RET例4-20雙字節(jié)二進制無符號數(shù)乘法。標號:MULD。
入口條件:被乘數(shù)在R2、R3中,乘數(shù)在R6、R7中。出口信息:乘積在R2、R3、R4、R5中。影響資源:PSW、A、B、R2~R7。堆棧需求:2字節(jié)。MULD:MOV
A,R3 ;計算R3乘R7
MOV
B,R7
MUL AB
MOV
R4,B
;暫存部分積
MOV
R5,A
MOV
A,R3
;計算R3乘R6
MOV
B,R6
MUL
AB
ADD
A,R4
;累加部分積
MOV
R4,A
CLR
A
ADDC
A,B
MOV
R3,AMOV
A,R2
;計算R2乘R7
MOV
B,R7
MUL
AB
ADD
A,R4
;累加部分積
MOV
R4,A
MOV
A,R3
ADDC
A,B
MOV
R3,A
CLR
A
RLC
A
XCH
A,R2
;計算R2乘R6
MOV
B,R6
MUL
AB
ADD
A,R3
;累加部分積
MOV
R3,A
MOV
A,R2
ADDC
A,B
MOV
R2,A
RET
例4-21ASCII碼轉(zhuǎn)換成十六進制數(shù)。標號:ASCH。
入口條件:待轉(zhuǎn)換的ASCII碼(30H~39H或41H~46H)在A中。出口信息:轉(zhuǎn)換后的十六進制數(shù)(00H~0FH)仍在累加器A中。影響資源:PSW、A。堆棧需求:2字節(jié)。
ASCH:
CLR
C
SUBB
A,#30H
JNB
ACC.4,ASH1
SUBB
A,#7
ASH1: RET例4-22
單字節(jié)十六進制整數(shù)轉(zhuǎn)換成單字節(jié)BCD碼整數(shù)。標號:HBCD。
入口條件:待轉(zhuǎn)換的單字節(jié)十六進制整數(shù)在累加器A中。出口信息:轉(zhuǎn)換后的BCD碼整數(shù)(十位和個位)仍在累加器A中,百位在R3中。影響資源:PSW、A、B、R3。堆棧需求:2字節(jié)。HBCD:
MOV
B,#100;分離出百位,存放在R3中
DIV
AB
MOV
R3,A
MOV
A,#10
;余數(shù)繼續(xù)分離十位和個位
XCH
A ,B
DIV
AB
SWAP
A
ORL
A,B
;將十位和個位拼裝成BCD碼
RET
例4-23
單字節(jié)BCD碼整數(shù)轉(zhuǎn)換成單字節(jié)十六進制整數(shù)。標號:BCDH。
入口條件:待轉(zhuǎn)換的單字節(jié)BCD碼整數(shù)在累加器A中。出口信息:轉(zhuǎn)換后的單字節(jié)十六進制整數(shù)仍在累加器A中。影響資源:PSW、A、B、R4。堆棧需求:2字節(jié)。BCDH:MOV
B,#10H
;分離十位和個位
DIV
AB
MOV
R4,B;暫存?zhèn)€位
MOV
B,#10;將十位轉(zhuǎn)換成十六進制
MUL AB
ADDA,R4
;按十六進制加上個位
RET
例4-24
求單字節(jié)十六進制無符號數(shù)據(jù)塊的極值。標號:MM。
入口條件:數(shù)據(jù)塊的首址在DPTR中,數(shù)據(jù)個數(shù)在R7中。出口信息:最大值在R6中,地址在R2R3中;最小值在R7中,地址在R4R5中。影響資源:PSW、A、B、R1~R7。堆棧需求:4字節(jié)。MM:MOV B,R7;保存數(shù)據(jù)個數(shù)
MOVX
A,@DPTR ;讀取第一個數(shù)據(jù)
MOV R6,A
;作為最大值的初始值
MOV
R7,A
;也作為最小值的初始值
MOV A,DPL ;取第一個數(shù)據(jù)的地址
MOV
R3,A
;作為最大值存放地址的初始值
MOV
R5,A;也作為最小值存放地址的初始值
MOV
A,DPH
MOV
R2,A
MOV R4,A
MOV
A,B
;取數(shù)據(jù)個數(shù)
DEC
A
;減1,得到需要比較的次數(shù)
JZ
MME
;只有一個數(shù)據(jù),不需要比較
MOV
R1,A
;保存比較次數(shù)
PUSH
DPL
;保護數(shù)據(jù)塊的首址
PUSH
DPH
MM1:INC DPTR
;指向一個新的數(shù)據(jù)
MOVXA,@DPTR ;讀取這個數(shù)據(jù)
MOV
B,A
;保存
SETB
C
;與最大值比較
SUBB
A,R6
JCMM2
;不超過當前最大值,保持當前
最大值
MOV R6,B;超過當前最大值,更新最大值
存放地址
MOV
R2,DPH;同時更新最大值存放地址
MOV
R3,DPL
SJMP
MM3
MM2:MOV
A,B ;與最小值比較
CLR
C
SUBB
A,R7
JNC
MM3
;大于或等于當前最小值,保持
當前最小值
MOV
R7,B
;更新最小值
MOV
R4,DPH;更新最小值存放地址
MOV
R5,DPL
MM3:DJNZ
R1,MM1;處理完全部數(shù)據(jù)
POP DPH
;恢復數(shù)據(jù)首址
POP
DPL
MME:
RET4.3編程及開發(fā)環(huán)境
4.3.1WAVE6000MCS-51單片機編程開發(fā)環(huán)境
WAVE6000是MCS-51單片機的開發(fā)平臺,其使用步驟如下:
(1)建立新程序。選擇菜單[文件/新建文件],如圖4-7所示。圖4-7新建文件
(2)在出現(xiàn)的源程序窗口中輸入所需編寫的程序,如圖4-8所示。圖4-8編輯源程序
(3)保存程序。選擇菜單[文件/保存文件],保存時文件名稱必須帶上后綴名[.asm],如圖4-9所示。建議保存在一個文件夾下。
(4)仿真器設置。選擇菜單[仿真器/設置/仿真器設置],在彈出的[仿真器設置]對話框中,按圖4-10設置,選擇[使用偉福軟件模擬器]。圖4-9保存文件圖4-10仿真器設置
(5)編譯程序。選擇菜單[項目/編譯],進行編譯程序。若無錯,則單擊[好]進入下一步;若有錯,則先修改程序,然后再進行編譯程序。
(6)執(zhí)行程序。選擇菜單[執(zhí)行],進行程序執(zhí)行。執(zhí)行方式可分為全速執(zhí)行、跟蹤執(zhí)行、單步執(zhí)行、執(zhí)行到光標處,如圖4-11所示。圖4-11編輯窗口
(7)查看結果。選擇菜單[窗口/數(shù)據(jù)窗口/DATA],如圖4-12所示。DATA—片內(nèi)RAM區(qū)域CODE—ROM區(qū)域
XDATA—片外RAM區(qū)域
PDATA—分頁式數(shù)據(jù)存儲器,51中無用BIT—位尋址區(qū)域圖4-12觀察結果窗口4.3.2MPLABPIC單片機集成開發(fā)環(huán)境
開發(fā)PIC單片機時使用Microchip公司提供的MPLAB集成開發(fā)環(huán)境(IDE),該環(huán)境是一個綜合編輯器、項目管理器和設計平臺。下面介紹其具體使用步驟。
1.創(chuàng)建項目
1)編寫代碼并保存
(1)編寫代碼。雙擊MPLABIDE編輯器桌面圖標進入開發(fā)環(huán)境,選擇[File/New],在工作區(qū)中打開一個空白的代碼編寫窗口。在該窗口中輸入?yún)R編代碼,如圖4-13所示。圖4-13代碼編寫窗口
(2)文件保存。輸入完代碼后,選擇[File/Save]保存文件。例如保存在名為D:\MyProj的新文件夾下,取名為test.asm,如圖4-14所示。單擊[保存]按鈕,完成文件保存。圖4-14文件保存窗口
2)創(chuàng)建項目
這里,舉例使用MPLAB項目向?qū)?chuàng)建開發(fā)應用程序
項目。
(1)啟動向?qū)?。選擇[Project/ProjectWizard]啟動項目向?qū)В霈F(xiàn)歡迎界面,如圖4-15所示,單擊[下一步]按鈕繼續(xù),出現(xiàn)器件選擇窗口,如圖4-16所示。圖4-15項目導向界面
3)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度商業(yè)搬遷及裝修服務合同3篇
- 2024智能制造-工業(yè)機器人研發(fā)與銷售合同
- 孕產(chǎn)期心理健康從醫(yī)學角度看維護策略
- 二零二五年度企業(yè)內(nèi)部會議信息保密承諾書6篇
- 2025年度消防疏散指示系統(tǒng)安裝補充合同范本3篇
- 花卉育苗課程設計報告
- 2024年汽車維修中心員工勞動合同書模板2篇
- 培養(yǎng)良好語文習慣對兒童心理發(fā)展的影響
- 2024年物業(yè)維修基金管理章程3篇
- 課程設計萬用電表
- 天然氣長輸管道安全培訓
- 2024版《隱患排查標準手冊》(附檢查依據(jù))
- 2024年三門峽職業(yè)技術學院單招職業(yè)技能測試題庫及答案解析
- (高清版)DZT 0268-2014 數(shù)字地質(zhì)數(shù)據(jù)質(zhì)量檢查與評價
- 泛微協(xié)同管理平臺(e-cology)產(chǎn)品白皮書2015-V1.0
- 車間生產(chǎn)中的節(jié)能減排與環(huán)境保護技術
- 內(nèi)蒙古自治區(qū)呼和浩特市2023-2024學年英語九上期末學業(yè)質(zhì)量監(jiān)測試題含解析
- 重慶工作報告
- 通用勞務合同Word模板下載(多份)
- 教科版科學四年級下冊第二單元《電路》教學計劃
- 第七講 磁電選
評論
0/150
提交評論