新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ASM51調(diào)用C51函數(shù)的實(shí)現(xiàn)

        ASM51調(diào)用C51函數(shù)的實(shí)現(xiàn)

        作者: 時(shí)間:2016-11-18 來(lái)源:網(wǎng)絡(luò) 收藏
        MCS-51系列單片機(jī)在目前和今后的相當(dāng)一段時(shí)間內(nèi)都將是我國(guó)的單片機(jī)主流機(jī)種。但在早期的開(kāi)發(fā)過(guò)程中,程序員不得不從深?yuàn)W的匯編語(yǔ)言開(kāi)始摸索,同時(shí)要求開(kāi)發(fā)人員對(duì)硬件亦有相當(dāng)?shù)淖咏狻O啾榷裕瑢?zhuān)用8051系列單片機(jī)設(shè)計(jì)的Franklin C51語(yǔ)言是一種通用的高級(jí)結(jié)構(gòu)化的程序設(shè)計(jì)語(yǔ)言。入門(mén)容易,程序可讀性強(qiáng),調(diào)試、移植都很方便,故開(kāi)發(fā)效率高,尤其在數(shù)值運(yùn)算處理方便具有很大的優(yōu)勢(shì)(這正是ASM51匯編語(yǔ)言的薄弱環(huán)節(jié))。不過(guò),C語(yǔ)言雖然也可對(duì)計(jì)算機(jī)的硬件系統(tǒng)進(jìn)行操作,但在處理特殊I/O口和中斷向量方面,不如匯編那樣直接、有效。因而,在效率為重的今天,將ASM51匯編與C51語(yǔ)言結(jié)合起來(lái),充分發(fā)揮各自的優(yōu)勢(shì),無(wú)疑是單片機(jī)開(kāi)發(fā)人員的最佳選擇。

        1 、匯編與C51的混合編程

        本文引用地址:http://www.104case.com/article/201611/315821.htm

        一般的做法都是利用C51上手容易、便于理解的優(yōu)勢(shì)來(lái)編寫(xiě)主程序,在C51語(yǔ)言不便處理或者效率比較低時(shí)調(diào)用匯編函數(shù)。考慮到MCS-51(尤其是 8031內(nèi)部的資源配置情況:可用的RAM不到256字節(jié),5個(gè)固定地址的有限中斷源,4個(gè)8位并口中實(shí)際可作I/O口的只有P1口。因而要求開(kāi)發(fā)都對(duì)單片機(jī)的內(nèi)部結(jié)構(gòu)有清楚的了解,并盡可能地統(tǒng)籌安排這些資源。事實(shí)也證明,不理解匯編語(yǔ)言是很難寫(xiě)出高效程序的。故筆者的觀(guān)點(diǎn)是利用匯編語(yǔ)言對(duì)I/O接口、中斷向量及程序空間分配的茂大優(yōu)勢(shì),讓程序員對(duì)MCS-51內(nèi)的第一個(gè)字節(jié)甚至是每一比特(可位尋址的空間)全部進(jìn)行統(tǒng)籌安排,設(shè)計(jì)好各個(gè)程序模塊,包括 I/O口地址和中斷向量地址的處理;同時(shí)在具體的數(shù)據(jù)處理、通信等不需要過(guò)多與硬件直接打交道的程序模塊中,充分利用C51語(yǔ)言強(qiáng)大高效的編程能力。

        最后的關(guān)鍵是如何讓匯編模塊能正確識(shí)別C51函數(shù)并調(diào)用它來(lái)完成相應(yīng)的功能。ASM51匯編與C51語(yǔ)言之間的調(diào)用約定并不簡(jiǎn)單,而且各種編譯器使用的約定不盡相同,甚至還依賴(lài)于程序所選擇的大、中、小存儲(chǔ)模式。通常每個(gè)需傳遞的參數(shù)按調(diào)用順序和類(lèi)型分別由約定的寄存器來(lái)傳遞。如果參數(shù)過(guò)多或者無(wú)足夠寄存器可用時(shí),參數(shù)的傳遞將在固定持存儲(chǔ)器區(qū)域內(nèi)進(jìn)行,相同類(lèi)型的參數(shù)共享一個(gè)參數(shù)傳遞段,按參數(shù)調(diào)用順序遞增其存放地址,返回值也由約定的寄存器或地址段返回。由此可見(jiàn)程序調(diào)用的效率必將受到接口復(fù)雜度的影響。盡管目前的單片機(jī)仿真器已經(jīng)提供了標(biāo)準(zhǔn)接口的全自動(dòng)轉(zhuǎn)換功能,減少了接口工作量,但在程序的調(diào)試及移植中,如果程序員不了解這些接口的各種約定,將對(duì)出現(xiàn)的錯(cuò)誤不知所措。比如返回值不止一個(gè)時(shí),編譯器自己就無(wú)法正確完成接口配置。這里力薦一種簡(jiǎn)潔有效的調(diào)用方法——無(wú)參數(shù)化調(diào)用。

        2 、ASM51無(wú)參數(shù)化調(diào)用C51函數(shù)的實(shí)現(xiàn)原理

        所謂的無(wú)參數(shù)化調(diào)用是指讓C51子函數(shù)不帶任何參數(shù),這樣就可以從根本上避開(kāi)調(diào)用參數(shù)的傳遞和返回值的安排等繁瑣易出錯(cuò)的問(wèn)題,只需要簡(jiǎn)單地在匯編語(yǔ)言開(kāi)頭說(shuō)明一下外部C51子函數(shù)(“EXTRN code()”)。至于C51函數(shù)中需要使用的外部參數(shù)值及其返回值,完全可以通過(guò)加入C51的< absacc.h>頭文件來(lái)解決。

        頭文件中的函數(shù)原型為:

        # define CBYTE((unsigned char *)0x50000L)

        # define DBYTE ((unsigned char *)0x50000L)

        # define PBYTE ((unsigned char *)0x50000L)

        # define XBYTE((unsigned char *)0x50000L)

        其中CBYTE定義為尋址CODE程序區(qū);DBYTE定義為尋址DATA數(shù)據(jù)區(qū);PBYTE定義為尋址相對(duì)于MOVX @R0"指令的分頁(yè)數(shù)據(jù)XDATA區(qū);XBYTE定義為尋址相對(duì)于MOVX @DPTR"指令的分布數(shù)據(jù)XDATA區(qū)。它們的類(lèi)型決定了絕對(duì)地址空間的位置。

        引進(jìn)該頭文件后,程序員就可以對(duì)8051系列單片機(jī)的存儲(chǔ)器進(jìn)行絕對(duì)地址的訪(fǎng)問(wèn),把對(duì)參數(shù)值和返回值的操作轉(zhuǎn)化為對(duì)存儲(chǔ)器絕對(duì)地址的操作,像純匯編操作一樣,根本不用定義C51函數(shù)與匯編接口的參數(shù)和返回值的配置,從而提高了調(diào)用效率。具體做法是:先在C51函數(shù)中定義好傳遞參數(shù)和返回值所需要的各個(gè)絕對(duì)地址(視程序員自己的空間配置而定),在其它匯編模塊中將C51函數(shù)中將要使用的參數(shù)值放入這些絕對(duì)地址中,把被調(diào)用C51模塊將輸出的計(jì)算值(可以不止一個(gè))也放入類(lèi)似的絕對(duì)地址中。于是,當(dāng)C51函數(shù)中需要使用某個(gè)參數(shù)值時(shí),就直接從相應(yīng)的絕對(duì)地址中讀取該值;當(dāng)別的匯編模塊中需要使用C51函數(shù)返回值時(shí),也直接對(duì)存放返回值的絕對(duì)地址進(jìn)行讀操作即可。下面以一個(gè)調(diào)試通過(guò)的匯編調(diào)用C51函數(shù)的簡(jiǎn)單程序?yàn)槔M(jìn)行具體說(shuō)明。

        3 、ASM51無(wú)參數(shù)化調(diào)用C51函數(shù)的實(shí)現(xiàn)示例

        該系統(tǒng)要示然而單片機(jī)根據(jù)實(shí)時(shí)采樣輸入的轉(zhuǎn)速實(shí)現(xiàn)機(jī)車(chē)速度的測(cè)量,并可隨鍵盤(pán)輸入的車(chē)輪直徑變化實(shí)時(shí)調(diào)整車(chē)速,最后將車(chē)速和輪徑值都顯示出來(lái)。設(shè)計(jì)任務(wù)很簡(jiǎn)單,編程中的最大難度就在于車(chē)速的計(jì)算程序。由于輪徑值要求精確到mm(最大值超過(guò)了1000),車(chē)速的計(jì)算結(jié)果要保留到小數(shù)點(diǎn)后一位,因此需要進(jìn)行浮點(diǎn)數(shù)運(yùn)算,期間還要完成數(shù)的各種進(jìn)制間的換算。雖然算法簡(jiǎn)單,但實(shí)際用匯編語(yǔ)言實(shí)現(xiàn)起來(lái)經(jīng)常考慮不周,調(diào)試起來(lái)費(fèi)時(shí)費(fèi)力(筆者調(diào)試通過(guò)的這段匯編代碼長(zhǎng)達(dá)近400行)。這樣,自然就想到調(diào)用C51函數(shù)了,充發(fā)發(fā)揮兩種語(yǔ)言的優(yōu)勢(shì)。先用匯編語(yǔ)言設(shè)計(jì)好各個(gè)模塊,包括循環(huán)顯示車(chē)速和輪徑值的主程序模塊,響應(yīng)采樣轉(zhuǎn)速值和鍵盤(pán)輸入兩個(gè)中斷模塊,代碼如下所示。

        EXTRN CODE(CALL1) ;聲明外部C51函數(shù)

        ORG 0000H

        LJMP MAIN

        ORG 0003H

        AJMP KEYINPUT ;鍵盤(pán)輸入中斷

        ORG 000BH

        AJMP SETTIME ;采樣時(shí)間到,采樣轉(zhuǎn)速值中斷

        ORG 0100H

        KEYINPUT:…… ;鍵盤(pán)輸入中斷

        …… ;將鍵盤(pán)輸入信號(hào)保存在

        ;70h~73h的地址空間中

        RETI

        ORG 0600H

        SETTIME:…… ;采樣時(shí)間到,采樣轉(zhuǎn)速值中斷

        …… ;將轉(zhuǎn)速值放置在地址為3Ah的空間中

        ;緊接著調(diào)用外部C51函數(shù)CALL1()進(jìn)

        ;行車(chē)速的計(jì)算

        LCALL CALL1

        RETI

        ORG 2000H ;主程序模塊

        MAIN:…… ;首先進(jìn)行初始化操作

        ……

        ;直接從地址空間70h~77h中讀取顯示數(shù)據(jù),循環(huán)顯示車(chē)速和輪徑值

        END

        這些小模塊用匯編實(shí)現(xiàn)起來(lái)不僅容易,而且程序員可以清楚地了解到各個(gè)模塊的出入口及其相應(yīng)的功能,實(shí)現(xiàn)對(duì)程序空間的充分配置。最后用C51語(yǔ)言來(lái)實(shí)現(xiàn)車(chē)速的計(jì)算模塊CALL1()。以前用匯編編寫(xiě)的近400行代碼,一下子被壓縮到20~30行(真正的計(jì)算代碼僅9行),不僅簡(jiǎn)短易懂,而且?guī)缀蹙筒恍枰{(diào)試了。

        下面的代碼是計(jì)算模塊CALL1()及其需要的絕對(duì)地址定義。

        #pragma code small

        #include

        #include

        #define PI 3.1415926

        #define NCIRCLE DBYTE[0x3A] ;定義放置轉(zhuǎn)速的絕對(duì)地址

        #define DIRECT1 DBYTE[0x70] ;定義放置輪徑千位的絕對(duì)地址

        #define DIRECT2 DBYTE[0x71] ;定義放置輪徑百位的絕對(duì)地址

        #define DIRECT3 DBYTE[0x72] ;定義放置輪徑十位的絕對(duì)地址

        #define DIRECT4 DBYTE[0x73] ;定義放置輪徑個(gè)位的絕對(duì)地址

        #define VELOCITY1 DBYTE[0x74] ;定義返回車(chē)速的千位絕對(duì)地址

        #define VELOCITY2 DBYTE[0x75] ;定義返回車(chē)速的百位絕對(duì)地址

        #define VELOCITY3 DBYTE[0x76] ;定義返回車(chē)速的十位絕對(duì)地址

        #define VELOCITY4 DBYTE[0x77] ;定義返回車(chē)速的個(gè)位絕對(duì)地址

        void call1()

        {

        float data result;

        int data DIRECT;

        DIRECT=DIRECT1*1000+DIRECT2*100+DIRECT3*10+DIRECT4;

        result=(DIRECT/1000.0)*PI*NCIRCLE*3.6;

        VELOCITY1=result/100;

        Result=result-VELOCITY1*100;

        VELOCITY2=result/10;

        result=result-CELOCITY 2*10;

        VELOCITY3=result;

        result=result-VELOCITY3;

        VELOCITY4=result*10;

        }

        在本例中定義了絕對(duì)地址空間70h~77H和3AH。其中3AH存放采樣轉(zhuǎn)速值輸入模塊輸入的轉(zhuǎn)速;70H~73H的地址空間中存放鍵盤(pán)輸入中斷模塊中鍵盤(pán)輸入的輪徑值;而地址為74H~77H的空間中則存放計(jì)算模塊中的車(chē)速計(jì)算返回值。盡管需要傳遞和返回的參數(shù)比較多,但通過(guò)這些絕對(duì)地址的定義,完全解決了原來(lái)復(fù)雜的匯編與C51之間的調(diào)用接口配置。計(jì)算模塊中需要使用轉(zhuǎn)速和輪徑值時(shí),將自動(dòng)從絕對(duì)地址3AH和70H~73H中取值;在循環(huán)顯示車(chē)速和輪徑值的主程序模塊中則直接讀取絕對(duì)地址空間70H~77H的各個(gè)數(shù)據(jù)進(jìn)行循環(huán)顯示。當(dāng)然,程序員可以根據(jù)自己的空間配置另外定義這些絕對(duì)地址。

        以上程序代碼均已在Dais-52.196P仿真器上順利調(diào)試通過(guò)。

        由上面的簡(jiǎn)單程序可以看出這種無(wú)參數(shù)化調(diào)用方法的優(yōu)越性和有效:從程序代碼看,無(wú)論是編寫(xiě)C51子程序還是匯編主程序,都與編寫(xiě)純C51函數(shù)或者純匯編主程序的格式完全一樣,從根本上簡(jiǎn)化了C51與匯編函數(shù)之間的接口編程,提高了程序調(diào)用的效率;充分利用了匯編與高測(cè)驗(yàn)C51語(yǔ)言各自的優(yōu)點(diǎn),開(kāi)發(fā)、調(diào)試快速方便,通用性強(qiáng),尤其適合于初學(xué)者。對(duì)于復(fù)雜程序,同樣可以利用無(wú)參數(shù)化方法來(lái)幫助實(shí)現(xiàn)。這對(duì)于提高單片機(jī)應(yīng)用程序的開(kāi)發(fā)效率很有意義。

        無(wú)參數(shù)化調(diào)用實(shí)質(zhì)上在C51函數(shù)中定義了幾個(gè)全局變量(絕對(duì)地址),依靠它們直接完成參數(shù)值的傳遞和返回值的調(diào)用,相當(dāng)于一種程序員自定義的傳遞方式,拋棄了傳統(tǒng)C與匯編之間的接口約定。只要程序員安排得當(dāng),還可以進(jìn)一步人工實(shí)現(xiàn)C51中的動(dòng)態(tài)覆蓋重用,提高RAM區(qū)的利用效率。由上也可看出:無(wú)參數(shù)化調(diào)用方法要在A(yíng)SM匯編調(diào)用C51函數(shù)時(shí)才分依速無(wú)參數(shù)化思想,就違背了利用C51編程,過(guò)衷,得不償失。當(dāng)然,如果開(kāi)發(fā)人員已經(jīng)對(duì)C51與匯編函數(shù)之間的參數(shù)傳遞接口很熟悉,完全可以按接口約定或者由編譯器自動(dòng)完成參數(shù)的傳遞。



        關(guān)鍵詞: ASM51調(diào)用C51函

        評(píng)論


        技術(shù)專(zhuān)區(qū)

        關(guān)閉
        主站蜘蛛池模板: 兴义市| 玛沁县| 枣强县| 杂多县| 永州市| 弋阳县| 同心县| 阳泉市| 兴宁市| 仪陇县| 日喀则市| 曲阜市| 苗栗市| 策勒县| 河北省| 东城区| 霍林郭勒市| 张掖市| 长乐市| 仙游县| 湟中县| 盐津县| 汶川县| 东宁县| 永清县| 荃湾区| 连城县| 台东市| 慈溪市| 阿尔山市| 榆林市| 永平县| 汤原县| 广元市| 乌鲁木齐市| 惠州市| 临桂县| 嵩明县| 伊宁县| 沿河| 子洲县|