8.1.1 為什么要用高級語言
當設計一個小的嵌入式系統(tǒng)時,一般我們都用匯編語言。在很多工程中這是一個很好的方法,因為代碼一般都不超過8K, 而且都比較簡單。如果硬件工程師要同時設計軟件和硬件,經常會采用匯編語言來做程序。我的經驗告訴我:硬件工程師一般不熟悉像C一類的高級語言。
使用匯編的麻煩,在于它的可讀性和可維護性。特別當程序沒有很好的標注的時候,代碼的可重用性也比較低,如果使用C的話可以很好的解決這些問題。
用C 編寫的程序,因為C 語言很好的結構性和模塊化,更容易閱讀和維護。而且,由于模塊化用C 語言編寫的程序,有很好的可移植性,功能化的代碼能夠很方便的從一個工程移植到另一個工程,從而減少了開發(fā)時間。用C 編寫程序比匯編更符合人們的思考習慣,開發(fā)者可以更專心的考慮算法,而不是考慮一些細節(jié)問題。這樣,就減少了開發(fā)和調試的時間。
使用像C 這樣的語言,程序員不必十分熟悉處理器的運算過程。這意味著對新的處理器也能很快上手,不必知道處理器的具體內部結構。使得用C 編寫的程序比匯編程序有更好的可移植性,很多處理器支持C 編譯器。
所有這些,并不說明匯編語言就沒了立足之地。很多系統(tǒng),特別是實時時鐘系統(tǒng)都是用C 和匯編語言聯(lián)合編程。對時鐘要求很嚴格時,使用匯編語言成了唯一的方法。除此之外,包括硬件接口的操作都應該用C 來編程。C 的特點:就是可以使你盡量少地對硬件進行操作,是一種功能性和結構性很強的語言。
8.1.2 Keil C 和ANSI C
下面將介紹Keil C 的主要特點和它與ANSI C 的不同之處。并給你一些對8051 使用C的啟發(fā)。
Keil 編譯器,除了少數(shù)一些關鍵地方外,基本類似于ANSI C 。差異主要是:Keil 可以讓用戶針對8051 的結構進行程序設計。其它差異主要是8051 的一些局限引起的。
8.1.3 特殊功能寄存器
特殊功能寄存器,用sfr 來定義。而sfr16 用來定義16 位的特殊功能寄存器。如DPTR通過名字或地址來引用特殊功能寄存器,地址必須高于80H。 可位尋址的特殊功能寄存器的位變量定義,用關鍵字sbit SFR 的定義如列表0-1所示:對于大多數(shù)8051 成員Keil提供了一個包含了所有特殊功能寄存器和他們的位的定義的頭文件。通過包含頭文件可以很容易的進行新的擴展。
列表0-1
sfr SCON=0X98; //定義SCON
sbit SM0=0X9F; //定義SCON 的各位
sbit SM1=0X9E;
sbit SM2=0X9D;
sbit REN=0x9C;
sbit TB8=0X9B;
sbit RB8=0X9A;
sbit TI=0X99;
sbit RI=0X98;
8.1.4 存儲類型
Keil 允許使用者指定程序變量的存儲區(qū),這使使用者可以控制存儲區(qū)的使用,編譯器可識別以下存儲區(qū)。
存儲區(qū)描述
DATA RAM 的低128 個字節(jié)可在一個周期內直接尋址
BDATA DATA 區(qū)的16 個字節(jié)的可位尋址區(qū)
IDATA RAM 區(qū)的高128 個字節(jié)必須采用間接尋址
PDATA 外部存儲區(qū)的256 個字節(jié)通過P0 口的地址對其尋址
使用指令MOVX @Rn,需要兩個指令周期
XDATA 外部存儲區(qū)使用DPTR 尋址
CODE 程序存儲區(qū)使用DPTR 尋址
8.1.5 中斷服務
8051 的中斷系統(tǒng)十分重要,C51 使你能夠用C 來聲明中斷和編寫中斷服務程序(當然你也可以用匯編來寫) ,中斷過程通過使用interrupt 關鍵字和中斷號(0 到31)來實現(xiàn)。中斷號告訴編譯器,中斷程序的入口地址、中斷號對應著IE 寄存器中的使能位。換句話說IE寄存器中的0 位對應著外部中斷0 。相應的外部中斷0 的中斷號是0, 表0-6 反映了這種關系:
一個中斷過程,并不一定帶上所有參數(shù),可以沒有返回值。有了這些限制,編譯器不須要擔心寄存器組參數(shù)的使用和對累加器狀態(tài)寄存器B 、寄存器數(shù)據(jù)指針和默認的寄存器的保護。只要他們在中斷程序中,被用到編譯的時候,會把他們入棧在中斷程序結束時將他們恢復。中斷程序的入口地址被編譯器放在中斷向量中,C51 支持所有5 個8051/8052 標準中斷、從0 到4 和在8051 系列中多達27 個中斷源,一個中斷服務程序的例子如下:
列表0-2
#include
#include
#define RELOADVALH 0x3C
#define RELOADVALL 0xB0
extern unsigned int tick_count;
void timer0(void) interrupt 1
{
TR0=0; // 停止定時器0
TH0=RELOADVALH; // 50ms后溢出
TL0=RELOADVALL;
TR0=1; // 啟動T0
tick_count++; // 時間計數(shù)器加1
printf("tick_count=%05u\n", tick_count);
}
有關KEIL C的集成環(huán)境使用可參考本書附錄,這里就不詳述。
使用C 來開發(fā)系統(tǒng),方便快捷。他既不會降低你對硬件的控制能力,也不會使你的代碼長度增加多少,如果你運用得好的話,你能夠開發(fā)出非常高效的系統(tǒng),并且非常利于維護。
