|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機 | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計 | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
[轉(zhuǎn)貼]HC08 C語言程序設(shè)計(2) |
| 作者:JerryBJ 欄目:單片機 |
周末在www.mcu123.com上讀到劉玉宏同志的這篇文章,覺得寫得很好,基本上涵蓋了使用C語言對HC(S)08微控制器編程的基本知識,推薦給大家。把這篇文章轉(zhuǎn)貼過來,沒有經(jīng)過原文作者和MCU123的允許,希望他們不會生氣。若作者和MCU123對此感到不適,請即告知,我們立刻刪除此轉(zhuǎn)貼。原文鏈接如下: http://www.mcu123.com/news/Article/uc/Motorola/200608/253.html 變量定位 普通變量的定義和訪問同標準C語言,在HCS08 C語言中我們主要要解決映像寄存器變量和某些特殊變量的定位問題,即把這些變量存放在RAM中指定的位置。 1映像寄存器定位 映像寄存器單片機中跟硬件有關(guān)的寄存器,它們都有各自固定RAM地址,其定位有3種方法 1)宏定義 例如:#define PortA ( * ( volatile unsigned CHAR * ) 0x0000 ) 這樣 PortA 成為一個地址在0x0000的unsigned CHAR類型變量。這個定義看起來很復雜,其實它也可以分解成幾個很簡單的部分來看。 ( volatile unsigned CHAR * )是C語言中的強制類型轉(zhuǎn)換,它的作用是把0x0000這個純粹的十六進制數(shù)轉(zhuǎn)換成為一個(地址)指針,其中volatile并不是必要的,它只是告訴編譯器,這個值與外界環(huán)境有關(guān),不要對它優(yōu)化接下來在外面又加了一個*號,就表示0x0000內(nèi)存單元中的內(nèi)容了。經(jīng)過這個宏定義之后,PortA就被可以做為一個普通的變量來操作,所有出現(xiàn)PortA的地方編譯的時候都被替換成( * ( volatile unsigned CHAR * ) 0x0000 ),外面一層括號是為了保證里面的操作不會因為運算符優(yōu)先級或者其它不可預測的原因被改變而無法得到預期的結(jié)果。 這種定義方法適合所有的C編譯器,可移植性好,但PortA并不是一個真正的變量,只是一個宏名,當你調(diào)試一個程序的時候,無法在調(diào)試窗口觀察它的值。另外連接器也失去了靈活性,它得防止其它變量跟此變量沖突。 2)使用@關(guān)鍵字 例如: volatile unsigned CHAR PortA @0x0000; @是編譯器擴展的一個特殊修飾符,其它編譯器很可能并不認識。這種定義具有很好的可讀性,失去了可移植性。 3)使用段定義 這種方法分為2個步驟 首先把變量定義在段中,其次在連接參數(shù)文件(*.prm)中把段定位在一個合適的位置 例如:第1步:在源程序文件中 #pragma DATA_SEG PORTB_SEG volatile unsigned CHAR PortA; #pragma DATA_SEG DEFAULT 這樣變量 PortA 定義在段 PORTB_SEG 中 第2步:在 prm 文件中 SECTIONS PORTB_SEG = READ_WRITE 0x0000 SIZE 1; 這樣段 PORTB_SEG 定位在地址0x0000上。 這種方法可移植性也很差,如果你要把它移植在別的編譯器上,你不得不修改源程序。 2變量定義修飾符 變量定義有三個修飾符值得注意,雖然它們與標準C是相同的,但是在嵌入式C語言中又有不同的含義。 1) static 在子函數(shù)中static用聲明的變量是局部變量,但是退出這個子函數(shù)后其值不消失。下一次調(diào)用這個函數(shù)時仍可以訪問到原來的值。注意,在子函數(shù)中聲明的static變量只對聲明他的函數(shù)可見,別的函數(shù)是不可以使用的。如果static變量是在模塊中聲明的,那么只有本模塊的函數(shù)可以使用它,別的模塊中的函數(shù)是不能訪問的。 void MyFunction (void) { static CHAR myVar = 0; //用 static聲明的局部變量 myVar = myVar + 1; } void main (void) { MyFunction(); //調(diào)用之前myVar = 0,調(diào)用之后myVar = 1 MyFunction(); //調(diào)用之前myVar = 1,調(diào)用之后myVar = 2 } 2) volatile 如果一個變量的值可能會被程序操作之外的其它操作所改變,那么你必需用volatile 聲明。在嵌入式系統(tǒng)中其它操作是:中斷服務程序的操作、硬件動作的操作。 用volatile聲明的變量是不會被編譯器優(yōu)化掉的,如: volatile unsigned CHAR PortA @0x0000; PORTA做為一個輸入端口,其值是由外部設(shè)備決定的,由于外部設(shè)備的變化是隨機的,因此第一次讀取的值和第二次讀取的值很可能不同,所以我們把它聲明為volatile變量。 a = PORTA; a = PORTA; 由于PORTA是用volatile聲明的變量,編譯器不會把它優(yōu)化成一句,而如果不是volatile聲明的編譯器就會將第二句優(yōu)化掉,從而程序?qū)雎暂斎攵丝诘淖兓?br> 通常把嵌入式設(shè)備的所有外圍器件寄存器都聲明為volatile 的。 3) const 修飾符 const 可以用在任何變量之前, 告訴編譯器把此變量存儲在ROM中。ROM_VAR段是定位 const 變量的默認段 語法格式:#pragma CONST_SEG <段名> 例如: #pragma DATA_SEG DEFAULT #pragma CONST_SEG DEFAULT static int a;//變量 a 存放在默認的 RAM 段 DEFAULT_RAM 中,DEFAULT_RAM是段名 static const int c0 = 10;//變量 c0 存放在默認的 ROM 段 ROM_VAR 中,ROM_VAR是段名 此時編譯器選項-Cc必需是打開的。如果編譯器選項-Cc必需是關(guān)閉的,則變量a和c0都定位在DEFAULT_RAM中。 例如: #pragma DATA_SEG MyVarSeg #pragma CONST_SEG MyConstSeg static int a; //變量 a 存放在段MyVarSeg中,MyVarSeg是段名 static const int c0 = 10; //變量 c0 存放在段 MyConstSeg 中,MyConstSeg是段名 此時編譯器選項-Cc必需是打開的。如果編譯器選項-Cc必需是關(guān)閉的,則變量a和c0都定位在MyVarSeg中。 3全局變量和局部變量 全局變量為整個程序而定義,在整個程序運行期間。它們占用固定的RAM資源,因此除非在必需的情況,否則不要輕易使用。局部變量為某個函數(shù)而定義,只在此函數(shù)運行的時候,占用?臻g,局部變量實質(zhì)上是函數(shù)運行所需要的一段RAM空間。因此函數(shù)不運行時,它們不占用RAM資源。全局變量通常是為了給中斷服務函數(shù)傳遞參數(shù)定義的,建議定義時把它們定義在一個相對集中的RAM空間。 例如: #pragma DATA_SEG SCI_DATA /* 這條預處理指令之后的所有變量定義在 SCI_DATA 段 */ CHAR senderBuffer[50]; CHAR receiverBuffer[100]; ... #pragma DATA_SEG DEFAULT /*這條預處理指令之后的所有變量定義在默認段*/ 在參數(shù)文件中必需指定 SCI_DATA 段。 4位定義和訪問 HCS08 C 語言采用直接位訪問的方法來訪問位,位的定義采用聯(lián)合和結(jié)構(gòu)數(shù)據(jù)類型來實現(xiàn)。 例如: volatile union { struct { unsigned CHAR MWPR:1; /* MWPR is bit 0 in FEETST */ unsigned CHAR STRE:1; /* STRE is bit 1 in FEETST */ unsigned CHAR VTCK:1; /* VTCK is bit 2 in FEETST */ unsigned CHAR FDISVFP:1; /*FDISVFP is bit 3 in FEETST */ unsigned CHAR FENLV:1;/* FENLV is bit 4 in FEETST */ unsigned CHAR HVT:1; /* HVT is bit 5 in FEETST */ unsigned CHAR GADR:1; /* GADR is bit 6 in FEETST */ unsigned CHAR FSTE:1; /* FSTE is bit 7 in FEETST */ } FEETST_BITS; unsigned CHAR FEETST_BYTE; /* Alternate definition of the PORT as a 8-bit variables. */ } FEETST_struct @0x00F6; /* Define Symbol to access register FEETST */ #define FEETST FEETST_struct.FEETST_BYTE /* Define Symbols to access SINGLE bits in FEETST */ #define MWPR FEETST_struct.FEETST_BITS.MWPR #define STRE FEETST_struct.FEETST_BITS.STRE #define VTCK FEETST_struct.FEETST_BITS.VTCK #define FDISVFP FEETST_struct.FEETST_BITS.FDISVFP #define FENLV FEETST_struct.FEETST_BITS.FENLV #define HVT FEETST_struct.FEETST_BITS.HVT #define GADR FEETST_struct.FEETST_BITS.GADR #define FSTE FEETST_struct.FEETST_BITS.FSTE 這里的“:1”表示僅需要一個位,HCS08會把它們包裝在一起形成一個字節(jié)。這樣我們就可以以字節(jié)方式或位方式訪問整個寄存器和位。 例如: FEETST =0X80;//字節(jié)方式 MWPR = 1;//位方式 VTCK=1; // BSET 2,FEETST1 FDISVFP=0; // BCLR 4,FEETST1 有關(guān)映像寄存器和位定義可以參照具體芯片的頭文件。 |
| 2樓: | >>參與討論 |
| 作者: afanti 于 2006/11/14 11:32:00 發(fā)布:
謝謝樓主了! |
|
|
|
| 免費注冊為維庫電子開發(fā)網(wǎng)會員,參與電子工程師社區(qū)討論,點此進入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號 |