41 概述 42 簡單程序設(shè)計 43 分支程序設(shè)計 44 循環(huán)程序設(shè)計.ppt_第1頁
41 概述 42 簡單程序設(shè)計 43 分支程序設(shè)計 44 循環(huán)程序設(shè)計.ppt_第2頁
41 概述 42 簡單程序設(shè)計 43 分支程序設(shè)計 44 循環(huán)程序設(shè)計.ppt_第3頁
41 概述 42 簡單程序設(shè)計 43 分支程序設(shè)計 44 循環(huán)程序設(shè)計.ppt_第4頁
41 概述 42 簡單程序設(shè)計 43 分支程序設(shè)計 44 循環(huán)程序設(shè)計.ppt_第5頁
已閱讀5頁,還剩160頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、,4.1 概述 4.2 簡單程序設(shè)計 4.3 分支程序設(shè)計 4.4 循環(huán)程序設(shè)計 4.5 查表程序 4.6 子程序設(shè)計與堆棧技術(shù) 4.7 實用匯編子程序舉例,返回主目錄,第4章 匯編語言程序設(shè)計,4.1 概 述,我們使用的程序都是用單片機匯編語言設(shè)計的。除了匯編語言外,單片機程序設(shè)計語言還有兩類:機器語言和高級語言。 機器語言(Machine Language)是指直接用機器碼編寫程序、能夠為計算機直接執(zhí)行的機器級語言。機器碼是一串由二進(jìn)制代碼“0”和“1”組成的二進(jìn)制數(shù)據(jù),其執(zhí)行速度快,但是可讀性極差。機器語言一般只在簡單的開發(fā)裝置中使用,程序的設(shè)計、輸入、修改和調(diào)試都很麻煩,在實訓(xùn)1和實訓(xùn)

2、3中直接固化或輸入的程序都是機器語言程序。,匯編語言(Assembly Language)是指用指令助記符代替機器碼的編程語言。匯編語言程序結(jié)構(gòu)簡單,執(zhí)行速度快,程序易優(yōu)化,編譯后占用存儲空間小,是單片機應(yīng)用系統(tǒng)開發(fā)中最常用的程序設(shè)計語言。匯編語言的缺點是可讀性比較差,只有熟悉單片機的指令系統(tǒng),并具有一定的程序設(shè)計經(jīng)驗,才能研制出功能復(fù)雜的應(yīng)用程序,實訓(xùn)4中的3個程序都是用匯編語言設(shè)計的。 高級語言(High-Level Language)是在匯編語言的基礎(chǔ)上用自然語言的語句來編寫程序,例如PL/M-51、Franklin C51、MBASIC 51等,程序可讀性強,通用性好,適用于不熟悉單片

3、機指令系統(tǒng)的的用戶。,高級語言編寫程序的缺點是實時性不高,結(jié)構(gòu)不緊湊,編譯后占用存儲空間比較大,這一點在存儲器有限的單片機應(yīng)用系統(tǒng)中沒有優(yōu)勢。 目前,大多數(shù)用戶仍然使用匯編語言進(jìn)行單片機應(yīng)用系統(tǒng)的軟件設(shè)計,本章將介紹MCS-51單片機匯編語言的程序設(shè)計方法。 單片機匯編語言程序設(shè)計的基本步驟如下: (1) 題意分析。熟悉并了解匯編語言指令的基本格式和主要特點,明確被控對象對軟件的要求,設(shè)計出算法等。 (2) 畫出程序流程圖。編寫較復(fù)雜的程序,畫出程序流程圖是十分必要的。程序流程圖也稱為程序框圖,是根據(jù)控制流程設(shè)計的,它可以使程序清晰,結(jié)構(gòu)合理,便于調(diào)試。,(3) 分配內(nèi)存工作區(qū)及有關(guān)端口地址。

4、分配內(nèi)存工作區(qū),要根據(jù)程序區(qū)、數(shù)據(jù)區(qū)、暫存區(qū)、堆棧區(qū)等預(yù)計所占空間大小,對片內(nèi)外存儲區(qū)進(jìn)行合理分配并確定每個區(qū)域的首地址,便于編程使用。 (4) 編制匯編源程序。 (5) 仿真、調(diào)試程序。 (6) 固化程序。,4.2 簡單程序設(shè)計,簡單程序也就是順序程序,實訓(xùn)4中的程序1就是順序程序結(jié)構(gòu),它是最簡單、最基本的程序結(jié)構(gòu),其特點是按指令的排列順序一條條地執(zhí)行,直到全部指令執(zhí)行完畢為止。不管多么復(fù)雜的程序,總是由若干順序程序段所組成的。本節(jié)通過實例介紹簡單程序的設(shè)計方法。 例4.1 4字節(jié)(雙字)加法。將內(nèi)部RAM 30H開始的4個單元中存放的4字節(jié)十六進(jìn)制數(shù)和內(nèi)部RAM 40H單元開始的4個單元中

5、存放的4字節(jié)十六進(jìn)制數(shù)相加,結(jié)果存放到40H開始的單元中。,圖4.5 例4.1題意分析示意圖,(1) 題意分析。 題目的要求如圖4.5所示。,ORG0000H MOVA,30H ADD A,40H MOV40H,A;最低字節(jié)加法并送結(jié)果 MOVA,31H ADDCA,41H MOV41H,A;第二字節(jié)加法并送結(jié)果,(2) 匯編語言源程序。 按照雙字節(jié)加法的思路,實現(xiàn)4字節(jié)加法的源程序如下:,MOVA,32H ADDC A,42H MOV42H,A;第三字節(jié)加法并送結(jié)果 MOVA,33H ADDCA,43H MOV43H,A;第四字節(jié)加法并送結(jié)果,進(jìn)位 位在CY中 END,顯然,上面程序中,每一

6、步加法的步驟很相似,因此我們可以采用循環(huán)的方法來編程,使得源程序更加簡潔,結(jié)構(gòu)更加緊湊。用循環(huán)方法編制的源程序見習(xí)題4.3題。 例4.2 數(shù)據(jù)拼拆程序。將內(nèi)部RAM 30H單元中存放的BCD碼十進(jìn)制數(shù)拆開并變成相應(yīng)的ASCII碼,分別存放到31H和32H單元中。 (1) 題意分析。 題目要求如圖4.6所示。,圖4.6 例4.2題意分析示意圖,本題中,首先必須將兩個數(shù)拆開,然后再拼裝成兩個ASCII碼。數(shù)字與ASCII碼之間的關(guān)系是:高4位為0011H,低4位即為該數(shù)字的8421碼。 (2) 匯編語言源程序。 源程序如下: ORG 0000H MOV R0,#30H MOV A,#30H XCH

7、D A,R0;A的低4位與30H單元的低4位 交換 MOV 32H,A ;A中的數(shù)值為低位的ASCII碼,MOV A,R0 SWAPA;將高位數(shù)據(jù)換到低位 ORL A,#30H ;與30H拼裝成ASCII碼 MOV 31H,A END,4.3 分支程序設(shè)計,4.3.1 分支程序?qū)嵗?1兩分支程序設(shè)計 例4.3 兩個無符號數(shù)比較(兩分支)。內(nèi)部RAM的20H單元和30H單元各存放了一個8位無符號數(shù),請比較這兩個數(shù)的大小,比較結(jié)果顯示在實訓(xùn)的實驗板上: 若(20H)(30H),則P1.0管腳連接的LED發(fā)光; 若(20H)(30H),則P1.1管腳連接的LED發(fā)光。,(1) 題意分析。 本例是典型

8、的分支程序,根據(jù)兩個無符號數(shù)的比較結(jié)果(判斷條件),程序可以選擇兩個流向之中的某一個,分別點亮相應(yīng)的LED。 比較兩個無符號數(shù)常用的方法是將兩個數(shù)相減,然后判斷有否借位CY。若CY=0,無借位,則XY;若CY=1,有借位,則XY。程序的流程圖如圖4.7所示。,圖4.7 兩數(shù)比較流程圖,(2) 匯編語言源程序。 源程序如下: X DATA 20H ;數(shù)據(jù)地址賦值偽指令DATA Y DATA 30H ORG0000H MOV A, X ;(X) A CLRC ;CY=0 SUBBA,Y ;帶借位減法,A- (Y)-CYA,JCL1 ;CY=1,轉(zhuǎn)移到L1CLRP1.0 ;CY=0,(20H)(30

9、H),點亮P1.0連接的LED SJMPFINISH ;直接跳轉(zhuǎn)到結(jié)束等待 L1:CLRP1.1 ;(20H)(30H),點亮P1.1連接的LED FINISH:SJMP$ END (3) 執(zhí)行結(jié)果。 執(zhí)行該程序之前,利用單片機開發(fā)系統(tǒng)先往內(nèi)部RAM的20H和30H單元存放兩個無符號數(shù)(可以任意設(shè)定),執(zhí)行后觀察點亮的LED是否和存放的數(shù)據(jù)大小相一致。,2. 三分支程序設(shè)計 例4.4 兩個有符號數(shù)比較(三分支程序)。內(nèi)部RAM的20H單元和30H單元各存放了一個8位有符號數(shù),請比較這兩個數(shù)的大小,比較結(jié)果顯示在實訓(xùn)實驗板上: 若(20H)=(30H),則P1.0管腳連接的LED發(fā)光; 若(20

10、H)(30H),則P1.1管腳連接的LED發(fā)光; 若(20H)(30H),則P1.2管腳連接的LED發(fā)光。,(1) 題意分析。 有符號數(shù)在計算機中的表示方式與無符號數(shù)是不相同的:正數(shù)以原碼形式表示,負(fù)數(shù)以補碼形式表示,8位二進(jìn)制數(shù)的補碼所能表示的數(shù)值范圍為+127-128。 計算機本身無法區(qū)分一串二進(jìn)制碼組成的數(shù)字是有符號數(shù)或無符號數(shù),也無法區(qū)分它是程序指令還是一個數(shù)據(jù)。編程員必須對程序中出現(xiàn)的每一個數(shù)據(jù)的含義非常清楚,并按此選擇相應(yīng)的操作。例如,數(shù)據(jù)FEH看作無符號數(shù)其值為254,看作有符號數(shù)為-2。,比較兩個有符號數(shù)X和Y大小要比無符號數(shù)麻煩得多。這里提供一種比較思路:先判別兩個有符號數(shù)X

11、和Y的符號,如果X、Y兩數(shù)符號相反,則非負(fù)數(shù)大;如果X、Y兩數(shù)符號相同,將兩數(shù)相減,然后根據(jù)借位標(biāo)志CY進(jìn)行判斷。這一比較過程如圖4.8所示。,圖4.8 比較兩個有符號數(shù)X、Y的流程圖,(2) 匯編語言源程序。 源程序如下: XDATA 20H YDATA 30H ORG 0000H MOV A,X XRLA,Y;(X)與(Y)進(jìn)行異或操作 JBACC.7,NEXT1;累加器A的第7位為1, 兩數(shù)符號不同,轉(zhuǎn)移到NEXT1 MOV A,X CJNEA,Y,NEQUAL;(X)(Y),轉(zhuǎn)移到 NEQUAL,CLR P1.0 ;(X)=(Y),點亮P1.0連接的LED SJMP FINISH NE

12、QUAL:JC XXY ;(X)(Y),轉(zhuǎn)移到XDY NEXT1:MOVA,X JNBACC.7,XDY ;判斷(X)的最高位D7,以確定其 正負(fù),XXY:CLRP1.2 ;(X)(Y),點亮P1.1連接的LED FINISH:SJMP$ END (3) 程序說明。 判斷兩個有符號數(shù)符號異同的方法。 本例中使用邏輯異或指令,將(X)與(Y)進(jìn)行異或操作,那么,(X)的符號位(X)7與(Y)的符號位(Y)7異或的結(jié)果如下:,若(X)7與(Y)7相同,則(X)7(Y)70;若(X)7與(Y)7不相同,則(X)7(Y)71。 本例中,(X)與(Y)的異或結(jié)果存放在累加器A中,因此判斷ACC.7是否為

13、零即可知道兩個數(shù)的符號相同與否。 比較兩個有符號數(shù)的其它方法。 除了本例中使用的比較兩個有符號數(shù)的方法之外,我們還可以利用溢出標(biāo)志OV的狀態(tài)來判斷兩個有符號數(shù)的大小。具體算法如下: 若X-Y為正數(shù),則 OV=0 時 XY;OV=1 時XY。 采用這種比較方式的匯編語言源程序見習(xí)題4.10。,3. 散轉(zhuǎn)程序 散轉(zhuǎn)程序是指經(jīng)過某個條件判斷之后,程序有多個流向(三個以上)。在后面的鍵盤接口程序設(shè)計中經(jīng)常會用到散轉(zhuǎn)功能根據(jù)不同的鍵碼跳轉(zhuǎn)到相應(yīng)的程序段。 例4.5在實訓(xùn)4程序2的基礎(chǔ)之上,先設(shè)計兩個開關(guān),使CPU可以察知兩個開關(guān)組合出的4種不同狀態(tài)。然后對應(yīng)每種狀態(tài),使8個LED顯示出不同的亮滅模式。

14、(1) 硬件設(shè)計。 在實訓(xùn)1的電路中,我們使用單片機的并行口P1的輸出功能來控制8個LED的顯示?,F(xiàn)在我們使用其P3口的輸入功能來設(shè)計兩個輸入開關(guān),硬件原理圖如圖4.9所示。,圖4.9 在實訓(xùn)1原理圖基礎(chǔ)之上的例4.5硬件原理圖,如圖4.9所示,當(dāng)開關(guān)S0接通2時,P3.4管腳接地,P3.4=0;當(dāng)S0接通1時,P3.4接+5 V,P3.4=1。同樣,當(dāng)開關(guān)S1接通2時,P3.5管腳接地,P3.5=0;當(dāng)S1接通1時,P3.5接+5 V,P3.5=1。 假設(shè)要求P3口的開關(guān)狀態(tài)對應(yīng)的P1口的8個LED的顯示方式如下: P3.5 P3.4顯示方式 0 0全亮 0 1 交叉亮 1 0低4位連接的燈

15、亮,高4位滅 1 1低4位連接的燈滅,高4位亮,(2) 軟件設(shè)計。 程序設(shè)計思想。散轉(zhuǎn)程序的特點是利用散轉(zhuǎn)指令實現(xiàn)向各分支程序的轉(zhuǎn)移,程序流程圖如圖4.10所示。,圖4.10 散轉(zhuǎn)程序流程圖, 匯編語言源程序。 ORG0000H MOVP3,#00110000B ;使P3口鎖存器相應(yīng)位置位 MOVA,P3 ;讀P3口相應(yīng)引腳線信號 ANLA,#00110000B;“邏輯與”操作,屏蔽掉無 關(guān)位 SWAPA ;將相應(yīng)位移位到低位 RLA ;循環(huán)左移一位,A*2A MOVDPTR,#TABLE;轉(zhuǎn)移指令表的基地址送數(shù) 據(jù)指針DPTR JMPA+DPTR ;散轉(zhuǎn)指令,ONE: MOVP1,#00H;

16、第一種顯示方式,S0接地,S1 接地 SJMP $ TWO: MOV P1,#55H ;第二種顯示方式,S0接+5 V, S1接地 SJMP $ THREE:MOV P1,#0FH ;第三種顯示方式,S0接地,S1 接+5 V SJMP$ FOUR:MOVP1,#0F0H;第四種顯示方式,S0接 +5 V,S1接地 SJMP $,TABLE:AJMPONE;轉(zhuǎn)移指令表 AJMPTWO AJMPTHREE A JMPFOUR END (3) 程序說明。 讀P3口的管腳狀態(tài)。MCS-51的4個I/O端口共有三種操作方式:輸出數(shù)據(jù)方式,讀端口數(shù)據(jù)方式和讀端口引腳方式。,輸出數(shù)據(jù)方式舉例: MOV P

17、1,#00H ;輸出數(shù)據(jù)00HP1端口鎖存器P1引腳 讀端口數(shù)據(jù)方式舉例: MOV A,P3 ;AP3端口鎖存器 讀端口引腳方式舉例: MOV P3,#0FFH ;P3口端口鎖存器各位置1 MOV A,P3 ;AP3端口引腳狀態(tài) 注意:讀引腳方式必須連續(xù)使用兩條指令,首先必須使欲讀的端口引腳所對應(yīng)的鎖存器置位,然后再讀引腳狀態(tài)。, 散轉(zhuǎn)指令JMP A+DPTR。 散轉(zhuǎn)指令是單片機指令系統(tǒng)中專為散轉(zhuǎn)操作提供的無條件轉(zhuǎn)移指令,指令格式如下: JMP A+DPTR;PCDPTR+A 一般情況下,數(shù)據(jù)指針DPTR固定,根據(jù)累加器A的內(nèi)容,程序轉(zhuǎn)入相應(yīng)的分支程序中去。本例采用最常用的轉(zhuǎn)移指令表法,就是先

18、用無條件轉(zhuǎn)移指令按一定的順序組成一個轉(zhuǎn)移表,再將轉(zhuǎn)移表首地址裝入數(shù)據(jù)指針DPTR中,然后將控制轉(zhuǎn)移方向的數(shù)值裝入累加器A中作變址,最后執(zhí)行散轉(zhuǎn)指令,實現(xiàn)散轉(zhuǎn)。指令轉(zhuǎn)移表的存儲格式如圖4.11所示。,圖4.11 指令轉(zhuǎn)移表的存儲格式,由于無條件轉(zhuǎn)移指令A(yù)JMP是兩字節(jié)指令,因此控制轉(zhuǎn)移方向的A中的數(shù)值為 A=0 轉(zhuǎn)向AJMPONE A=2 轉(zhuǎn)向AJMPTWO A=4 轉(zhuǎn)向AJMPTHREE A=6 轉(zhuǎn)向AJMPFOUR 程序中,從P3口讀入的數(shù)據(jù)分別為0、1、2、3,因此必須乘以2來修正A的值。如果A=2,散轉(zhuǎn)過程如下: JMPA+DPTR PC=TABLE+2 AJMP TWO, 三種無條件轉(zhuǎn)

19、移指令LJMP、AJMP和SJMP 的比較。 三種無條件轉(zhuǎn)移指令在應(yīng)用上的區(qū)別有以下三點: 一是轉(zhuǎn)移距離不同,LJMP可在64 KB范圍內(nèi)轉(zhuǎn)移,AJMP指令可以在本指令取出后的2 KB范圍內(nèi)轉(zhuǎn)移,SJMP的轉(zhuǎn)移范圍是以本指令為核心的-126+129 B范圍內(nèi)轉(zhuǎn)移; 二是匯編后機器碼的字節(jié)數(shù)不同,LJMP是三字節(jié)指令,AJMP和SJMP都是兩字節(jié)指令。,三是LJMP和AJMP都是絕對轉(zhuǎn)移指令,可以計算得到轉(zhuǎn)移目的地址,而SJMP是相對轉(zhuǎn)移指令,只能通過轉(zhuǎn)移偏移量來進(jìn)行計算。 選擇無條件轉(zhuǎn)移指令的原則是根據(jù)跳轉(zhuǎn)的遠(yuǎn)近,盡可能選擇占用字節(jié)數(shù)少的指令。例如,動態(tài)暫停指令一般都選用SJMP $,而不用L

20、JMP $。,4.3.2 分支程序結(jié)構(gòu) 分支程序比順序程序的結(jié)構(gòu)復(fù)雜得多,其主要特點是程序的流向有兩個或兩個以上的出口,根據(jù)指定的條件進(jìn)行選擇確定。編程的關(guān)鍵是如何確定供判斷或選擇的條件以及選擇合理的分支指令。 通常,根據(jù)分支程序中出口的個數(shù)分為單分支結(jié)構(gòu)程序(兩個出口)和多分支結(jié)構(gòu)程序(三個或三個以上出口)。 1. 單分支結(jié)構(gòu)程序的形式 單分支結(jié)構(gòu)在程序設(shè)計中應(yīng)用最廣,擁有的指令也最多。單分支結(jié)構(gòu)一般為:一個入口,兩個出口。如圖4.12所示,單分支結(jié)構(gòu)程序有以下兩種典型形式:,圖4.12(a)表示當(dāng)條件滿足時執(zhí)行分支程序1,否則執(zhí) 行分支程序2,例4.3就是這樣的一種結(jié)構(gòu)。 圖4.12(b)

21、表示當(dāng)條件滿足時跳過程序段2,從程序段 3往下執(zhí)行,否則順序執(zhí)行程序段2和3。,圖4.12 單分支結(jié)構(gòu)程序的典型形式,另外,分支結(jié)構(gòu)程序允許嵌套,即一個分支接一個分 支,形成樹形多級分支結(jié)構(gòu)程序,例4.4就是這樣的結(jié)構(gòu)。 2. 散轉(zhuǎn)程序 在實際應(yīng)用中,常常需要從兩個以上的出口中選一個,稱 為多分支程序或散轉(zhuǎn)程序。MCS-51單片機指令系統(tǒng)中專門提 供了散轉(zhuǎn)指令,使得散轉(zhuǎn)程序的編制更加簡潔。 例4.5中采用轉(zhuǎn)移地址表法實現(xiàn)散轉(zhuǎn)程序,轉(zhuǎn)移表是由雙 字節(jié)短轉(zhuǎn)移指令“AJMP”組成的,各轉(zhuǎn)移指令地址依次相差兩 個字節(jié),所以累加器A中變址值必須作乘2修正。若轉(zhuǎn)移表是 由三字節(jié)長轉(zhuǎn)移指令“LJMP”組成,

22、則累加器A中變址值必須乘 3。當(dāng)修正值有進(jìn)位時,則應(yīng)將進(jìn)位先加在數(shù)據(jù)指針高位 字節(jié)DPH上。,此外,轉(zhuǎn)移表中使用“AJMP”指令,這就限制了轉(zhuǎn)移的 入口地址ONE、TWO、THREE、FOUR必須和散轉(zhuǎn)表首地址 TABLE位于同一個2 KB范圍內(nèi)。為了克服上述局限性,除了 可以使用“LJMP”指令組成跳轉(zhuǎn)表外,還可采用雙字節(jié)的寄存 器存放散轉(zhuǎn)值,并利用對DPTR進(jìn)行加法運算的方法,直接修 改DPTR,然后再用散轉(zhuǎn)指令實現(xiàn)散轉(zhuǎn)。 散轉(zhuǎn)程序除了轉(zhuǎn)移指令表法之外,還可以采用地址偏移 量表法、轉(zhuǎn)向地址表法及利用“RET”指令(子程序返回指令) 實現(xiàn)散轉(zhuǎn)程序等,具體實現(xiàn)參見習(xí)題4.11題。,3. 轉(zhuǎn)移條

23、件的形成 分支程序中的轉(zhuǎn)移條件一般都是程序狀態(tài)字(PSW)中標(biāo)志位的狀態(tài),因此,保證分支程序正確流向的關(guān)鍵如下: (1) 在判斷之前,應(yīng)執(zhí)行對有關(guān)標(biāo)志位有影響的指令該標(biāo)志位能夠適應(yīng)問題的要求,這就要求編程員要十分了Vcv 解指令對標(biāo)志位的影響情況。 (2) 當(dāng)某一標(biāo)志位處于某一狀態(tài)時,在未執(zhí)行下一條影響此標(biāo)志位的指令前,它一直保持原狀態(tài)不變。 (3) 正確理解PSW中各標(biāo)志位的含義及變化情況,才能正確地判斷轉(zhuǎn)移。,4.4 循環(huán)程序設(shè)計,4.4.1 循環(huán)程序?qū)嵗?1. 單重循環(huán)程序設(shè)計 例4.6 實訓(xùn)4的程序3設(shè)計。用P1口連接的8個LED模擬霓虹燈的顯示方式。編程實現(xiàn)P1口連接的8個LED顯示

24、方式如下: 按照從P1.0到P1.7的順序,依次點亮其連接的LED。 (1) 題意分析。 這種顯示方式是一種動態(tài)顯示方式,逐一點亮一個燈,使人們感覺到點亮燈的位置在移動。根據(jù)點亮燈的位置,我們要向P1口依次送入如下的立即數(shù):,FEH點亮P1.0連接的LEDMOVP1,#0FEH FDH點亮P1.1連接的LEDMOVP1,#0FDH FBH點亮P1.2連接的LEDMOVP1,#0FBH 7FH點亮P1.7連接的LEDMOVP1,#7FH 以上完全重復(fù)地執(zhí)行往P1口傳送立即數(shù)的操作,會使程序結(jié)構(gòu)松散。我們看到,控制LED點亮的顯示模式字立即數(shù)0FEH、0FDH、0FBH7FH之間存在著每次左移一位

25、的規(guī)律,因此我們可以試用循環(huán)程序來實現(xiàn)。初步設(shè)想的程序流程圖如圖4.13所示。,4.13 例4.6初步設(shè)想的程序流程圖,用匯編語言實現(xiàn)的程序如下: ORG 0000H START:MOVR2,#08H ;設(shè)置循環(huán)次數(shù) MOVA,#0FEH;從P1.0P1.7使LED逐 ;個亮過去 NEXT: MOVP1,A ;點亮LED RL A ;左移一位 DJNZR2,NEXT;次數(shù)減1,不為零,繼續(xù) ;點亮下一個LED SJMPSTART;反復(fù)點亮 END,執(zhí)行上面程序后,結(jié)果是8個燈全部被點亮,跟預(yù)想 的結(jié)果不符,為什么呢?這是因為程序執(zhí)行得很快,逐一 點亮LED的間隔太短,在我們看來就是同時點亮了,

26、因此, 必須在點亮一個LED后加一段延時程序,使該顯示狀態(tài)稍 事停頓,人眼才能區(qū)別開來。正確的程序流程圖參見實訓(xùn) 中的圖4.4。,(2) 匯編語言源程序。 本例完整的匯編語言源程序見實訓(xùn)4程序3。 由于程序設(shè)計中經(jīng)常會出現(xiàn)如圖4.14所示的次數(shù)控制循 環(huán)程序結(jié)構(gòu),為了編程方便,單片機指令系統(tǒng)中專門提供了 循環(huán)指令DJNZ,以適用于上述結(jié)構(gòu)的編程。 DJNZR2,NEXT;R2中存放控制次數(shù),R2-1R2,R20,轉(zhuǎn)移到NEXT繼續(xù)循環(huán), ;否則執(zhí)行下面指令,圖4.14 常見循環(huán)程序結(jié)構(gòu),2雙重循環(huán)程序設(shè)計延時程序設(shè)計 在上例中使用了延時程序段之后,我們才能看到正確 的顯示結(jié)果。延時程序在單片機

27、匯編語言程序設(shè)計中使用 非常廣泛,例如,鍵盤接口程序設(shè)計中的軟件消除抖動、 動態(tài)LED顯示程序設(shè)計、LCD接口程序設(shè)計、串行通信接 口程序設(shè)計等。所謂延時,就是讓CPU做一些與主程序功 能無關(guān)的操作(例如將一個數(shù)字逐次減1直到為0)來消耗 掉CPU的時間。由于我們知道CPU執(zhí)行每條指令的準(zhǔn)確時 間,因此執(zhí)行整個延時程序的時間也可以精確計算出來。 也就是說,我們可以寫出延時長度任意而且精度相當(dāng)高的 延時程序。,例4.7 設(shè)計一個延時1 s的程序,設(shè)單片機時鐘晶振頻 率為fosc=6 MHz。 (1) 題意分析。 設(shè)計延時程序的關(guān)鍵是計算延時時間。延時程序一般采 用循環(huán)程序結(jié)構(gòu)編程,通過確定循環(huán)程

28、序中的循環(huán)次數(shù)和循 環(huán)程序段兩個因素來確定延時時間。對于循環(huán)程序段來講, 必須知道每一條指令的執(zhí)行時間,這里涉及到幾個非常重要 的概念時鐘周期、機器周期和指令周期。 時鐘周期T時鐘是計算機基本時間單位,同單片機使用的 晶振頻率有關(guān)。題目給定fosc=6 MHz,那么T時鐘=1/fosc=1/6 M=166.7 ns。,機器周期T機器是指CPU完成一個基本操作所需要的時 間,如取指操作、讀數(shù)據(jù)操作等,機器周期的計算方法:T 機器=12T時鐘=166.7 ns12=2 s。 指令周期是指執(zhí)行一條指令所需要的時間。由于指令 匯編后有單字節(jié)指令、雙字節(jié)指令和三字節(jié)指令,因此指 令周期沒有確定值,一般為

29、14個T機器。在附錄2的指令表 中給出了每條指令所需的機器周期數(shù),可以計算每一條指 令的指令周期。 現(xiàn)在,我們可以來計算一下實訓(xùn)4程序3中延時程序段 的延時時間。延時程序段如下:,DELAY1:MOV R3,#0FFH DEL2: MOV R4,#0FFH DEL1: NOP DJNZ R4,DEL1 DJNZ R3,DEL2 經(jīng)查指令表得到:指令MOV R4,#0FFH、NOP、DJNZ 的執(zhí)行時間分別為2 s、2 s和4 s。 NOP為空操作指令,其功能是取指、譯碼,然后不進(jìn)行 任何操作進(jìn)入下一條指令,經(jīng)常用于產(chǎn)生一個機器的延遲。,延時程序段為雙重循環(huán),下面分別計算內(nèi)循環(huán)和外循環(huán) 的延時時

30、間。 內(nèi)循環(huán):內(nèi)循環(huán)的循環(huán)次數(shù)為255(0FFH)次,循環(huán)為以下兩條指令: NOP;2 s DJNZ R4,DEL1;4 s 內(nèi)循環(huán)延時時間為 :255(2+4)=1530 s。 外循環(huán):外循環(huán)的循環(huán)次數(shù)為255(0FFH)次,循環(huán)內(nèi)容如下: MOVR4,#0FFH;2 s 1530 us內(nèi)循環(huán) ;1530 s DJNZ R3,DEL2 ;4 s,外循環(huán)一次時間為1530 s+2 s+4 s=1536 s,循環(huán)255 次,另外加上第一條指令 MOVR3,#0FFH;2 s的循環(huán)時間2 s,因 此總的循環(huán)時間為 2s+(1530s+2s+4s)255=391682s392 ms 以上是比較精確的

31、計算方法,一般情況下,在外循環(huán)的計算中,經(jīng)常忽略比較小的時間段,例如將上面的外循環(huán)計算公式簡化為 1530 s255 = 390 150 s 390 ms,了解了延時時間的計算方法,本例我們使用三重循環(huán)結(jié)構(gòu)。程序流程圖如圖4.15所示。 內(nèi)循環(huán)選擇為1 ms,第二層循環(huán)達(dá)到延時10 ms(循環(huán)次數(shù)為10),第三層循環(huán)延時到1 s(循環(huán)次數(shù)為100)。 (2) 匯編語言源程序段。 一般情況下,延時程序均是作為一個子程序段使用,不會獨立運行它,否則單純的延時沒有實際意義。,圖4.15 延時1 s的程序流程圖,DELAY:MOVR0,#100;延時1 s的循環(huán)次數(shù) DEL2: MOVR1,#10 ;

32、延時10 ms的循環(huán)次數(shù) DEL1: MOVR2,#7DH ;延時1 ms的循環(huán)次數(shù) DEL0: NOP NOP DJNZR2,DEL0 DJNZR1,DEL1 DJNZR0,DEL2,(3) 程序說明。 本例中,第二層循環(huán)和外循環(huán)都采用了簡化計算方法,編程關(guān)鍵是延時1ms的內(nèi)循環(huán)程序如何編制。首先確定循環(huán)程序段的內(nèi)容如下: NOP ;2 s NOP ;2 s DJNZ R2,DEL0 ;4 s 內(nèi)循環(huán)次數(shù)設(shè)為count,計算方法如下式: (一次循環(huán)時間)count = 1 ms 從而得到 count = 1 ms/(2 s+2 s+4 s) = 125 = 7DH,本例提供了一種延時程序的基

33、本編制方法,若需要延時更長或更短時間,只要用同樣的方法采用更多重或更少重的循環(huán)即可。 值得注意的是,延時程序的目的是白白占用CPU一段時間,此時不能做任何其它工作,就像機器在不停地空轉(zhuǎn)一樣,這是程序延時的缺點。若在延時過程中需要CPU做指定的其它工作,就要采用單片機內(nèi)部的硬件定時器或片外的定時芯片(如8253等)。,3. 數(shù)據(jù)傳送程序 例4.8 不同存儲區(qū)域之間的數(shù)據(jù)傳輸。將內(nèi)部RAM 30H單元開始的內(nèi)容依次傳送到外部RAM 0100H單元開始的區(qū)域,直到遇到傳送的內(nèi)容是0為止。 (1) 題意分析。 本例要解決的關(guān)鍵問題是:數(shù)據(jù)塊的傳送和不同存儲區(qū)域之間的數(shù)據(jù)傳送。前者采用循環(huán)程序結(jié)構(gòu),以條

34、件控制結(jié)束;后者采用間接尋址方式,以累加器A作為中間變量實現(xiàn)數(shù)據(jù)傳輸。程序流程圖如圖4.16所示。,圖4.16 例4.8程序流程圖,(2) 匯編語言源程序。 ORG0000H MOVR0,#30H;R0指向內(nèi)部RAM數(shù)據(jù)區(qū)首地址 MOVDPTR,#0100H;DPTR指向外部RAM數(shù)據(jù)區(qū)首地址 TRANS: MOVA,R0;A(R0) MOVXDPTR,A;(DPTR)A CJNE A,#00H,NEXT SJMP FINISH;A=0,傳送完成,NEXT:INCR0 ;修改地址指針 INCDPTR AJMPTRANS;繼續(xù)傳送 FINISH:SJMP$ END (3) 程序說明。 間接尋址指

35、令。在單片機指令系統(tǒng)中,對內(nèi)部RAM讀/寫數(shù)據(jù)有兩種方式:直接尋址方式和間接尋址方式。例如:,直接方式:MOVA,30H ;內(nèi)部RAM(30H)累加器A 間接方式:MOV R0,#30H;30HR0 MOV A,R0;內(nèi)部RAM(R0)累加器A 對外部RAM的讀/寫數(shù)據(jù)只有間接尋址方式,間接尋址寄存器有R0、R1(尋址范圍是00HFFH)和DPTR(尋址范圍0000HFFFFH,整個外部RAM區(qū))。, 不同存儲空間之間的數(shù)據(jù)傳輸。MCS-51系列單片機存儲器結(jié)構(gòu)的特點之一是存在著4種物理存儲空間,即片內(nèi)RAM、片外RAM、片內(nèi)ROM和片外ROM。不同的物理存儲空間之間的數(shù)據(jù)傳送一般以累加器A作

36、為數(shù)據(jù)傳輸?shù)闹行?,如圖4.17所示。 不同的存儲空間是獨立編址的,在傳送指令中的區(qū)別在于不同的指令助記符,例如: MOVR0,#30H MOVA,R0;內(nèi)部RAM(30H)A MOVX A,R0 ;外部RAM(30H)A,圖4.17 以累加器A為中心的不同存儲空間的數(shù)據(jù)傳送示意圖,4.4.2 循環(huán)程序結(jié)構(gòu) 1. 循環(huán)程序組成 從以上循環(huán)程序?qū)嵗?,我們看到循環(huán)程序的特點是程序中含有可以重復(fù)執(zhí)行的程序段。循環(huán)程序由以下4部分組成: (1) 初始化部分。程序在進(jìn)入循環(huán)處理之前必須先設(shè)立初值,例如循環(huán)次數(shù)計數(shù)器、工作寄存器以及其它變量的初始值等,為進(jìn)入循環(huán)做準(zhǔn)備。 (2) 循環(huán)體。循環(huán)體也稱為循環(huán)處

37、理部分,是循環(huán)程序的核心。循環(huán)體用于處理實際的數(shù)據(jù),是重復(fù)執(zhí)行部分。,(3) 循環(huán)控制。在重復(fù)執(zhí)行循環(huán)體的過程中,不斷修改和判別循環(huán)變量,直到符合循環(huán)結(jié)束條件。一般情況下,循環(huán)控制有以下幾種方式: 計數(shù)循環(huán)如果循環(huán)次數(shù)已知,用計數(shù)器計數(shù)來控制循環(huán)次數(shù),這種控制方式用得比較多。循環(huán)次數(shù)要在初始化部分預(yù)置,在控制部分修改,每循環(huán)一次,計數(shù)器內(nèi)容減1。例4.6、例4.7都屬于計數(shù)循環(huán)控制方式。 條件控制循環(huán)在循環(huán)次數(shù)未知的情況下,一般通過設(shè)立結(jié)束條件來控制循環(huán)的結(jié)束,例4.8就是用條件A=0來控制循環(huán)結(jié)束的。, 開關(guān)量與邏輯尺控制循環(huán)這種方法經(jīng)常用在過程控制程序設(shè)計中,這里不再詳述。 (4) 循環(huán)結(jié)

38、束處理。這部分程序用于存放執(zhí)行循環(huán)程序所得結(jié)果以及恢復(fù)各工作單元的初值等。 2. 循環(huán)程序的基本結(jié)構(gòu) 循環(huán)程序通常有兩種編制方法:一種是先處理再判斷,另一種是先判斷后處理,如圖4.18所示。,圖4.18 循環(huán)程序的兩種基本結(jié)構(gòu)(a)先執(zhí)行后判斷;(b)先判斷后執(zhí)行,3. 多重循環(huán)結(jié)構(gòu)程序 有些復(fù)雜問題,必須采用多重循環(huán)的程序結(jié)構(gòu),即循環(huán)程序中包含循環(huán)程序或一個大循環(huán)中包含多個小循環(huán)程序,稱為多重循環(huán)程序結(jié)構(gòu),又稱循環(huán)嵌套。 多重循環(huán)程序必須注意的是各重循環(huán)不能交叉,不能從外循環(huán)跳入內(nèi)循環(huán)。例4.7的延時程序就是一個典型的三重循環(huán)結(jié)構(gòu)。 4. 循環(huán)程序與分支程序的比較 循環(huán)程序本質(zhì)上是分支程序的

39、一種特殊形式,凡是分支程序可以使用的轉(zhuǎn)移指令,循環(huán)程序一般都可以使用,并且由于循環(huán)程序在程序設(shè)計中的重要性,單片機指令系統(tǒng)還專門提供了循環(huán)控制指令,如DJNZ等。,4.5 查 表 程 序,在單片機匯編語言程序設(shè)計中,查表程序的應(yīng)用非常廣泛,在LED顯示程序和鍵盤接口程序設(shè)計中都用到了查表程序段。 例4.9 在程序中定義一個09的平方表,利用查表指令找出累加器A=05H的平方值。 (1) 題意分析。 所謂表格是指在程序中定義的一串有序的常數(shù),如平方表、字型碼表、鍵碼表等。因為程序一般都是固化在程序存儲器(通常是只讀存儲器ROM類型)中,因此可以說表格是預(yù)先定義在程序的數(shù)據(jù)區(qū)中,然后和程序一起固化

40、在ROM中的一串常數(shù)。,查表程序的關(guān)鍵是表格的定義和如何實現(xiàn)查表。 (2) 匯編語言源程序。 ORG0000H MOVDPTR,#TABLE ;表首地址DPTR(數(shù)據(jù)指針) MOVA,#05 ;05A MOVCA,A+DPTR;查表指令,25A,A=19H SJMP$;程序暫停 TABLE:DB0,1,4,9,16,25,36,49,64,81;定義09平方表 END,(3) 程序說明。 從程序存儲器中讀數(shù)據(jù)時,只能先讀到累加器A中,然后再送到題目要求的地方。單片機提供了兩條專門用于查表操作的查表指令: MOVCA,A+DPTR;(A+DPTR)A MOVCA,A+PC;PC+1PC,(A+P

41、C)A DPTR為數(shù)據(jù)指針,一般用于存放表首地址。 用指令MOVC A,A+PC實現(xiàn)查找平方表的源程序如下:,ORG 0000H MOV A,#05;05A ADD A,#02;修正累加器A的值,修正值為查表指令距離表格首地址 ;的字節(jié)數(shù)減去1 MOVCA,A+PC;25A SJMP$ TABLE:DB 0,1,4,9,16,25,36,49,64,81;定義09平方表 END,在解決實際問題時,經(jīng)常會遇到一個程序中多次使用同一個程序段,例如延時程序、查表程序、算術(shù)運算程序段等功能相對獨立的程序段。在實訓(xùn)4中,我們反復(fù)使用了延時程序段。 為了節(jié)約內(nèi)存,我們把這種具有一定功能的獨立程序段編成子程

42、序,例如延時子程序。當(dāng)需要時,可以去調(diào)用這些獨立的子程序。調(diào)用程序稱為主程序,被調(diào)用的程序稱為子程序。 本節(jié)用實例介紹子程序和堆棧的使用方法。,4.6 子程序設(shè)計與堆棧技術(shù),4.6.1 子程序?qū)嵗?例4.10 延時子程序:編程使P1口連接的8個LED按下面方式顯示:從P1.0連接的LED開始,每個LED閃爍10次,再移向下一個LED,同樣閃爍10次,循環(huán)不止。 (1) 題意分析。 在前面的例子中,我們已經(jīng)編了一些LED模擬霓虹燈的程序,按照題目要求畫出本例的程序流程圖如圖4.19所示。 在圖4.19中,兩次使用延時程序段,因此我們把延時程序編成子程序。,圖4.19 例4.10程序流程圖,(2)

43、 匯編語言源程序。 ORG0000H MAIN: MOVA,#0FE ;送顯示初值 LP:MOVR0,#10 ;送閃爍次數(shù) LP0:MOVP1,A;點亮LED LCALL DELAY;延時 MOVP1,#0FFH;熄滅燈 LCALL DELAY;延時,DJNZ R0,LP0;閃爍次數(shù)不夠10次,繼續(xù) RL A;否則A左移,下一個燈閃爍 SJMPLP;循環(huán)不止 DELAY : MOV R3,#0FFH;延時子程序 DEL2: MOV R4,#0FFH DEL1 : NOP DJNZ R4,DEL1 DJNZ R3,DEL2 RET,(3) 程序說明。 子程序調(diào)用和返回過程。在上例中,MAIN為主

44、程序,DELAY為延時子程序。當(dāng)主程序MAIN需要延時功能時,就用一條調(diào)用指令A(yù)CALL(或LCALL)DELAY即可。子程序DELAY的編制方法與一般程序遵循的規(guī)則相同,同時也有它的特殊性。子程序的第一條語句必須有一個標(biāo)號,如DELAY,代表該子程序第一個語句的地址,也稱為子程序入口地址,供主程序調(diào)用;子程序的最后一條語句必須是子程序返回指令RET。 子程序一般緊接著主程序存放,例4.10的主程序和子程序在存儲器中的存儲格式如下:,主程序: 地址機器碼指令 0005 12 *LCALL DELAY;第一次調(diào)用子程序 0008 * MOV P1,#0FFH;LCALL指令的下 一條指令首址00

45、08H稱為斷點地址,子程序: 0013 *MOVR3,#0FFH;子程序開始 001C 22RET;子程序返回 主程序兩次調(diào)用子程序及子程序返回過程如圖4.20所示。,圖4.20 子程序兩次調(diào)用、返回過程示意圖,子程序只需書寫一次,主程序可以反復(fù)調(diào)用它。CPU執(zhí)行LCALL指令所進(jìn)行的具體操作(以第一次調(diào)用為例)是: (a) PC的自動加1功能使PC=0008H,指向下一條指令MOV P1,#0FFH的首址,PC中即為斷點地址; (b) 保存PC中的斷點地址0008H; (c) 將子程序DELAY的入口地址0013H賦給PC,PC=0012H; (d) 程序轉(zhuǎn)向DELAY子程序運行。,CPU執(zhí)

46、行RET指令的具體操作(以第一次調(diào)用為例)是: (a) 取出執(zhí)行調(diào)用指令時保存的斷點地址0008H,并將它賦給PC,PC=0008H; (b) 程序轉(zhuǎn)向斷點處繼續(xù)執(zhí)行主程序。 從以上分析來看,在子程序調(diào)用過程中,斷點地址0008H是自動保存和取出的,那么斷點地址究竟存放在什么地方呢?這里引出一個新的存儲區(qū)域概念堆棧,它是一個存放臨時數(shù)據(jù)(例如斷點地址)的內(nèi)存區(qū)域。堆棧的巧妙設(shè)計使程序員不必操心數(shù)據(jù)的具體存放地址。 子程序嵌套。,修改上面的程序,將一個燈的閃爍過程也編成子程序形式。修改后的源程序如下: ORG0000H MAIN:MOVA,#0FEH ;送顯示初值 COUN:ACALL FLAS

47、H;調(diào)閃爍子程序 RLA;A左移,下一個燈閃爍 SJMPCOUN ;循環(huán)不止,FLASH:MOVR0,#10;送閃爍次數(shù) FLASH1:MOVP1,A;點亮LED LCALL DELAY;延時 MOVP1,#0FFH;熄滅燈 LCALL DELAY;延時 DJNZR0,FLASH1;閃爍次數(shù)不夠10次,繼續(xù) RET,DELAY: MOV R3,#0FFH ;延時子程序 DEL2: MOV R4,#0FFH DEL1: NOP DJNZ R4,DEL1 DJNZ R3,DEL2 RET END,上面程序中,主程序調(diào)用了閃爍子程序FLASH,閃爍子程序中又調(diào)用延時子程序DELAY,這種主程序調(diào)用子

48、程序,子程序又調(diào)用另外的子程序的程序結(jié)構(gòu),稱為子程序的嵌套。一般來說,子程序嵌套層數(shù)理論上是無限的,但實際上,受堆棧深度的影響,嵌套層數(shù)是有限的。 與子程序的多次調(diào)用不同,嵌套子程序的調(diào)用過程如圖4.21所示。,圖4.21 例4.10程序中嵌套子程序的執(zhí)行過程,例4.11 查表子程序。假設(shè)a、b均小于10,計算c=a2+b2,其中a事先存在內(nèi)部RAM的31H單元,b事先存在32H單元,請把c存入33H單元。 (1) 題意分析。 本例兩次使用平方的計算,在前面的例4.9中已經(jīng)編過查平方表得到平方值的程序,在此我們采用把求平方編為子程序的方法。 (2) 匯編語言源程序。,ORG0000H;主程序

49、MOVSP,#3FH;設(shè)置棧底 MOVA,31H;取數(shù)a存放到累加器A中 作為入口參數(shù) LCALLSQR MOVR1,A;出口參數(shù)平方值存 放在A中 MOVA,32H,ADDA,R1 MOV33H,A SJMP$ ;子程序:SQR ;功能:通過查表求出平方值y=x2 ;入口參數(shù):x存放在累加器A中 ;出口參數(shù):求得的平方值y存放在A中 ;占用資源:累加器A,數(shù)據(jù)指針DPTR,SQR: PUSHDPH ;保護(hù)現(xiàn)場,將主程序中DPTR 的高8位放入堆棧 PUSH DPL ;保護(hù)現(xiàn)場,將主程序中DPTR 的低8位放入堆棧 MOV DPTR,#TABLE ;在子程序中重新使用DPTR, 表首地址DPT

50、R MOVC A,A+DPTR ;查表 POP DPL ;恢復(fù)現(xiàn)場,將主程序中DPTR 的低8位從堆棧中彈出,POP DPH ;恢復(fù)現(xiàn)場,將主程序中DPTR的高8 位從堆棧中彈出 RET TABLE: DB0,1,4,9,16,25,36,49,64,81 (3) 執(zhí)行程序。 在運行程序之前,利用單片機開發(fā)系統(tǒng)先在內(nèi)部RAM的31H、32H存放兩個小于10的數(shù),執(zhí)行完之后,結(jié)果放在33H單元。 (4) 程序說明。, 參數(shù)傳遞。主程序調(diào)用查表子程序時,子程序需要從主程序中得到一個參數(shù)已知數(shù)x,這個參數(shù)稱為子程序的入口參數(shù)。查表子程序執(zhí)行完以后,必須將結(jié)果傳送給主程序,這個子程序向主程序傳遞的參數(shù)

51、稱為子程序的出口參數(shù)。 本例中入口參數(shù)和出口參數(shù)都是通過累加器A來傳送的。 現(xiàn)場保護(hù)和現(xiàn)場恢復(fù)。子程序在編制過程中經(jīng)常會用到一些通用單元,如工作寄存器、累加器、數(shù)據(jù)指針DPTR以及PSW等。而這些工作單元在調(diào)用它的主程序中也會用到,為此,需要將子程序用到的這些通用編程資源加以保護(hù),稱為保護(hù)現(xiàn)場。在子程序執(zhí)行完后需恢復(fù)這些單元的內(nèi)容,稱為恢復(fù)現(xiàn)場。,本例中,保護(hù)和恢復(fù)現(xiàn)場是在子程序中利用堆棧操作實現(xiàn)的,在子程序的開始部分把子程序中要用到的編程資源都保護(hù)起來,在執(zhí)行返回指令之前恢復(fù)現(xiàn)場,這是一種比較規(guī)范的方法。 另外,也可以在主程序中實現(xiàn)保護(hù)和恢復(fù)現(xiàn)場。在調(diào)用子程序前保護(hù)現(xiàn)場,子程序返回后恢復(fù)現(xiàn)場

52、,這種方式比較靈活,可以根據(jù)當(dāng)時的需要確定要保護(hù)的內(nèi)容。 子程序的說明。在查表子程序前,以程序注釋的形式對子程序進(jìn)行了說明,說明內(nèi)容如下:,(a) 子程序名:提供給主程序調(diào)用的名字。 (b) 子程序功能:簡要說明子程序能完成的主要功能。 (c) 入口參數(shù):主程序需要向子程序提供的參數(shù)。 (d) 出口參數(shù):子程序執(zhí)行完之后向主程序返回的參數(shù)。 (e) 占用資源:該子程序中使用了哪些存儲單元、寄存 器等。 這些說明是寫給程序員看的,供以后使用子程序時參考。,4.6.2 堆棧結(jié)構(gòu) 1. 堆棧概念 堆棧實際上是內(nèi)部RAM的一部分,堆棧的具體位置由堆棧指針SP確定。SP是一個8位寄存器,用于存放堆棧的棧

53、底(初始化)地址和棧頂?shù)刂贰?單片機復(fù)位或上電時,SP的初值是07H,表示堆棧棧底為07H,存入數(shù)據(jù)后,地址增1,SP中的地址值隨著加1。SP的值總是指向最后放進(jìn)堆棧的一個數(shù),此時,SP中的地址稱為棧頂?shù)刂贰6褩=Y(jié)構(gòu)示意圖如圖4.22所示。,圖4.22 堆棧結(jié)構(gòu)示意圖,2. 堆棧操作 堆棧有兩種最基本操作:向堆棧存入數(shù)據(jù)稱為“入?!被颉皦喝攵褩!保≒USH);從堆棧取出數(shù)據(jù)稱為“出棧”或“彈出堆?!保≒OP)。堆棧中數(shù)據(jù)的存取采用后進(jìn)先出方式,即后入棧的數(shù)據(jù),彈出時先彈出,類似貨棧堆放貨物的存取方式,“堆?!币辉~因此而得名。 由于單片機初始化的堆棧區(qū)域同第1組工作寄存器區(qū)重合,也就是說,當(dāng)把堆

54、棧棧底設(shè)在07H處時,就不能使用第1組工作寄存器,如果堆棧存入數(shù)據(jù)量比較大的話,甚至第2組和第3組工作寄存器也不能使用了。因此,在匯編語言程序設(shè)計中,通??偸前讯褩^(qū)的位置設(shè)在用戶RAM區(qū)。例如,MOVSP,#60H;將堆棧棧底設(shè)在內(nèi)部RAM的60H處 3. 堆棧的功能 最初,堆棧是為了子程序調(diào)用和返回而設(shè)計的,執(zhí)行調(diào)用指令(LCALL、ACALL)時,CPU自動把斷點地址壓棧;執(zhí)行返回指令RET時,自動從堆棧中彈出斷點地址。 由于堆棧操作簡單,程序員也經(jīng)常用堆棧暫存中間結(jié)果或數(shù)據(jù)。只是使用時需要注意堆棧先進(jìn)后出的特點。例如,例4.11中的子程序SQR中,恢復(fù)現(xiàn)場的順序就不能弄反,先保護(hù)的DP

55、H后恢復(fù)出來。 另外,在子程序調(diào)用時,CPU會自動利用堆棧進(jìn)行保護(hù)現(xiàn)場和恢復(fù)現(xiàn)場。,4. 堆棧操作與RAM操作的比較 堆棧作為內(nèi)部RAM的一個特殊區(qū)域,又有其獨特性,為匯編語言程序設(shè)計提供了更多的方便。同內(nèi)部RAM的操作相比較,使用堆棧有以下優(yōu)點: (1) 使用內(nèi)部RAM必須知道單元具體地址,而堆棧只需設(shè)置好棧底地址,就可放心使用,無需再記住單元具體地址。 (2) 當(dāng)我們需要重新分配內(nèi)存工作單元時,程序中使用內(nèi)部RAM的地方,都要修改單元地址,而堆棧只需修改棧底地址就行了。,(3) 堆棧所特有的先進(jìn)后出特點,使得數(shù)據(jù)彈出之后,存儲單元自動回收、再次使用,充分提高了內(nèi)存的利用率;而內(nèi)部RAM的操

56、作是不可能實現(xiàn)自動回收再利用的,必須通過編程員的重新分配,才能再次使用。,4.6.3 子程序結(jié)構(gòu) 1. 子程序的編程原則 在實際的單片機應(yīng)用系統(tǒng)軟件設(shè)計中,為了程序結(jié)構(gòu)更加清晰,易于設(shè)計,易于修改,增強程序可讀性,基本上都要使用子程序結(jié)構(gòu)。子程序作為一個具有獨立功能的程序段,編程時需遵循以下原則: (1) 子程序的第一條指令必須有標(biāo)號,明確子程序入口地址。 (2) 以返回指令RET結(jié)束子程序。,(3) 簡明扼要的子程序說明部分。 (4) 較強的通用性和可浮動性,盡可能避免使用具體的內(nèi)存單元和絕對轉(zhuǎn)移地址等。 (5) 注意保護(hù)現(xiàn)場和恢復(fù)現(xiàn)場。 2. 參數(shù)傳遞的方法 主程序調(diào)用子程序時,主程序和子程序之間存在著參數(shù)互相傳遞的問題。參數(shù)傳遞一般有以下三種方法。,1) 寄存器傳遞參數(shù) 如例4.11那樣,通過寄存器A傳遞入口參數(shù)和出口參數(shù)。 2) 利用堆棧傳遞參數(shù) 修改例4.11,利用堆棧來傳遞參數(shù),源程序如

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論