研製單片機應用係統時,匯編語言是一種常用的軟件工具。它能直接操作硬件,指令的執行速度快。但其指令係統的固有格式受硬件結構的限製很大,且難於(yu) 編寫(xie) 與(yu) 調試,可移植性也差。隨著單片機硬件性能的提高,其工作速度越來越快,因此在編寫(xie) 單片機應用係統程序時,更著重於(yu) 程序本身的編寫(xie) 效率。而Franklin C51交叉編譯器是專(zhuan) 為(wei) 80C51係列單片機設計的一種高效的C語言編譯器,使用它可以縮短開發周期,降低開發成本,而且開發出的係統易於(yu) 維護,可靠性高,可移植性好,即使在代碼的使用效率上,也完全可以和匯編語言相比,因此目前它已成為(wei) 開發80C51係列單片機的流行工具。
1 C51語言程序設計的基本技巧
C語言是一種高級程序設計語言,它提供了十分完備的規範化流程控製結構。因此采用C51語言設計單片機應用係統程序時,首先要盡可能地采用結構化的程序設計方法,這樣可使整個(ge) 應用係統程序結構清晰,易於(yu) 調試和維護。對於(yu) 一個(ge) 較大的程序,可將整個(ge) 程序按功能分成若幹個(ge) 模塊,不同的模塊完成不同的功能。對於(yu) 不同的功能模塊,分別指定相應的入口參數和出口參數,而經常使用的一些程序最好編成函數,這樣既不會(hui) 引起整個(ge) 程序管理的混亂(luan) ,還可增強可讀性,移植性也好。
在程序設計過程中,要充分利用C51語言的預處理命令。對於(yu) 一些常用的常數,如TRUE,FALSE,PI以及各種特殊功能寄存器,或程序中一些重要的依據外界條件可變的常量,可采用宏定義(yi) "#define"或集中起來放在一個(ge) 頭文件中進行定義(yi) ,再采用文件包含命令"#include"將其加入到程序中去。這樣當需要修改某個(ge) 參量時,隻須修改相應的包含文件或宏定義(yi) ,而不必對使用它們(men) 的每個(ge) 程序文件都作修改,從(cong) 而有利於(yu) 文件的維護和更新。現舉(ju) 例說明如下:
例1 對於(yu) 不同的單片機晶振,程序取不同的延時時間,而且可根據外界條件的變化修改延時時間的長短。對於(yu) 這樣的程序,可利用宏定義(yi) 和條件編譯來實現。程序如下:
#define flag 1
#ifdef flag==1
#define fosc 6M
delay=10;
#elif flag = = 0
#define fosc 8M
delay=12;
#else
#define fosc 12M
delay=20;
#endif
main()
{
for(I=0;I
2 C51語言與(yu) 匯編語言程序的混合編程
C51編譯器能對C語言源程序進行高效率的編譯,生成高效簡潔的代碼,在絕大多數場合采用C語言編程即可完成預期的目的。但有時為(wei) 了編程直觀或某些特殊地址的處理,還須采用一定的匯編語言編程。而在另一些場合,出於(yu) 某種目的,匯編語言也可調用C語言。在這種混合編程中,關(guan) 鍵是參數的傳(chuan) 遞和函數的返回值。它們(men) 必須有完整的約定,否則數據的交換就可能出錯。下麵就以力源公司的10位串行A/D轉換器TLC1549 為(wei) 例說明C語言程序與(yu) 匯編語言程序的調用。
圖1 TLC1549管腳圖
1549的管腳圖和時序圖分別如圖1和圖2所示,假定DATA OUT接P1.0,
接P1.1,CLOCK接P1.2。
1549的具體(ti) 特性請查閱有關(guan) 資料。
例2 C語言程序與(yu) 匯編語言程序的調用,其子程序如下:
PUBLIC AD ;入口地址
SEG_AD SEGMENT CODE ;程序段
RSEG SEG_AD
USING 0
AD: MOV R6,#00
MOV R7,#00
SETB P1.1
ACALL DELAY
CLR P1.1
ACALL DELAY
MOV R0,#10
RR0: SETB P1.2
NOP
CLR P1.2
DJNZ R0,RR0
ACALL DELAY
MOV 30H,R6 ;A/D轉換的高
;兩(liang) 位保存在R6中
ACALL CIR
MOV R6,30H
SETB P1.2
NOP
CLR P1.2
MOV 30H,R6
ACALL CIR
MOV R6,30H
MOV R0,#8 ;A/D轉換的低
;8位保存在R7中
RR2: SETB P1.2
NOP
CLR P1.2
MOV 30H,R7
ACALL CIR
MOV R7,30H
DJNZ R0,RR2
RET
CIR: CLR C
MOV C,P1.0
MOV A,30H
RLC A
MOV 30H,A
RET
END
在以上程序中,函數的返回值為(wei) 一無符號整型數,根據調用規則,返回值的高位必須在R6中,低位在R7中,這樣才可保證數據的傳(chuan) 遞不出錯。另外,在調用過程中,必須注意寄存器的入棧。這樣在以後用到A/D轉換時,在C語言中調用匯編語言子程序AD()即可。
3 C51中斷處理過程
C51編譯器支持在C源程序中直接開發中斷過程,因此減輕了使用匯編語言的繁瑣工作,提高了開發效率。中斷服務函數的完整語法如下:
void 函數名(void)[模式]
[再入]interrupt n [using r]
其中n(0~31)代表中斷號。C51編譯器允許32個(ge) 中斷,具體(ti) 使用哪個(ge) 中斷由80C51係列的芯片決(jue) 定。r(0~3)代表第r組寄存器。在調用中斷函數時,要求中斷過程調用的函數所使用的寄存器組必須與(yu) 其相同。"再入"用於(yu) 說明中斷處理函數有無"再入"能力。C51編譯器及其對C語言的擴充允許編程者對中斷所有方麵的控製和寄存器組的使用。這種支持能使編程者創建高效的中斷服務程序,用戶隻須在C語言下關(guan) 心中斷和必要的寄存器組切換操作。
例3 設單片機的fosc=12MHz,要求用T0的方式1編程,在P1.0腳輸出周期為(wei) 2ms的方波。
用C語言編寫(xie) 的中斷服務程序如下:
#include
sbit P1_0=P1^0;
void timer0(void)interrupt 1 using 1 {
/*T0中斷服務程序入口*/
P1_0=!P1_0;
TH0=-(1000/256); /*計數初值重裝*/
TL0=-(1000%256);
}
void main(void)
{
TMOD=0x01; /*T0工作在定時器方式1*/
P1_0=0;
TH0=-(1000/256); /*預置計數初值*/
TL0=-(1000%256);
EA=1; /*CPU開中斷*/
ET0=1; /*T0開中斷*/
TR0=1; /*啟動T0*/
do{}while(1);
}
在編寫(xie) 中斷服務程序時必須注意不能進行參數傳(chuan) 遞,不能有返回值。
4 結論
C51編譯器不但可以縮短單片機控製係統的開發周期,而且易於(yu) 調試和維護。此外,C51語言還有許多強大的功能,如提供豐(feng) 富的庫函數供用戶直接調用,完整的編譯控製指令為(wei) 程序調試提供必要的符號信息等等。總之,C51語言是廣大單片機開發人員的強有力的工具。