c編譯器應(yīng)用篇,利用SDCC c編譯器開(kāi)發(fā)微控制器
對(duì)于c編譯器,很多朋友均有所了解。往期文章中,小編為大家?guī)?lái)過(guò)諸多c編譯器文章。在這篇c編譯器相關(guān)文章中,小編將介紹如何基于SDCC c編譯器開(kāi)發(fā)微控制器。如果你對(duì)c編譯器的應(yīng)用同樣存在興趣,不妨繼續(xù)往下閱讀哦。
簡(jiǎn)介
SDCC (小型設(shè)備C編譯器)是為8位微控制器開(kāi)發(fā)的免費(fèi)C編譯器。盡管兼容多種不同體系結(jié)構(gòu),但SDCC C編譯器更適合8051內(nèi)核。本應(yīng)用筆記主要介紹采用SDCC來(lái)開(kāi)發(fā)Maxim/Dallas Semiconductor的DS89C430/450系列超高速8051兼容微控制器固件。
SDCC是命令行固件開(kāi)發(fā)工具,含預(yù)處理器、編譯器、匯編器、鏈接器和優(yōu)化器。安裝文件中還捆綁了SDCDB、類似于gdb (GNU調(diào)試器)的源碼級(jí)調(diào)試器。無(wú)錯(cuò)的程序采用SDCC編譯、鏈接后,生成一個(gè)Intel十六進(jìn)制格式的加載模塊。之后可采用串行加載器將該文件加載至DS89C430/450微控制器閃存。(參見(jiàn)DS89C430/450文檔和應(yīng)用筆記,了解固件下載至器件的詳細(xì)信息。)
關(guān)于SDCC的最新信息,請(qǐng)?jiān)L問(wèn)http://sdcc.sourceforge.net,或者閱讀SDCC手冊(cè)sdccman.pdf (在安裝過(guò)程中復(fù)制到您的硬盤上)。也可以將問(wèn)題提交給SDCC在線消息論壇,或發(fā)郵件至SDCC網(wǎng)頁(yè)“Support”列出的郵件地址。
安裝SDCC免費(fèi)C編譯器
如果需要安裝SDCC,請(qǐng)從官網(wǎng)下載SDCC最新版本。雖然也可使用該軟件的日常構(gòu)建(nightly builds)版,但通常最安全的方式是下載經(jīng)過(guò)完全測(cè)試的最新發(fā)布版。
在“Download”頁(yè)為不同的操作系統(tǒng)提供不同的SDCC。如果您使用運(yùn)行Microsoft Windows的PC,請(qǐng)下載并運(yùn)行win32自解壓SDCC安裝文件。
安裝程序時(shí)會(huì)出現(xiàn)一個(gè)提示,詢問(wèn)是否將含有程序二進(jìn)制文件的目錄添加到您的路徑中。建議同意添加,本應(yīng)用筆記假設(shè)用戶路徑中已添加該目錄。
采用SDCC編譯器編譯一個(gè)簡(jiǎn)單的C程序
為確保SDCC已在您的硬盤上正確安裝,請(qǐng)?jiān)诿钐崾痉骆I入sdcc --version,然后回車,窗口中應(yīng)出現(xiàn)圖1所示文本(實(shí)際文本與您下載的SDCC版本有關(guān)):
圖1. 通過(guò)版本檢查確認(rèn)SDCC是否正確安裝
為測(cè)試包含路徑,生成名為sdcctest.c的文件,并將以下源代碼復(fù)制到該文件中。
以普通ASCII格式(如使用Microsoft記事本程序)保存該文件。在命令提示符下,鍵入sdcc sdcctest.c,然后回車。如像圖2那樣沒(méi)有任何反應(yīng),則說(shuō)明程序編譯成功。
圖2. 編譯簡(jiǎn)單的SDCC程序
當(dāng)源代碼編譯成功時(shí),SDCC會(huì)生成多個(gè)文件。在編譯目錄中可找到以下文件:
sdcctest.asm:程序的匯編文件
sdcctest.lst:程序的列表文件
sdcctest.rst:被鏈接器更新的列表文件
sdcctest.map:被鏈接器更新的最終存儲(chǔ)器映射
sdcctest.ihx:Intel十六進(jìn)制格式的加載模塊。該文件必須被下載到微控制器中。
同時(shí)還生成其它文件(多數(shù)用于源碼級(jí)調(diào)試器)。請(qǐng)閱讀SDCC文檔了解更詳細(xì)的信息。
SDCC專有數(shù)據(jù)類型
SDCC支持多數(shù)ANSI-C數(shù)據(jù)類型。此外,SDCC支持多種擴(kuò)展數(shù)據(jù)類型(也稱為存儲(chǔ)類型),以充分利用8051體系結(jié)構(gòu)的優(yōu)勢(shì),這將在后面以實(shí)例說(shuō)明。
與一些商用8051微控制器開(kāi)發(fā)工具不同,SDCC僅支持聲明位和字節(jié)可尋址特殊功能寄存器。盡管8051匯編語(yǔ)言支持,但SDCC并不支持共享位和字節(jié)可尋址RAM。為證實(shí)這一點(diǎn),請(qǐng)觀察以下代碼實(shí)例和編譯完的匯編代碼。
C源程序:
盡管在聲明中“a”看起來(lái)是位尋址存儲(chǔ)器,但匯編列表文件(來(lái)自由SDCC生成的.rst文件)表明變量并沒(méi)有使用位尋址。在列表中不要混淆“a”和“_a”。“a”指累加器,而“_a”指變量。
注意,本應(yīng)用筆記在“絕對(duì)尋址”一節(jié)介紹了一種可真正實(shí)現(xiàn)存儲(chǔ)器位尋址的方法。
near/data
以near或data存儲(chǔ)類型聲明的變量將被放在8051內(nèi)核的直接尋址RAM中。DS89C430/450系列微控制器具有128字節(jié)直接尋址存儲(chǔ)器,這是8051能夠訪問(wèn)的速度最快的存儲(chǔ)器,生成的匯編代碼只需一個(gè)MOV指令即可讀寫該RAM中的數(shù)據(jù)。
far/xdata
以far或xdata存儲(chǔ)類型聲明的變量將被放在外部RAM中。這樣開(kāi)發(fā)人員能夠訪問(wèn)更大的RAM空間,但生成的匯編代碼需要使用MOVX指令來(lái)讀寫該存儲(chǔ)器,這要求將外部存儲(chǔ)器地址裝入數(shù)據(jù)指針。
DS89C430/450系列微控制器含有1K字節(jié)的內(nèi)部SRAM,可被用于以far/xdata聲明的變量。注意,電源管理寄存器(PMR)中的DME1:0位在該存儲(chǔ)器初始化或使用之前,必須先被置為內(nèi)部SRAM模式。
idata
以idata存儲(chǔ)類型聲明的變量將被放在8051內(nèi)核的間接尋址存儲(chǔ)器中。間接可尋址存儲(chǔ)器與直接尋址存儲(chǔ)器類似,在8051內(nèi)核中共有128字節(jié)(不包括特殊功能寄存器)。但是,訪問(wèn)idata需要額外的MOV命令將RAM地址移至工作寄存器中。
pdata
存儲(chǔ)類型pdata用于訪問(wèn)分頁(yè)的外部數(shù)據(jù)存儲(chǔ)器。該存儲(chǔ)類型超出了本應(yīng)用筆記范疇,有興趣的讀者可以閱讀SDCC文檔的pdata部分。
code
以code存儲(chǔ)類型聲明的變量將被放在程序存儲(chǔ)器(DS89C430/450微控制器內(nèi)部的閃存)中。對(duì)于SDCC來(lái)說(shuō),這類變量只讀,因此常使用code來(lái)聲明常量(如:查找表)。
bit
以bit存儲(chǔ)類型聲明的變量被放在8051內(nèi)核的位尋址存儲(chǔ)器中。8051內(nèi)核的16字節(jié)直接尋址RAM可用作位尋址存儲(chǔ)器(字節(jié)0x20至0x2F),提供128個(gè)可尋址位。使用該類變量作為標(biāo)志位可高效利用存儲(chǔ)空間。
sfr
存儲(chǔ)類型sfr被用來(lái)定義8051內(nèi)核專有的特殊功能寄存器(SFR)。附錄A定義文件中使用sfr標(biāo)識(shí)符定義了DS89C430/450微控制器中的所有SFR。
注意,下面的實(shí)例已定義了SFR,因此沒(méi)有必要包含定義文件sdcc_reg420.h。
sbit
存儲(chǔ)類型sbit用于定義可位尋址SFR中的特殊位。在8051內(nèi)核中,地址以0或者8 (十六進(jìn)制)結(jié)束的所有SFR均可位尋址。附錄A定義文件中使用sbit標(biāo)識(shí)符定義了DS89C430/450微控制器SFR的所有可尋址位。
絕對(duì)尋址
SDCC支持采用at標(biāo)識(shí)符的絕對(duì)尋址。但是,SDCC不跟蹤聲明的絕對(duì)尋址變量,而且可能在其地址聲明其它變量,造成相互覆蓋。
以下程序顯示了有趣的潛在錯(cuò)誤。
使用SDCC時(shí),盡管變量"y"和"z"分配同一個(gè)位置,也可進(jìn)行無(wú)錯(cuò)誤或警告的編譯。如果要運(yùn)行該程序,我們認(rèn)為程序(a = c[5])中"a"最終將被設(shè)置為0xAA。但情況并非如此。"a"最終被分配的值為0xF2。
絕對(duì)尋址可用于仿真位尋址變量。在下面的例子中,在位尋址存儲(chǔ)器的最后一個(gè)字節(jié)處定義變量n_byte。然后,在8051內(nèi)核位尋址存儲(chǔ)器的最后8位定義n_bit0至n_bit7。由于這種重疊,可采用變量n_bit0至n_bit7對(duì)變量n_byte進(jìn)行位尋址。
存儲(chǔ)器模式
SDCC支持兩種存儲(chǔ)器模式:小模式和大模式。使用存儲(chǔ)器小模式時(shí),SDCC在內(nèi)部RAM中聲明所有不帶存儲(chǔ)類型的變量(如,data、idata、xdata、pdata、bit、code)。使用存儲(chǔ)器大模式時(shí),SDCC在外部RAM中聲明所有不帶存儲(chǔ)類型的變量。
采用SDCC編譯時(shí),默認(rèn)為小模式。如果要強(qiáng)制SDCC使用特定的存儲(chǔ)器模式,可使用以下命令行參數(shù):
sdcc --model-small sdcctest.c
或者
sdcc --model-large sdcctest.c
不要鏈接使用不同存儲(chǔ)器模式編譯的模塊或目標(biāo)文件。
SDCC的中斷
定義中斷服務(wù)程序(ISR)時(shí),應(yīng)使用以下格式:
其中interrupt_idenTIfier可以是任意有效的SDCC函數(shù)名,interrupt_number代表中斷在中斷向量表中的位置。表1列出了DS89C430/450系列微控制器支持的每個(gè)中斷的中斷號(hào)??蛇x參數(shù)bank_number用于指示SDCC采用哪個(gè)寄存器區(qū)存儲(chǔ)ISR中的局部變量。
表1. DS89C430/450中斷服務(wù)程序的中斷號(hào)
SDCC處理與ISR編程相關(guān)的許多細(xì)節(jié),如使用堆棧保存和恢復(fù)累加器及數(shù)據(jù)指針。(實(shí)際上所有函數(shù)均進(jìn)行此操作。請(qǐng)參考SDCC手冊(cè)中的_naked關(guān)鍵字來(lái)禁止在堆棧中保存這些變量)。其它細(xì)節(jié)不由SDCC處理(因?yàn)楹侠淼脑?,這對(duì)嵌入式編程開(kāi)發(fā)新手帶來(lái)一定難度。許多這類問(wèn)題屬于高級(jí)編程范疇,已超出本文討論的范圍,SDCC手冊(cè)和嵌入式編程教材可提供更深入的內(nèi)容。
使用中斷時(shí),應(yīng)遵循以下原則。
可在ISR內(nèi)部寫、并可在ISR外部訪問(wèn)的每個(gè)全局變量必須被聲明為volatile,以確保優(yōu)化器不會(huì)刪除與該變量相關(guān)的指令。
以非原子(non-atomic)方式使用數(shù)據(jù)時(shí)(如,訪問(wèn)16位/32位變量)應(yīng)禁止中斷。當(dāng)對(duì)變量的訪問(wèn)為原子方式時(shí),處理器無(wú)法中斷(帶有ISR)對(duì)存儲(chǔ)器的數(shù)據(jù)存取。
避免在ISR內(nèi)部調(diào)用函數(shù)。如果必須這樣做,需要將函數(shù)聲明為reentrant (參見(jiàn)SDCC手冊(cè)),這樣函數(shù)中的所有局部變量被分配在堆棧中,而不是在RAM中。
注意,如果被SDCC使用的含ISR的源文件不含main()函數(shù),那么含main()函數(shù)的源文件應(yīng)包含每個(gè)ISR的函數(shù)原型。
下面的例子定義了一個(gè)處理串行通信接口1 (SCI_1)的中斷服務(wù)程序(ISR)。程序接收來(lái)自SCI_1接收器的一個(gè)字節(jié),將接收字節(jié)加1,通過(guò)SCI_1發(fā)射器連續(xù)發(fā)送出去。
內(nèi)嵌匯編
SDCC完全支持內(nèi)嵌匯編。使用該功能時(shí),匯編代碼應(yīng)嵌在_asm和_endasm標(biāo)識(shí)符之間。注意,通過(guò)在變量名前加下劃線,內(nèi)嵌匯編代碼也可以訪問(wèn)C變量。以下實(shí)例采用內(nèi)嵌匯編執(zhí)行nop指令(用于在微控制器內(nèi)部占用一個(gè)時(shí)鐘周期),然后將變量"a"加1。
SDCC還可用于C和匯編函數(shù)接口,這是較深入的問(wèn)題。
以上便是此次小編帶來(lái)的“c編譯器”相關(guān)內(nèi)容,希望大家對(duì)本文講解的內(nèi)容具備一定的認(rèn)知。如果你喜歡本文,不妨持續(xù)關(guān)注我們網(wǎng)站哦,小編將于后期帶來(lái)更多精彩內(nèi)容。最后,十分感謝大家的閱讀,have a nice day!