




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
基于koilc的8051單片機嵌入式開發(fā)
1c語言生成模塊8151納米針系列是八本最著名的機系列之一。近幾年,隨著8051系列單片機版權的開放,在8051系列上的應用開發(fā)不斷增加,而且應用規(guī)模比以往大,可執(zhí)行代碼往往上幾百KB。這對于現在32位的PC平臺來說只是小菜一碟,而對于8位的單片機來說,已經算是大規(guī)模的開發(fā)了。這種大型的嵌入式開發(fā)不可能完全用匯編語言或C語言來完成。C語言便于模塊化的編程風格、優(yōu)良的可讀性、良好的可移植性和調試方便性更是這種大型程序開發(fā)的項目維護管理所需要的。另外,C51經過多年的發(fā)展,已經具有很多優(yōu)秀的集成開發(fā)工具,KeilC就是其中之一,這些集成開發(fā)工具為程序開發(fā)調試提供了良好的人機接口。因此,C語言廣泛應用在這類大型的嵌入式程序中,通常占95%以上的代碼量。由于C51是8051單片機的C語言編譯器,與ANSI-C編譯器有不同的地方,具有很多8051單片機的特點。280c語言代碼設計8051系列單片機有多種存儲器類型:外部程序存儲器、內部程序存儲器、外部數據存儲器、內部數據存儲器。在開發(fā)較大型程序的時候,因為內部程序存儲器和內部數據存儲器容量都比較小,通常會被分配給實現底層功能的匯編語言使用。C語言的代碼一般使用外部程序存儲器和外部數據存儲器。由于51系列單片機16位地址寄存器的限制,外部程序存儲器和外部數據存儲器的尋址范圍都是64KB。分組連接定位器BL51允許生成代碼長度大于64KB的8051目標程序,它可以管理一個公共區(qū)域(COMMONAREA)和最多32個代碼組區(qū)域(BANKAREA),每個代碼組最大為64KB。8051單片機本身不支持代碼組切換,切換要通過額外的地址線(片選信號)來完成。代碼組切換的軟件功能由文件L51_BANK.A51完成。每次組切換要花費50個機器周期和2個字節(jié)的堆??臻g,所以如果發(fā)生頻繁的組切換,會消耗CPU大量的時間。外部數據存儲器和外部程序存儲器包括公共區(qū)域和組區(qū)域就是我們最關心的部分。3存儲模式分類C51有三種存儲器模式,分別是SMALL、COMPACT和LARGE。存儲器模式決定默認情況下給變量分配的存儲器的類型。本文所討論的問題都設定在LARGE存儲器模式下,在這種模式下,變量缺省被定義在外部存儲器中。3.1外部程序存儲的靜態(tài)分配圖我們可以通過查看BL51連接器產生的m51文件來了解程序所使用的存儲器的情況。在m51文件中的LINKMAPOFMODULE部分,可以看到其中XDATAMEMORY段是外部數據存儲器的靜態(tài)分配圖,CODEMEMORY段是外部程序存儲器公共區(qū)域的連接分配圖,緊跟在后面的是CODEBANKx段就是各個組代碼的連接分配圖。在這些段里,我們可以看到類型、開始地址、長度和段名等的信息。段名的前綴?PR?、CO?和?XD?是最常見的,分別代表程序執(zhí)行代碼、程序代碼中的常量和放在外部存儲器的數據變量。而段的后綴一般就是大寫的C文件名的前綴。3.2堆棧方式管理通常硬件設計時外部數據存儲器要比外部程序存儲器少得多,一般限制在64KB內,這是在一般的PC平臺開發(fā)中很少遇到的。根據應用的不同,我們可以采用包括算法、程序設計方法和技巧等方面的各種內存受限的開發(fā)方法,不能一一盡述。這里將講述C51在存儲管理方式上不同于ANSI-C的特殊的地方。首先以下面的例子來了解C51是如何給不同類型的變量分配存儲器的。為了產生短小和快速的代碼,C51缺省把函數看作不可重入的,不使用堆棧來管理函數。對上面例子中的所有變量,包括函數fun1里面的a,b和函數fun2里面的a,b,C51都在外部數據存儲器里分配不同的空間。這是C51與ANSI-C不同的地方,也是相同的代碼在C51編譯器和ANSI-C編譯器上有不同行為的原因。C1這種缺省的不可重入函數處理方式一方面令那些利用堆棧的程序設計方法如遞歸函數出錯;另一方面它為函數中的自動變量分配不同的空間也浪費了大量寶貴的外部數據存儲器空間。對于大型的應用來說,我們更趨向使用與ANSI-C一致的堆棧方式。這時候,我們可以使用C51的特殊保留字reentrance把函數聲明為可再入函數,C51編譯器使用堆棧方式來管理可再入函數的變量。在上面例子中應用reentrance后代碼的如下:現在,編譯器只為全局變量g、fun1里面的靜態(tài)變量sa和fun1里面的靜態(tài)變量sa在XDATA分配不同的空間。而對于fun1和fun2的參數變量b和自動變量a,則使用在XDATA中的模擬堆??臻g,在程序運行時才自動分配。這樣,我們就節(jié)省了大量的自動變量的空間。要注意的是,中斷函數不可以使用reentrance。另外,上面例子不直接使用保留字reentrance是為了方便在非C51下試調代碼,在非C51的編譯環(huán)境下,我們只要把例子中的首行改為#defineCOMPILER_REENTRANCE就可以避免非C51編譯器不認識C51的特殊保留字reentrance的錯誤了。3.3公共區(qū)域ct的生成外部程序存儲器放置連接器產生的公共區(qū)域代碼和組代碼。公共區(qū)域中的代碼可以在任何時候由所有代碼組使用。這些代碼包括:復位和中斷向量、常數、C51中斷函數、組切換跳轉表和庫函數。其實,公共區(qū)域與每個組的代碼共享64KB的尋址空間,連接器缺省把公共區(qū)域放在64KB空間的低端,如圖1所示。而且公共區(qū)域在每個64KB中的起始地址和內容完全一樣,所以叫做公共區(qū)域。這樣,實際上,程序代碼可用的最大空間=組數目×64KB-(組數目-1)×公共區(qū)域大小??梢?為了獲取更多的代碼空間,就要盡可能減少公共區(qū)域的大小。分析公共區(qū)域的代碼后,可以從三個方面減少代碼。1用一個中斷函數C51編寫的中斷函數必需放在公共區(qū)域里,但是在中斷函數里面可以調用任何組的函數。我們可以利用中斷函數的這個特性,把中斷函數寫成只有一個函數調用的外殼函數的形式,把實際工作交給組代碼里的函數完成。這個方法可以減少中斷函數的大小,但是必須考慮組切換的時間(50個機器周期)是否滿足中斷函數處理時間的要求。2減少庫函數的大小因為庫函數的調用有時需要采用一些特殊的調用方式,這些方式有時會受到組間切換的影響,所以連接程序BL51總是庫函數段放置在公共區(qū)域,程序員也無法重新定位庫函數段到其他地方。要減少庫函數段的大小,就要減少使用的庫函數的數目。我們需要了解某個庫函數在哪些組里被調用,還有被調用的次數。我們應該盡量把被多個組調用,而且被調用頻率最高的庫函數保留在公共區(qū)域;考慮重寫那些只是在單個組里被調用或使用頻率很低的庫函數。通過重寫這些庫函數,我們可以根據自己要求去裁剪原來庫函數的功能,使得執(zhí)行代碼更小。另外,我們還可以自由擺放重寫后函數的位置,一般是放在發(fā)生調用的那一組里,以減少公共區(qū)域的大小。3調整傳輸字符缺省情況下,程序中的所有字符串常量會被安排在公共區(qū)域里。這種安排的好處是程序員可以像ANSI-C的習慣一樣放心地傳遞字符串常量的指針來調用函數,不需要擔心C51特殊的跨組調用問題。因為每個64KB的代碼組都有公共區(qū)域的代碼,而且定位地址是一致的。但是在大型開發(fā),特別是涉及人機用戶界面相關的開發(fā)中,程序中會存在大量的字符串常量,如果按照以上的缺省配置方式來存放,這些字符串將占用大量的公共區(qū)域空間。為了減少公共區(qū)域中字符串常量的大小,我們可以調整的BL51設定,把常量放在指定的組,而不放在公共區(qū)域里面。例如,我們要把文件file1.c中的常量放在組1,在KeilC集成開發(fā)環(huán)境下,選擇Project菜單下Optionsfortarget,然后在BL51Misc頁下的Misccontrols中,把file1.c的常量段?CO?FILE1加到BANK1()的括號中。在把常量放在獨立的組以后,我們就必須考慮跨組調用的問題。3.4組切換時的pstC51的指針不帶有代碼組的信息,不能辨識是指向哪個代碼組的,在發(fā)生代碼組切換的時候,這些指針就會出現問題。如以下的例子:如圖2所示,假設函數fun1(void)在組1,display(char*pstr)函數在組0,并根據上面所述的方法把字符串常量放置在組1,連接器分配給常量“中文”的起始地址是1000H。在程序運行的時候,程序把常量“中文”的起始地址1000H壓入堆棧,調用display,因為display在組0,所以程序發(fā)生組切換,由當前組1切換到組0,在display函數里面,程序讀出剛剛壓入的地址信息1000H并賦予pstr,這時候pstr指向的地址是組0的1000H地址,而不是組1的1000H,所以display顯示的結果是不正確的。為了解決常量字符串指針的跨組調用的問題,我們先把常量字符串拷貝到外部數據存儲器,然后傳遞指向外部數據存儲器字符串的指針給需要切換組調用的函數。如圖2所示。使用這個方法后上例的代碼修改如下:另外,其他指向代碼組的指針,如指向函數的指針都存在同樣的問題。不過函數指針使用得比較少,一般可以通過調整函數所在的代碼組來解決。此外,出于提高性能和減少錯誤的考慮,我們通常希望組切換盡量少發(fā)生,這就涉及到如何把組代碼分配到64KB-公共區(qū)域代碼大小的若干個組里去了。這時候我們采用軟件工程的方法,把軟件按功能劃分為模塊,較大的模塊劃分為更小的子模塊。然后分析各個模塊、子模塊間的耦合度,把耦合最大的模塊盡量放在同一個組里。這屬于靜態(tài)分析的方法。另外,我們還可以對程序進行動態(tài)分析,把軟件運行時經常執(zhí)行的代碼放在同一個組里面。經過這樣劃分和整理以后,一方面使得軟件架構條理清晰,一方面減少了跨組調用的情況。3.5動態(tài)內存池的自適應內容分配對于大型應用來說,在很多情況下都會用到C語言的動態(tài)內存分配庫函數。因為C51是為資源相對寶貴的單片機而設的,所以C51動態(tài)內存分配函數的使用也與一般的C語言有所不同。首先,考慮到單片機硬件和應用的獨特性,C51的動態(tài)內存分配函數不單以函數庫的形式提供的,同時還提供源程序。源代碼分別在KeilC安裝路徑下的\C51\Lib目錄下的init_mem.c、malloc.c、alloc.c、realloc.c和free.c文件里。用戶可以根據自己的需要編寫自己的內存分配函數來替換這些庫函數。當然,用戶也可以把這些文件拷貝出來加入自己的工程中,以減少公共區(qū)域的大小。其次,在使用C51的所有動態(tài)內存管理函數(malloc,alloc,realloc,free,)前,必須先初始化動態(tài)內存池,其函數原型是:voidinit_mempool(voidxdata*p,unsignedintsize);其中p是動態(tài)內存池的開始地址,size是動態(tài)內存池的大小。函數的功能是從外部數據存儲器里面劃出一塊內存建立動態(tài)內存池,并交由動態(tài)內存分配函數管理,程序員必須保證動態(tài)內存池不會與其他的內存區(qū)域相互覆蓋,相互改寫內容。實際應用中的問題是如何確定動態(tài)內存池的位置。我們提供以下兩個方法方法一:把動態(tài)內存池建立在變量分配堆棧的上部,與堆棧共用同一空間,如圖3所示。先任意填寫init_mempool()函數調用中的內存池開始地址或填寫地址0X0000,在編譯連接通過后,利用連接器生成的m51文件分析外部數據存儲器的使用情況,確定C51變量分配堆棧的頂端地址,也就是外部數據存儲器的最后空閑區(qū)域的開始地址。然后把init_mempool()的開始地址改為堆棧的頂端地址。最后再重新編譯連接一次。這個方法的一個弊端是,隨著程序的修改增減,變量分配堆棧的頂端會發(fā)生改變,所以每次程序的更改,都要重復以上的步驟。方法二:如果只是模塊A需要使用動態(tài)內存分配,那么動態(tài)內存池可以與其他不和模塊A同時運作的模塊來共享一部分內存。例如,模塊A需要5KB的內存池用作動態(tài)分配,而模塊B要用到3個2KB的緩沖區(qū)。我們可以依照如下代碼來定義模塊B緩沖區(qū)和初始化內存池。其示意圖如圖4所示:4參數返回值和貯存前閥值的傳遞關系在單片機開發(fā)中,底層的硬件中斷和驅動等的例程往往用匯編語言來實現。在大型的嵌入式開發(fā)中,C語言代碼調用底層的匯編語言代碼。要解決C語言與匯編語言之間的調用,最重要的是了解它們之間的函數名的命名規(guī)則和函數參數傳遞規(guī)則和返回值傳遞規(guī)則。C51程序模塊編譯成目標文件后,其中的函數名依據其定義的性質不同會轉換為不同的函數名。對于不傳遞參數或參數不通過寄存器傳遞的函數,其函數名不改變。voidfunc(void)轉變后函數名為FUNC。對于參數通過寄存器傳遞的函數,轉變后函數名在原來的名字前加′_′。voidfunc(intt)轉變后函數名為_FUNC。函數參數傳遞和寄存器的對應關系,一般按參數從左到右的順序填寫寄存器R7到R0。char類型占1byte,先填R7,第二個char類型填R5。int類型占2bytes,按高低位先填R6、R7,第二個int類型填R4、R5。float和double類型占4bytes,按高低位填R4、R5、R6、R7。一般指針占3bytes,存儲器類型在R3,高位在R2,低位在R1。函數返回值和寄存器之間的對應關系與參數傳遞的對應關系差不多。以函數charVoiceOperation(charmode,intid,char*str)為例,R7存放char類型參數mode,R4、R5存放int類型參數id,R1、R2、R3存放char*類型參數str,函數的返回值存放在R7。根據上面的參數和返回值傳遞規(guī)則,用匯編編寫函數_VoiceOperation。在C語言中聲明函數VoiceOperation為外部函數,然后就可以在C語言中調用匯編語言實現的VoiceOperation。5調試模塊的實現調試是軟件開
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 三年級思品與社會上冊 友愛殘疾人教學設計2 北師大版
- 一年級數學上冊 八 10以內的加法和減法第4課時 得數是6、7的加法教學設計 蘇教版
- 七年級語文下冊 第三單元 10 老王教學設計 新人教版
- 第7課 小小音樂家《星光圓舞曲》(教學設計)-2023-2024學年人音版(2012)音樂一年級上冊001
- 人教版地理七年級上冊 第1章 地球和地圖第1節(jié) 地球和地球儀 第2課時 地球的模型-地球儀教案
- 8 人之初教案-2024-2025學年統編版(2024)語文一年級下冊001
- 長者保護安全培訓
- 靜物組合寫生課件
- 10竹節(jié)人教學設計-2024-2025學年六年級上冊語文統編版001
- 七年級歷史上冊 第四單元 三國兩晉南北朝時期:政權分立與民族交融第19課 北魏政治和北方民族大交融教學設計 新人教版
- 2025年初級會計師考試的練習題解答試題及答案
- 2025智聯招聘行測題庫及答案解析
- 湖南新高考教學教研聯盟暨長郡二十校聯盟2025屆高三年級第二次聯考地理試題及答案
- 博翠芙蓉湖5#-9#施工組織總設計
- GB/Z 15166.8-2025高壓交流熔斷器第8部分:應用導則
- 貴州國企招聘2025六盤水市公共交通有限公司招聘合同制駕駛員30人筆試參考題庫附帶答案詳解
- 預防毒品教育主題班會教案
- 2025年《職業(yè)病防治法》宣傳周知識考試題庫300題(含答案)
- 貴陽語文初一試題及答案
- 機器人舞蹈表演行業(yè)深度調研及發(fā)展戰(zhàn)略咨詢報告
- 2025年北京市朝陽區(qū)高三一模地理試卷(含答案)
評論
0/150
提交評論