飛思卡爾軟件應用與C語言編程要點_第1頁
飛思卡爾軟件應用與C語言編程要點_第2頁
飛思卡爾軟件應用與C語言編程要點_第3頁
飛思卡爾軟件應用與C語言編程要點_第4頁
飛思卡爾軟件應用與C語言編程要點_第5頁
已閱讀5頁,還剩38頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1.CodeWarrior中建立新項目運行CodeWarrior(CW集成開發平臺,如圖1-1所示在File菜單下點擊New,彈出建立新項目的模板對話框,見圖1-2。一般的簡便做法是在圖1-2對話框左面的選擇列表中選擇“HC(S08 New Project Wizard”,然后在右面的項目名“Project Name”輸入條中,輸入你要建立的新項目名字,再在“Location”一欄中用 確定項目存放的文件夾路經,完成后按“OK”進入下一步。你也可以在圖1-2對話框左側列表中選擇“Empty Project”,這樣生成的項目不包含任何文件,你必須在CodeWarrior中自己添加所有相關的文件內

2、容。我想除非有特殊理由,實際項目開發過程中很少采用這種麻煩的方式來建立自己的項目。接下去是選擇項目開發所用的編程語言,見圖1-3。最常用的當然是C語言編程。有時因具體項目要求,除了C編程外還需要編寫獨立的匯編語言模塊,那就再加選匯編工具(Assembly。C+編程在免費版和標準版CW下都不支持,只有在專業版下才可以使用。編程語言選擇完畢后按“Next”。 圖1-1 圖1-2圖1-3223206fde0a 2c12a0c020 3bc286cf189數字簽名人223206fde0a2c12a0c0203bc286cf189 DN:cn=223206fde0a2c12a0c0203bc286cf

3、189,o=A Corporation,ou=CA Center,title=m-alipay原因:我是該文檔的作者日期:2012.08.29 13:40:13 +0800 這時將出現如圖1-4的對話框,讓你選擇項目開發對應的MCU 型號。在CW5.x 版本下支持幾乎所有的HC08和大部分HCS08單片機型號。在最新的CW6.x 中,增加了飛思卡爾最低端的8位機(RS08系列和低端32位處理器(Coldfire V1系列的支持,但HC08系列的有些型號沒有被包含在內。由于HC08為比較老的產品系列,已經不推薦在新項目設計中選用,因此影響不會太大。對于新用戶來說,請盡量直接安裝CW6.x 或以后

4、推出的更新版本。以典型的9S08系列為例,當你選擇了一個MCU 型號后,在圖1-4右側會顯示出所有針對該型號芯片可用的項目調試場景。其中: “Full Chip Simulator ”是芯片全功能模擬仿真,即無需任何目標系統的硬件資源,直接在你的PC 機上模擬運行單片機的程序,在模擬運行過程中可以觀察調試程序的各項控制和運行流程,分析代碼運行的時間,觀察各種變量,等等。CW 提供了功能強大的模擬激勵功能,可以在模擬運行時模擬一些外部事件的輸入,配合程序調試; “P&E Multilink/Cyclone Pro ”是基于P&E 公司的硬件調試工具實現實時在線硬件調試。實際就是我們經常說的BDM

5、 調試。BDM 調試是基于芯片本身內含的在線調試功能,可實現程序下載,單步/全速運行,可以設若干個斷點,可以觀察和修改任意寄存器或RAM 內存空間。BDM 幾乎是開發飛思卡爾8位(9S08和RS08系列、16位(9S12系列和32位(Coldfire V1系列單片機的標準調試模式,運用最為廣泛; “SofTec HCS08”是另外一家SofTec 公司提供的硬件調試工具,國內使用較少; “HCS08 Serial Monitor ”是基于芯片串口的監控調試開發模式。由于開發效率較低,現在幾乎無人使用。注意不同系列,不同型號的芯片,或不同版本的CW ,其所對應或支持的開發場景可能不同,在圖1-4

6、的項目建立模板中都可以顯現出來。用戶點擊選擇某一項場景后,該場景將在項目建立完成后作為首選配置。你可以在稍后調試過程中隨意切換開發場景,不必太在意在這里的選擇。到此你如果按“Finish ”,整個項目建立過程將完成,剩下的一些項目設定將自動用缺省配置。如果你要自己選擇調整,則按“Next ”進入下一步,往項目中添加現成的文件,見圖1-5。圖1-4 如果你以前編寫了很多代碼文件現在想重復利用,那么可以通過圖1-5對話框左面的文件樹選擇對應的文件,按中間的“Add ”逐個添加到右側的“Project Files ”列表中。若加錯了就用“Remove ”把列表中的文件移除。注意此列表下方的兩個選項:

7、“Copy files to project ”選擇是否將所選的文件拷貝到現在的項目文件夾中。如果你準備在新的項目中修改這些文件,就選擇拷貝,以免把原始的文件改變后而影響先前的一些項目;“Create main.c/main.asm file ”選擇是否在本項目中生成全新的main.c 或main.asm 文件,一般的項目開發都需要生成新的main 文件。按用戶自己的要求和目的自由選取。建議大家保留默認的選擇狀態。如果沒有什么現成的文件需要加入,就直接按“Next ”進入下一步,選擇處理器專家(Processor Expert 或簡稱PE 。 PE 是CW 集成開發平臺內帶的可實現芯片內部各種

8、資源模塊配置并自動生成相關代碼的一個軟件工具。不過只有專業版的CW 才支持該功能。通過PE ,用戶可以快速實現芯片初始化代碼的自動生成工作,而且PE 還提供了大量的軟件庫可供用戶開發時嵌入或調用。因為8位單片機結構和功能相對簡單,實現的控制項目復雜度也不是很高,故一般情況下8位機開發我們都不需要PE 的介入,自己直接編寫程序代碼即可。關于PE 的詳細介紹將耗費大量的文字,這里按下不提。所以在圖1-6的對話框中選擇“None ”,并直接按“Next ”進入下一步。 這是項目建立模板的最后一步。在這一步你可以決定有關C/C+的一些編譯和代碼生成模式,見圖1-7。啟動代碼選擇。所有C 編譯器會自動生

9、成一些啟動代碼。單片機復位后的指令運行將首先執行這些啟動代碼,然后再進入到你自己的程序模塊main 函數。這些啟動代碼主要完成堆棧指針初始化、全局和靜態變量自動清零圖1-5圖1-6圖1-7或賦初值、調用main 函數等。ANSI 標準初始化“ANSI startup code ”即完成上述工作,是項目開發的標準選擇;最小初始化“Minimal startup code ”除了初始化堆棧指針外就直接調用main 函數,代碼最少,進入main 函數最快,但變量的清零和賦初值必須由用戶自己編寫代碼實現。在這里請大家特別注意,即最小初始化將不會對全局或靜態變量自動清零,這一點在單片機編程中有時非常重要

10、。在實際產品中當單片機出現異常復位程序重新開始運行時,我們往往希望原先的控制過程得以延續,因此一些關鍵變量的內容要在復位后保留而不能不分青紅皂白地一概清零。選擇最小初始化代碼可以實現這一特殊要求,但還有更合理更高級的方法,將在后面介紹prm 文件時詳細說明。 編譯內存模式選擇。“Tiny ”模式是指所有程序不超過64KB ,RAM 變量不超過內存地址最前面的256字節(有時也被稱作第0頁;“Small ”模式程序空間一樣不超過64KB ,但RAM 不限于第0頁,可以覆蓋整個64K 地址空間。如果你選擇的芯片有超過第0頁空間的RAM 并想在設計中充分利用,就應該選擇該缺省的“Small ”模式。

11、 浮點運算庫選擇。當你的程序設計決定用浮點運算時就應該選擇加入浮點運算庫。浮點運算庫有兩種:一是標準浮點float 和雙精度浮點double 都用32位精度表示,換句話說float 和double 都看成是float 。這樣做的目的是減少代碼量,提高運算速度;另一種是double 用64位精度表示,毋庸置疑其運算精度將增加,但代碼量也將增加,運算時間也會更長。用戶可以按實際計算需求酌情選取。如果設計中無需浮點運算,就選擇“None ”。 全部選擇完成并確認后,按“Finish ”,恭喜你:你的項目已經成功建立,可以開始編寫你自己的代碼,調試你的目標系統了。完成后的項目范例如圖1-8,其中: S

12、ources 欄目下包含所有你的原程序文件,可以是C ,也可以是asm ,或C+。你可以在此欄下點擊鼠標右鍵在彈出菜單中選擇“Add Files ”添加其他源程序文件; Includes 欄目下包含本項目所有被引用的頭文件。你可以自己編寫項目相關的頭文件并添加到本欄目下; Libs 欄目所包含的是本項目開發用到的代碼庫,可以是目標代碼型式或C 源程序型式; Project Setting 下放的全是項目的配置文件。Startup Code 下是剛才建項目時自動生成的啟動文件,你可以打開觀察具體的程序代碼,也可以在必要時自己添加或修改這些啟動代碼;Link Files 下的三個文件分別是:用于編

13、程器下載的代碼文件格式配置(bbl 文件、機器代碼連接定位用的內存說明和配置文件圖1-8(prm文件、生成的目標代碼在內存中的映射文件(map文件。其中prm 文件最為關鍵,將在稍后重點專門介紹。2.CodeWarrior中項目的基本管理和設定現在項目已經成功建立,應該可以開始編寫自己的代碼了。但在寫代碼之前,先了解一下CW中最基本的項目管理和設定的方法還是很有必要。在圖1-8中項目窗口的右上角有一些小圖標,這些圖標代表了項目開發管理的最基本功能: 該圖標可以即時改變目標單片機型號和開發調試場景。按下這一圖標,將彈出圖1-4所示的對話框,可以按照前面針對新項目建立模板的介紹,改變目標單片機的型

14、號,或設定不同的當前目標開發調試場景。對于調試場景的改變,也可以直接點擊當前場景右邊的下拉菜單按紐,直接用鼠標點擊選擇所需的新場景,如圖2-1; 該圖標完成項目配置選項設定。點擊該圖標會彈出一個對話框,里面所含的 內容非常 繁雜,這里只解釋幾 個日常使用時最常用的選項配置:1.最終目標代碼類型設定(Target Setting。在這里你可以選擇最終編譯連接生成的代碼直接用于單片機程序運行(Link for HC08,或將各個源代碼文件編譯連接生成一個庫文件(Libmaker for HC08。這些選擇可以通過圖2-2所示的下拉菜單選擇;圖2-1圖2-2圖2-32. C 編譯選項設定(Compl

15、ier for HC08,對話框內容如圖2-3。在這里你可以完成針對C 編譯器的所有配置設定。幾個選項按紐解釋如下:選擇配置編譯時產生的各種信息,其中包括普通一般信息 (Information 、告警信息(Warning 、錯誤信息(Error 和致命信息(Fatal 。出現一般或告警信息時編譯能順利完成,所以你可以有選擇地將某些你不希望太關注的信息屏蔽掉(Disable ;但如果有任何錯誤或致命信息出現,當前源程序的編譯將立即終止,你必須按給出的信息提示解決這些錯誤,然后才能繼續編譯。完成編譯過程中代碼生成的各類選項設定,所含內容也很多, 最需要關注的是優化欄“Optimization ”。

16、你可以按實際需要打開或關閉某些特定的優化選項,但我們一般通過下面介紹的“Smart Sliders ”做綜合的優化設定。顯示編譯器當前設定的各類變量的長度和符號特性(針對字符 和枚舉型變量,無特殊原因一般都不用對這些變量長度做任何修改。按常規,在滿足功能要求的前提下,變量長度盡可能短,字符型變量盡量選擇無符號型,以便提高代碼編譯效率和程序運行速度。可以非常方便地實現代碼優化 時的綜合考慮。你可以用上面介紹的 “Option ”對話框可以設定特定的優化選項,但用此“Smart Sliders ”對話框則可以針對不同的優化側重面由系統自動配置具體的優化選項。具體的對話框見圖2-4,你只需用鼠標拉動

17、各項的滑塊對其進行優化級別的設定:“Code Density ”針對生成代碼的長度進行優化,設定越高,生成的代碼長度越短,代碼越高效緊湊; “Execution Speed ”針對代碼運行速度進行優化,設定越高,代碼執行速度越快;“Debug Complexity ”針對調試復雜度進行優化,設定越高,生成的的調試信息越豐富,調試越方便;“Compilation Time ”針對編譯時間進行優化,設定越高,表明編譯過程所需時間越長(對應其他各項所做的優化程度越高;“Information Level ”針對編譯信息進行優化,設定越高,表明編譯過程中產生的各類信息越豐富。所有這些編譯優化項目都是相

18、互關聯的。你移動任意一項滑塊的位置,其他各項也會隨之自動發生變化。你自己必須有針對性地改變某一項或兩項的優化級別,從中作出平衡,無法將所有的優化級別都提到最高。最常用的優化側重面是代碼長度和代碼速度這兩項。圖2-43.連接器選項設定(Linker forHC08,對話框內容見圖2-5,值得一提的是其中對prm文件的選擇。通過項目模板建立的項目其中必含有本項目專用的一個prm文件。缺省設置是利用此prm文件進行內存分配和連接定位。但你也可以通過此對話框選擇使用其他prm文件。當你的項目用的是純匯編單一文件且為絕對定位的編程模式,則不能選擇任何prm文件,必須設定成“Absolute, Singl

19、e File Assembly Project”。 該圖標檢查項目文件是否被更新。當你在CW環境中編輯項目中的各個文件時,只要文件內容發生變化,項目列表窗內該文件的左側會出現此小圖標,表明此文件已經被更新,它們在代碼生成過程會被重新編譯。有時你會用其它你熟悉或喜歡的文本編輯器編輯修改項目中各類文件,當編輯完成文件被保存后,在CW環境下按一下這個圖標,所有被更新的文件在項目欄中都會得到顯現。如果文件左側沒有出現此小圖標,表明該文件最近沒有被修改過,代碼生成時可能不會對它進行重新編譯,以節約時間。在任何時候你都可以用鼠標點擊源文件左側該小圖標的位置以顯現此圖標(如果原本沒有顯現的話,讓編譯器在代碼

20、生成過程中無條件重新編譯此文件。 該圖標進行代碼生成(make,鼠標點擊該圖標后進行源程序的編譯和目標代碼的連接定位。如果編譯連接成功,最后將生成用于源程序符號調試的abs文件、用于芯片燒寫的s19文件、所有變量和函數模塊在內存中的映射map 文件。另外通過CW菜單“ProjectMake”或鍵盤快捷鍵“F7”也可以實現相同功能。 該圖標用于打開并進入代碼調試窗口。鼠標點擊該圖標后,如果你的項目文件中有最新更新,CW會自動調用make功能進行編譯和連接。然后將利用最新生成的abs文件,激活一個獨立的代碼調試窗口,進行源程序級的代碼調試。CW菜單“ProjectDebug”或鍵盤快捷鍵“F5”同

21、效。因為關系到以后調試程序的方便,在這里還要特別提到編譯過程中調試信息的打開和關閉控制 。圖2-5 圖2-6請注意圖2-6中的黑點,該黑點表明編譯此文件時將產生調試信息,如果沒有此黑點,生成的abs 文件中將沒有對應的源程序調試信息,你就無法在調試窗口中進行源代碼級調試,只能進行匯編代碼級調試。你可以用鼠標點擊此黑點位置打開或關閉調試信息。所以當你在編譯連接結束后發現L1923號信息“xxx.o has no DWARF debug info ”,請檢查對應的文件調試信息有沒有打開。現在,請你在所建立的項目中體會一下上面介紹的這些基本配置及其設定方法。最后按下圖標,看是否能進入調試窗口?應該沒

22、問題! 好了,該編寫你自己的代碼了。3. C 語言編程要點CW 中針對Freescale 的8位單片C 語言編程基本符合ANSI 規范,因此關于標準C 語言編程的話題就不再重復。這里主要介紹和單片機資源密切相關的一些編程要點。3.1 變量類型和定義CW 中08系列單片機C 編譯器支持的基本變量類型及其缺省的長度位數由表3.1所示。有些變量的長度可以按實際項目需要而改變,見對話框圖3-1。此對話框經由上面的圖2-3中“Type Size ”配置按紐打開。 表3.1中所示的整形數變量char 、short 、int 、long 等都有對應的無符號型式(前面冠以unsigned 。CW 給定的頭文件

23、已經將最常用的一些無符號變量類型做了類型表3.1圖3-1名簡化替換,例如用“byte”代替“unsigned char”,用“word”代替“unsigned int”。這樣在程序編寫是可以節約點敲鍵盤的時間。在單片機程序設計中對于變量類型的選擇確認有兩條最基本的原則須遵循:能用短的變量就不用長的;能用無符號數就不用有符號數。這兩條基本原則將在很大程度上決定你代碼的長度和效率。因此請多多使用byte或word類型變量。由于08系列單片機內部硬件寄存器定義的特點,對于多字節組成的變量,例如int、long等,C編譯器缺省的變量內存排列方式是“big endian”模式,即高位字節放在低地址,低位

24、字節放在高地址,又俗稱“大頭朝上”。這一點相比普通Intel格式,例如51系列和PIC系列正好相反,它們都是“little endian”模式,即“大頭朝下”,在程序跨平臺移植時請特別注意。當然CW編譯器本身可以設定改變成“little endian”模式,但單片機內部寄存器地址排列順序無法改變,故這樣做將使最終的程序代碼效率降低,特別是在存取一些16位長的寄存器組時,它們在硬件上都是由順序排列的兩個8位寄存器組成,高字節在前,低字節在后。單片機程序設計中經常會用到的位變量作為一些標志。CW中沒有特別的位變量定義關鍵詞,位變量必須由位域結構體的型式來定義。例如:struct unsigned

25、powerOn : 1;unsigned alarmOn : 1;unsigned commActive : 1;unsigned sysError : 1; myFlag;若引用某個位變量,只需myFlag.alarmOn = 1;myFlag.sysError = 0;這樣定義的各個位變量將被順序排放在一起,以字節為基本單位,字節的第0位放第一個位變量,一個字節含8個位變量。因此如果位域結構中定義的位變量數目很多,在最后內存分配上將占居多個字節。有時為了編程方便,位變量需單獨定義和操作但又希望一次整個字節一起初始化(清零或賦值,這時我們可以定義字節(或字和位域結構的聯合體: union b

26、yte flagByte;struct unsigned powerOn : 1;unsigned alarmOn : 1;unsigned commActive : 1;unsigned sysError : 1; bits; myFlag;整字節操作可以myFlag.flagByte = 0;單獨某一個位操作可以可以myFlag.bits.powerOn = 1;myFmActive = !myFmActive;若嫌這樣的位變量名稱太長,大可以在你自己的頭文件里用“#define”預定義,用更簡潔易懂的名稱進行替換。最后要提醒的是在定義位變量時盡量將它們指定分配到內存空間的第0頁(地址范圍

27、0x00-0xff,這樣對位變量操作的C代碼將直接被編譯成對應的匯編位操作指令,代碼效率最高。具體的定位方法將在介紹“#pragma”時說明。3.2變量的特殊修飾上面介紹的各類基本變量和由其合成的高級變量如數組、結構和聯合,將滿足95%以上的單片機程序設計工作。由于單片機資源的有限性和特殊型,還有一小部分因素需要在定義變量時加以考慮:3.2.1變量的絕對定位變量絕對定位是特別針對芯片內部的硬件寄存器定義的。所有的硬件寄存器在編寫C程序時均被視為變量,它們都已在CW給定的頭文件中預先定義。由于是硬件資源,其地址是唯一且不可改的,所以在頭文件中定義這些寄存器時都采用絕對定位的方式,如定義9S08A

28、W32的PORTA:/* PTAD - Port A Data Register; 0x00000000 */typedef union byte Byte;struct byte PTAD0 :1; /* Port A Data Register Bit 0 */byte PTAD1 :1; /* Port A Data Register Bit 1 */byte PTAD2 :1; /* Port A Data Register Bit 2 */byte PTAD3 :1; /* Port A Data Register Bit 3 */byte PTAD4 :1; /* Port A D

29、ata Register Bit 4 */byte PTAD5 :1; /* Port A Data Register Bit 5 */byte PTAD6 :1; /* Port A Data Register Bit 6 */byte PTAD7 :1; /* Port A Data Register Bit 7 */ Bits; PTADSTR;extern volatile PTADSTR _PTAD 0x00000000;#define PTAD _PTAD.Byte#define PTAD_PTAD0 _PTAD.Bits.PTAD0#define PTAD_PTAD1 _PTAD

30、.Bits.PTAD1#define PTAD_PTAD2 _PTAD.Bits.PTAD2#define PTAD_PTAD3 _PTAD.Bits.PTAD3#define PTAD_PTAD4 _PTAD.Bits.PTAD4#define PTAD_PTAD5 _PTAD.Bits.PTAD5#define PTAD_PTAD6 _PTAD.Bits.PTAD6#define PTAD_PTAD7 _PTAD.Bits.PTAD7在定義端口寄存器時用“”給出其絕對地址為0x00。理論上用戶自己定義的變量也可以用這種方式對其分配一個固定地址來絕對定位。但這樣定義的變量其地址不被保留,完全

31、可能被其他變量覆蓋。例如用絕對定位的方式定義一個變量k在地址0x70,同時還有其他變量定義,在最后連接定位后的內存映射文件中我們可以看到變量i和k的地址是重疊的。- VARIABLES:prjName 80B9 F 15 1 .rodatax1 80C8 4 4 1 .rodatai 70 1 1 3 MY_ZEROPAGEj 71 1 1 1 MY_ZEROPAGEk 70 1 1 0 .abs_section_70所以你可以采用上面介紹的方法來絕對定位你自己的變量,但千萬千萬慎用。我自己實在找不到合適的理由去絕對定位程序中的各類變量。3.2.2變量volatile聲明聲明方法:volati

32、le byte msCounter;volatile byte uartBuff16;volatile word adValue;“volatile”型變量顧名思義就是這些變量是易變的,其值是不隨你的程序代碼運行而隨意改變的。可見,基本所有的單片機片內硬件寄存器其性質是易變的,因為其值變化是由內部硬件模塊運作或外部信號輸入決定而不受程序代碼的控制;你自己定義的變量如果在中斷服務程序中被修改,對正常的代碼運行流程來說它們也是易變的。“volatile”類型定義在單片機的C語言編程中是如此的重要,是因為它可以告訴編譯器的優化處理器這些變量是實實在在存在的,在優化過程中不能無故消除。假定你的程序定義

33、了一個變量并對其作了一次賦值,但隨后就再也沒有對其進行任何讀寫操作,如果是非volatile型變量,優化后的結果是這個變量將有可能被徹底刪除以節約存儲空間。另外一種情形是在使用某一個變量進行連續的運算操作時,這個變量的值將在第一次操作時被復制到中間臨時變量中,如果它是非volatile型變量,則緊接其后的其它操作將有可能直接從臨時變量中取數以提高運行效率,顯然這樣做后對于那些隨機變化的參數就會出問題。只要將其定義成volatile類型后,編譯后的代碼就可以保證每次操作時直接從變量地址處取數。任何類型的變量,都可以冠以“volatile”聲明。3.2.3const聲明const用以聲明變量為永不

34、變化的常數。一般來說這些變量都應該被放在ROM區(也就是Flash程序空間以節約寶貴的RAM內存。但簡單的一個const聲明并不能保證變量最后會被分配到ROM區,安全的做法必須配合#pragma聲明的“CONST_SEG”數據段或“INTO_ROM”一起實現,這將在稍后介紹。下面為const聲明的一個范例:const byte prjName=”This is a demo”;任何類型的變量,都可以冠以“const”聲明。3.3重要的#pragma聲明#pragma聲明是基于單片機開發的特點而對標準C語法的一個擴充。它對充分利用單片機內各類有限的資源起到不可或缺的關鍵作用。下面簡單介紹幾個最常

35、用的#pragma聲明。3.3.1#pragma DATA_SEG定義變量所處的數據段。其語法型式為:#pragma DATA_SEG 名稱數據段名稱可以自己任意命名,但習慣上有些約定的名稱,其作用分別為:DEFAULT-缺省的數據段,在08系列單片機中的地址為0x100以上。一般的變量定義可以放在這一區域。MY_ZEROPAGE-特指第0頁數據段,地址范圍0x00-0xff,但實際用戶可用的空間不到256字節,因為前面的一些地址空間已經分配給了片內寄存器。需要頻繁或快速存取的變量應該指定放在這一特殊區域,特別是位變量。數據段名稱必須和prm文件中的數據段配置說明相關連才能真正發揮其定位作用。

36、如果你自己命名的數據段在prm文件中沒有特別說明,那此數據段的性質等同于“DEFAULT”。數據段的“屬性”可以缺省,它主要的目的是告訴編譯器此段數據可適用的尋址模式。不同的尋址模式所花的指令數量和運行時間都不同。對于08系列單片機,關鍵的是第0頁數據段可以用8位地址進行直接快速尋址,故對應此數據段應盡量指明其屬性為“_SHORT_SEG”。對于一般數據段沒有屬性描述,其缺省是“_FAR_SEG”,將用16位地址間接尋址。舉幾個數據段定義的例子加以進一步說明。#pragma DATA_SEG _SHORT_SEG MY_ZEROPAGE /開始0頁數據定義volatile struct uns

37、igned powerOn : 1;unsigned alarmOn : 1;unsigned commActive : 1;unsigned sysError : 1; myFlag;volatile word msCounter;byte i,j,k;#pragma DATA_SEG DEFAULT /開始普通數據段定義(結束0頁數據段byte tmpBuff16;3.3.2#pragma CONST_SEG定義一個常數數據段,必須和變量的const修飾關鍵詞配合使用。其語法型式為: #pragma CONST_SEG 名稱該數據段下定義的所有數據將被放置在程序只讀的ROM區,也就是08系

38、列單片機內的Flash程序空間區。常數段名稱可以用戶自由定義,但一般都用“DEFAULT”,讓連接器按可用的ROM區域自由分配變量位置。舉例如下: #pragma CONST_SEG DEFAULTconst byte prjName=”This is a demo”;const word version = 0x0301;#pragma CONST_SEG DEFAULTword version = 0x0301; /沒有const該變量將被放置在RAM區!#pragma DATA_SEG DEFAULTconst word version = 0x0301; /盡管有const但該變量將被

39、放置在RAM區!3.3.3#pragma INTO_ROM功能類似于“CONST_SEG”,和變量修飾詞“const”配合使用。但它只定義一個常數變量到ROM區,且只作用于緊接著的下一行定義。例如:#pragma INTO_ROMconst byte prjName=”This is a demo”; /變量將被放置在ROM區word verData = 0x0301; /變量將被放置在缺省RAM區3.3.4#pragma CODE_SEG用以定義程序段并賦以特定的段名,語法型式如下:#pragma CODE_SEG 名稱一般的程序設計是無需對代碼段做特殊處理的。因為所有傳統的08系列單片機其

40、程序空間都不超過64KB(16位尋址最大范圍且在內存地址中呈線性連續分布。對于項目中所有的代碼文件或庫文件,連接器會在最后按程序模塊出現的先后順序挨個自動安排所有程序函數在內存中所處的實際位置,用戶不必太關心某一個函數的具體位置。但最新推出的幾款8位機程序將超過64KB,這樣必須在內存空間中以頁面型式映射到首64KB地址范圍,其對應的程序段屬性要特殊聲明。某些特殊的設計需要將不同部分的程序分別定位到不同的地址空間,例如實現程序代碼下載自動更新。這樣的設計需要把負責應用程序下載更新的驅動代碼固定放置在一個保留區域內,而把一般的應用程序放置在另外一個區域以便在需要時整體擦除后更新。這時就需要用“C

41、ODE_SEG”來分別指明不同的程序段,但還必須配合prm文件對程序空間進行分配和指派。代碼段的屬性一般都用缺省的“_FAR_SEG”,表明所有的函數調用都是長調用(對應匯編指令為JSR。但C08和S08系列單片機支持效率更高的函數短調用(對應匯編指令為BSR,如果你的某一個功能模塊含有多個相互調用的小函數且函數調用間距不超過+127或-128字節,則可以將這部分代碼段聲明為短調用屬性“_NEAR_SEG”。但實際編程時由于C代碼對應的匯編指令長度不是很容易就能估測得到,所以短調用屬性很少使用。下面以幾個實例進一步說明:/定義缺省的代碼段,缺省屬性為遠調用#pragma CODE_SEG DE

42、FAULTvoid main(void./定義名字為FUNC_CODE的代碼段,缺省屬性為遠調用#pragma CODE_SEG FUNC_CODEvoid MyApp(void/定義遠調用的程序段,段名為BOOTLOAD#pragma CODE_SEG _FAR_SEG BOOTLOADvoid BootLoader(void/定義近調用的程序段,段名為KEYBOARD#pragma CODE_SEG _NEAR_SEG KEYBOARDvoid KeyDebounce(void.byte KeyCheck(void.void KeyBoard(voidif (keyCheck( KeyDe

43、bounce(;.3.3.5#pragma TRAP_PROC用于定義一個函數為中斷服務類型。此類型的函數編譯器在將C代碼編譯成匯編指令時會在代碼前后增加必要的現場保護和恢復匯編代碼,同時函數的最后返回用匯編指令“RTI”而不是針對普通函數的“RTS”。例如:#pragma TRAP_PROCvoid SCI1_Int(void /定義SCI1的中斷服務程序.注意用“TRAP_PROC”定義的中斷服務函數其實際中斷矢量地址必須通過prm文件指派。3.3.6#pragma MESSAGE這個聲明用以控制編譯信息的顯示。一般情況下這些編譯信息都是有用的,特別是告警和錯誤信息。但有時我們會按單片機的

44、工作特性編寫一些代碼,但正常程序編寫時這些代碼會產生一些告警信息,例如#pragma MESSAGE DISABLE C4002 /忽略“Result-not-used”告警/=/ sci1 1 data receive interrupt service routine/ Assigned for full-duplex communication with Main board/=void interrupt 17 sci11_Receive_ISR(voidSCI1S1; /讀一次狀態寄存器清除中斷標志,會產生C4002告警sci1RxFifosci1FifoPut = SCI1D;sc

45、i1FifoPut+;sci1FifoPut &= (SCI1_RXFIFO_SIZE-1;如果你不想每次都看見編譯器給出的這一類信息,可以先確認這一信息的編號,然后用“#pragma MESSAGE”加上“DISABLE”關鍵詞和信息號將它屏蔽。如果你想特別關注某類信息,可以用“ENABLE”讓其永遠顯示出來。3.4編寫中斷服務函數編寫中斷函數幾乎是每一個單片機項目開發必需的一個內容。CW針對08系列單片機的中斷函數編寫有三種方式可以實現。3.4.1用關鍵詞interrupt和中斷矢量編號定義中斷函數這種方式最直觀也最簡單。缺點是程序的可移植性稍差。在上面的 3.3.6節中已經給出了實現的范

46、例。關鍵詞“interrupt”告訴編譯器此函數為中斷服務函數,數字“17”告訴連接器該中斷矢量的偏移位置(以復位矢量偏移為0計。某一個中斷響應對應的矢量入口編號可以在該芯片的數據手冊中查到。3.4.2用關鍵詞interrupt定義中斷函數,中斷矢量入口由prm文件指定仍以上面的中斷服務函數為例,這是函數的定義方式為void interrupt sci11_Receive_ISR(void.然后在項目對應的prm文件中添加一行矢量位置定義:VECTOR 0 _Startup /系統缺省的復位矢量入口VECTOR 17 sci11_Receive_ISR /指定的中斷服務矢量入口3.4.3用#p

47、ragma TRAP_PROC定義中斷函數,中斷矢量入口由prm文件指定實際上就是用前面介紹的“#pragma TRAP_PROC”定義中斷函數,再按照和“interrupt”相同的方法在prm文件中指定矢量入口,不再重復。4.prm文件內容釋疑prm文件已經在前面反復多次提到。我們在這里仔細看看此文件內包含的詳細內容,理解在項目開發過程中起到什么關鍵作用。通過項目模板建立的新項目中都有一個名字為“project.prm”的文件,位于圖1-8所示項目文件列表的“Linker Files”一欄。一個標準的prm文件起始內容如下:例4.1 prm文件內容實例/* This is a linker

48、parameter file for the AW32 */NAMES END /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */ROM = READ_ONLY 0x8000 TO 0xFFAF;Z_RAM = READ_WRITE

49、0x0070 TO 0x00FF;RAM = READ_WRITE 0x0100 TO 0x086F;ROM1 = READ_ONLY 0xFFC0 TO 0xFFCB;ENDPLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */DEFAULT_RAM INTO RAM;DEFAULT_ROM, ROM_VAR, STRINGS INTO ROM;_DATA_ZEROPAGE, MY_ZEROPAGE INTO Z_RAM;ENDSTACKSIZE 0x5

50、0VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */4.1prm文件組成結構按所含的信息prm文件有五個組成部分構成:“NAMES END”部分用以指定在連接時加入除本項目文件列表之外的額外的目標代碼模塊文件,這些文件都是事先經C編譯器或匯編器編譯好的機器碼目標文件而不是源代碼文件。不過這種用法比較少見,因為我們可以在圖1-8所示項目文件列表的“Libs”一欄中添加這些目標代碼文件來實現同樣的任務,而且由項目列表管理這些模塊文件比較直觀方便。“SEGMENTS END

51、”部分定義和劃分芯片所有可用的內存資源,包括程序空間和數據空間。一般我們將程序空間定義成“ROM”,把數據空間劃分成第0頁的“Z_RAM”和普通區域的“RAM”,但實際上這些名字都不是系統保留的關鍵詞,可以由用戶隨意修改。用戶也可以把內存空間按地址和屬性隨意分割成大小不同的塊,每塊可以自由命名。關于內存劃分的具體方法在后面詳解。“PLACEMENT END”部分將指派源程序中所定義的各種段,例如數據段DATA_SEG、CONST_SEG和代碼段CODE_SEG被具體放置到哪一個內存塊中。它是將源程序中的定義描述和實際物理內存掛鉤的橋梁。“STACKSIZE”定義系統堆棧長度,其后給出的長度字節

52、數可以根據實際應用需要進行修改。堆棧的實際定位取決于RAM內存的劃分和使用情況。在常見的RAM線性劃分變量連續分配的情況下,堆棧將緊挨在用戶所定義的所有變量區域的高端。但如果你將RAM區分成幾個不同的塊,請確保其中至少有一個塊能容納已經定義的堆棧長度。“VECTOR”定義所有矢量入口地址。模板在生成prm文件時已經定義了復位矢量的入口地址。對于各類中斷矢量用戶必須自己按矢量編號和中斷服務函數名相關聯,請參考 3.4.2中代碼范例。如果中斷函數的定義是用“interrupt”加上矢量號,則無需在這里重復定義。prm文件中可以添加注釋,語法和C語言相同,可以是“/*/”或“/”。4.2內存劃分的具

53、體方式由“SEGMENTS”開始到“END”為止,中間可以添加任意多行內存劃分的定義,每一行用分號“;”結尾。定義行的語法型式為:塊名 = 屬性 起始地址 TO 結束地址;其中,“塊名”的定義和C語言變量定義相同,是以英文字母開頭的一個字符串。“屬性”可以有三種不同的類型。對于只讀的Flash-ROM區屬性一定是“READ_ONLY”,對于可讀寫的RAM區屬性可以是“READ_WRITE”,也可以是“NO_INIT”。它們兩者的關鍵區別是ANSI-C的初始化代碼會把定位在“READ_WRITE”塊中的所有全局和靜態變量自動清零,而“NO_INIT”塊中的變量將不會被自動清零。對于單片機系統,變

54、量在復位時不被自動清零這一特性有時是很關鍵的。起始地址和結束地址決定了一內存塊的物理位置,用16進制表示。下面舉幾個例子來進一步說明:例4.2 劃分Flash-ROM區,定義512字節EEPROM模擬區SEGMENTSEEPROM = READ_ONLY 0x8000 TO 0x81FF;ROM = READ_ONLY 0x8200 TO 0xFFAF;Z_RAM = READ_WRITE 0x0070 TO 0x00FF;RAM = READ_WRITE 0x0100 TO 0x086F;END例4.3 劃分RAM區,定義16字節非自動清零的數據保留區SEGMENTSROM = READ_ONLY 0x8000 TO 0xFFAF;Z_RAM = READ_WRITE 0x0070 TO 0x00FF;RAM_KEEP = NO_INIT 0x0100 TO 0x010F;RAM = READ_WRITE 0x0110 TO 0x086F;END用“SEGMENTS”只是從單片機的物理內存這一角度對其進行空間劃分。源程序本身并不知道物理內存被分割和屬性定義的這些細節。它們兩者之間必須通過下面的“PLACEMENT”建立聯系。4.3程序段和數據段的放置“PLACEMENT - END”內所描述的信息是告訴連接器

溫馨提示

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

評論

0/150

提交評論