版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第5章 單片機的C語言程序設(shè)計,1 C語言與MCS-512 C51數(shù)據(jù)類型及在MCS-51中的存儲方式3 C51數(shù)據(jù)的存儲類型與MCS-51存儲結(jié)構(gòu)4 MCS-51特殊功能寄存器(SFR)的C51定義5 MCS-51并行接口的C51定義6 位變量的C51定義7 C51構(gòu)造數(shù)據(jù)類型8 模塊化程序開發(fā)過程,,采用C51的優(yōu)點,編譯器能自動完成變量的存儲單元的分配,編程者可以
2、專注于應(yīng)用軟件的設(shè)計,可以對常用的接口芯片編制通用的驅(qū)動函數(shù),對常用的功能模塊和算法編制相應(yīng)的函數(shù),可以方便地進行信號處理算法和程序的移植,從而加快單片機應(yīng)用系統(tǒng)的開發(fā)速度。 當代碼長度超過4KB以上時,C51比匯編語言更具有明顯的優(yōu)勢。,C-51與ASM-51相比,有如下優(yōu)點:1. 對單片機的指令系統(tǒng)不要求了解,僅要求對8051 的存貯器結(jié)構(gòu)有初步了解;2. 寄存器分配、
3、不同存貯器的尋址及數(shù)據(jù)類型等細節(jié)可由編譯器管理;3. 程序有規(guī)范的結(jié)構(gòu),可分成不同的函數(shù),這種方式可使程序結(jié)構(gòu)化;,4. 具有將可變的選擇與特殊操作組合在一起的能力,改善了程序的可讀性;5. 提供的庫包含許多標準子程序,具有較強的數(shù)據(jù)處理能力;6. 由于具有方便的模塊化編程技術(shù),使已編好程序可容易地移植;,例:清零程序 (將2000H—20FF
4、H的內(nèi)容清零) ★ 匯編語言程序 ORG 0000HSE01: MOV R0,#00H MOV DPTR,#2000H ;(0000H)送DPTRLOO1: CLR A MOVX @DPTR,A ;0送(DPTR) INC DPTR ;DPTR+1 INC R0 ;字節(jié)數(shù)加1
5、 CJNE R0,#00H,LOO1 ;不到FF個字節(jié)再清LOOP: SJMP LOOP END,清零程序 (將2000H—20FFH的內(nèi)容清零) ★ C-51程序 #include void main( ) { int i; unsigned char xdata *p=0x2000; /*
6、指針指向2000H單元 */ for(i=0;i<256;i++) {*p=0; p++;} /*清零2000H-20FFH單元*/ },ORG 0000HL00: MOV R0,#10H ;查找16個字節(jié) MOV R1,#00H MOV DPTR,#2000HL11: MOVX A,@DPTR CJNE A,#00H,L16 ;取出內(nèi)
7、容與00H相等嗎? INC R1 ;取出個數(shù)加1L16: INC DPTR DJNZ R0,L11 ;未完繼續(xù) MOV DPTR,#2100H MOV A,R1 MOVX @DPTR,A ;相同數(shù)個數(shù)送2100HL1E: SJMP L1E END,例:查找零的個數(shù)(在2000H--200FH中查出有幾個字節(jié)是零,把個數(shù)放在210
8、0H單元中),★查找零的個數(shù)C-51程序#include void main ( ){ unsigned char xdata *p=0x2000;/*指針p指向2000H單元*/ int n=0,i; for(i=0;i<16;i++) { if(*p= =0) n++; /* 若該單元內(nèi)容為零,則n+1 */ p++; /* 指針指向下一單元 */
9、 } p=0x2100; /* 指針p指向2100H單元 */ *p=n; /* 把個數(shù)放在2100H單元中 */},1 C語言與MCS–51,用匯編語言編程時,必須要考慮其存儲器結(jié)構(gòu),尤其必須考慮其片內(nèi)數(shù)據(jù)存儲器與特殊功能寄存器正確、合理的使用以及按實際地址處理端口數(shù)據(jù)。 用C語言編程中,對數(shù)據(jù)類型與變量的定義,必須要與單片機的存儲結(jié)構(gòu)相關(guān)聯(lián),否
10、則編譯器不能正確地映射定位。 用C語言編寫單片機程序與標準C語言程序的不同之處就在于根據(jù)單片機存儲結(jié)構(gòu)及內(nèi)部資源定義相應(yīng)的C語言中的數(shù)據(jù)類型和變量。,用C語言編寫的應(yīng)用程序必須經(jīng)單片機的C語言編譯器(簡稱C51),轉(zhuǎn)換生成單片機可執(zhí)行的代碼程序?,F(xiàn)在支持MCS–51系列單片機的C語言編譯器有很多種。 如American Automation、Auocet、BSO/TASKING、DUNFIELD SHAREWARE
11、、KEIL/Franklin等。 其中KEIL/Franklin以它的代碼緊湊和使用方便等特點優(yōu)于其它編譯器。本章是針對這種編譯器介紹 MCS–51單片機C語言程序設(shè)計。,2 C51數(shù)據(jù)類型及在MCS-51中的存儲方式,2.1 C51的數(shù)據(jù)類型 KEIL/Franklin C51編譯器支持的數(shù)據(jù)類型有:位型(bit)、無符號字符(unsigned char)、有符號字符(singed char)、無符號整型
12、(unsigned int )、有符號整型(signed int )、無符號長整型(unsigned long )、有符號長整型(signed long )、浮點型(float)和指針類型等。,表.1 C51的數(shù)據(jù)類型,2.2 C51數(shù)據(jù)在MCS-51中的存儲方式,位變量(bit):與MCS-51硬件特性操作有關(guān)的可定義成位變量。位變量必須定位在MCS-51單片機片內(nèi)RAM的位尋址空間中。 字符變量(char):字符變量的長度為
13、1 字節(jié)即8位。對于無符號變量(unsigned char)的值域范圍是0~255。對于有符號字符變量(signed char),最具有重要意義的位是最高位上的符號標志位(msb)。此位為1代表"負",為0代表"正"。有符號字符變量和無符號字符變量在表示0~127的數(shù)值時,其含義是一樣的,都是0~0x7F。負數(shù)一般用補碼表示,即用11111111表示-1, 用11111110表示-2……。,整型變
14、量(int): 整型變量的長度為16位。MCS-51系列單片機將int型變量的高位字節(jié)數(shù)存放在低地址字節(jié)中,低位字節(jié)數(shù)存放在高地址字節(jié)中。有符號整型變量(signed int)也使用msb位作符號標志位,并使用二進制補碼表示數(shù)值??芍苯邮褂脦追N專用的機器指令來完成多字節(jié)的加、減、乘、除運算。整型變量值0x1234以圖1所示的方式存放在內(nèi)存中。,圖1 整型數(shù)的存儲結(jié)構(gòu),+0+1,地址,+0+1+2+3,地址,圖2 長整型變量的
15、存儲結(jié)構(gòu),浮點型變量(float): 浮點型變量為32位,占4個字節(jié),許多復(fù)雜的數(shù)學(xué)表達式都采用浮點變量數(shù)據(jù)類型。用符號位表示數(shù)的符號,用階碼和尾數(shù)表示數(shù)的大小。 用它們進行任何數(shù)學(xué)運算都需要使用由編譯器決定的各種不同效率等級的庫函數(shù)。C51的浮點變量數(shù)據(jù)類型的使用格式與IEEE-754標準有關(guān),具有24位精度,尾數(shù)的高位始終為"1",因而不保存,位的分布如下:● 1位符號位。● 8位指數(shù)位?!?/p>
16、 23位尾數(shù)。,符號位是最高位,尾數(shù)為低23位,內(nèi)存中按字節(jié)存儲順序如下:,其中,S為符號位,1表示負,0表示正;E為階碼;M為23位尾數(shù),最高位為"1"。 浮點變量值 -12.5的十進制為:0xC1480000,它按圖3所示方式存于內(nèi)存中。,+0+1+2+3,地址,圖3 浮點數(shù)的存儲結(jié)構(gòu),在編程時,如果只強調(diào)運算速度而不進行負數(shù)運算時,最好采用無符號(unsigned)格式。
17、 無符號字符類型的使用:無論何時,應(yīng)盡可能使用無符號字符變量,因為它能直接被MCS-51所接受?;谕瑯拥脑颍矐?yīng)盡量使用位變量。有符號字符變量雖然也只占用一個字節(jié),但需要進行額外的操作來進行測試代碼的符號位。,使用簡化形式定義數(shù)據(jù)類型。其方法是在源程序開頭使用#define語句自定義簡化的類型標識符。例如:#define uchar unsigned char #define uint unsigned in
18、t 這樣,在編程中,就可以用uchar代替unsigned char,用uint代替unsigned int來定義變量。,3 C51數(shù)據(jù)的存儲類型與MCS-51存儲結(jié)構(gòu),表 2 C51存儲類型與MCS-51存儲空間的對應(yīng)關(guān)系,1、DATA 區(qū) 8051 內(nèi)128 字節(jié)的內(nèi)部RAM,或8052的前128字節(jié)內(nèi)部RAM, 這部分主要是作為數(shù)據(jù)段稱為DATA區(qū)。指令用一個或兩個周期來訪問數(shù)據(jù)段?!?數(shù)據(jù)段中有兩
19、個小段,第一個子段包含四組寄存器組。另外一個子段叫做位尋址段BDATA,包括16 個字節(jié)共128 位每一位都可單獨尋址?!?對DATA 區(qū)的尋址是最快的所以應(yīng)該把使用頻率高的變量放在DATA 區(qū),DATA 區(qū)除了包含程序變量外還包含了堆棧和寄存器組unsigned char data system_status=0;unsigned int data unit_id[2];char data inp_string[16];
20、float data outp_value;mytype data new_var;,2、BDATA 區(qū)單片機內(nèi)部RAM的位尋址區(qū)叫做位尋址段BDATA區(qū), 包括16 個字節(jié)共128位。可以在DATA 區(qū)的位尋址區(qū)定義變量(非浮點型) ,這個變量就可進行位尋址,并且可以聲明位變量。unsigned char bdata status_byte;unsigned int bdata status_word;sbit stat_
21、flag=status_byte^4;if(status_word^15){…}stat_flag=1;編譯器不允許在BDATA 段中定義float 和double 類型的變量。,IDATA 段 8051 系列的一些單片機如8052有附加的128字節(jié)的內(nèi)部RAM, 位于從80H開始的地址空間中,這部分加上低128字節(jié)的內(nèi)部RAM共256字節(jié),被稱為IDATA。因為IDATA區(qū)的地址和SFR的地址是重疊的,通過區(qū)分所訪問
22、的存儲區(qū)來解決地址重疊問題,因此IDATA 區(qū)只能通過間接尋址來訪問. IDATA 段也可存放使用比較頻繁的變量,使用寄存器作為指針進行尋址,在寄存器中設(shè)置8 位地址進行間接尋址。和外部存儲器尋址比較,它的指令執(zhí)行周期和代碼長度都比較短。unsigned char idata system_status=0;unsigned int idata unit_id[2];char idata inp_string[16];f
23、loat idata outp_value;,,PDATA區(qū) 外部存儲區(qū)的最低地址的256個字節(jié),稱為PDATA區(qū)。通過P0口的地址對其尋址,使用指令MOVX @Rn,需要兩個指令周期。unsigned int pdata unit_id[2];float pdata outp_value;,XDATA區(qū) 8051單片機的外部RAM,存儲空間為64K,采用16 位地址尋址稱作外部數(shù)據(jù)區(qū)簡稱XDATA區(qū)。這個區(qū)通常包括一
24、些RAM 如SRAM 或一些需要通過總線接口的外圍器件。unsigned char xdata system_status=0;char xdata inp_string[16];,CODE區(qū) 程序存儲區(qū)稱為CODE區(qū),使用MOVC A,@DPTR 訪問。代碼段的數(shù)據(jù)是不可改變的8051 的代碼段不可重寫一般代碼段中可存放數(shù)據(jù)表、跳轉(zhuǎn)向量和狀態(tài)表。對CODE 段的訪問和對XDATA 段的訪問的時間是一樣的,代碼段中的對象在
25、編譯的時候初始化。unsigned int code unit_id=1234;unsigned char ch_array[16]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};,表3 C51存儲類型及其數(shù)據(jù)長度和值域,帶存儲類型的變量的定義的一般格式為 數(shù)
26、據(jù)類型 存儲類型 變量名;,帶存儲類型的變量定義舉例:char data var1;bit bdata flags;float idata x,y,z;unsigned int pdata var2;unsigned char vector[3][4];,表 4 存儲模式說明,4 MCS-51特殊功能寄存器(SFR)的C51定義,MCS-51單片機中,除了程序計數(shù)器PC和4組工作寄存器組外,
27、其它所有的寄存器均為特殊功能寄存器(SFR),分散在片內(nèi)RAM區(qū)的高128字節(jié)中,地址范圍為80H~0FFH。SFR中有11個寄存器具有位尋址能力,它們的字節(jié)地址都能被8整除,即字節(jié)地址是以8或0為尾數(shù)的。 為了能直接訪問這些SFR, C51提供了一種自主形式的定義方法,這種定義方法與標準C語言不兼容,只適用于對MCS-51系列單片機進行C語言編程。,特殊功能寄存器C51定義的一般語法格式如下:sfr sfr-nam
28、e = int constant; "sfr"是定義語句的關(guān)鍵字,其后必須跟一個MSC-51單片機真實存在的特殊功能寄存器名,"="后面必須是一個整型常數(shù),不允許帶有運算符的表達式,是特殊功能寄存器"sfr-name"的字節(jié)地址,這個常數(shù)值的范圍須在SFR地址范圍內(nèi),位于0x80~0xFF。 例如:sfr SCON=0x98; /* 串口控制寄存
29、器地址98H */sfr TMOD=0x89;/* 定時/計數(shù)器方式控制寄存器地址89H */,MCS-51系列單片機的特殊功能寄存器的數(shù)量與類型不盡相同,因此一般將所有特殊的"sfr"定義放入一個頭文件中,該文件應(yīng)包括MCS-51單片機系列機型中的SFR定義。C51編譯器的"reg51.h"頭文件就是這樣一個文件。 在新的MCS-51系列產(chǎn)品中,SFR在功能上經(jīng)常組合為16位值
30、,當SFR的高字節(jié)地址直接位于低字節(jié)之后時,對16位SFR的值可以直接進行訪問。如52子系列的定時器/計數(shù)器2就是這種情況。為了有效地訪問這類SFR,可使用關(guān)鍵字"sfr16"來定義,其定義語句的語法格式與8位SFR相同,只是"="后面的地址必須用16位SFR的低字節(jié)地址,即低字節(jié)地址作為"sfr16"的定義地址。,例如: sfr16 T2 = 0xCC /
31、*定時器/計數(shù)器2:T2低8位地址為0CCH,T2高8位地址為0CDH*/ 這種定義適用于所有新的16位SFR,但不能用于定時器/計數(shù)器0和1。 對于位尋址的SFR中的位,C51的擴充功能支持特殊位的定義,像SFR一樣不與標準C兼容,使用"sbit"來定義位尋址單元。,第一種格式: sbit bit-name = sfr-name^int constant; "
32、;sbit"是定義語句的關(guān)鍵字,后跟一個尋址位符號名(該位符號名必須是MCS-51單片機中規(guī)定的位名稱),"="后的"sfr-name"必須是已定義過的SFR的名字,"^"后的整常數(shù)是尋址位在特殊功能寄存器"sfr-name"中的位號,必須是0~7范圍中的數(shù)。例如: sfr PSW=0xD0 ;/* 定義PSW寄存器地址為D0H *
33、/ sbit OV=PSW^2 ;/* 定義OV位為PSW.2,地址為D2H */ sbit CY=PSW^7 ;/* 定義CY位為PSW.7,地址為D7H */,第二種格式:sbit bit-name = int constant^int constant; "="后的int constant為尋址地址位所在的特殊功能寄存器的字節(jié)地址,"^"符號后的i
34、nt constant為尋址位在特殊功能寄存器中的位號。例如: sbit OV=0XD0^2 ; /* 定義OV位地址是D0H字節(jié)中的第2位 */ sbit CY=0XD0^7 ; /* 定義CY位地址是D0H字節(jié)中的第7位 */,第三種格式:sbit bit-name = int constant; "="后的int con
35、stant為尋址位的絕對位地址。例如: sbit OV=0XD2 ;/* 定義OV位地址為D2H */ sbit CY=0XD7 ;/* 定義CY位地址為D7H */ 特殊功能位代表了一個獨立的定義類,不能與其它位定義和位域互換。,5 MCS-51并行接口的C51定義,MCS-51系列單片機并行I/O接口除了芯片上的4個I/O口(P0 ~ P3)外,還可以在片外擴展I/O口
36、。MCS-51單片機I/O口與數(shù)據(jù)存儲器統(tǒng)一編址,即把一個I/O口當作數(shù)據(jù)存儲器中的一個單元來看待。 使用C51進行編程時,MCS-51片內(nèi)的I/O口與片外擴展的I/O可以統(tǒng)一在一個頭文件中定義,也可以在程序中(一般在開始的位置)進行定義,其定義方法如下:,對于MCS-51片內(nèi)I/O口按特殊功能寄存器方法定義。如:sfr P0=0x80 ; /* 定義P0口,地址為80H */sfr P1=0x90 ; /* 定義
37、P1口,地址為90H */,對于片外擴展I/O口,則根據(jù)硬件譯碼地址,將其視作為片外數(shù)據(jù)存儲器的一個單元,使用#define語句進行定義。例如#include #define PORTA XBYTE [0xFFC0] absacc.h是C51中絕對地址訪問函數(shù)的頭文件,將PORTA定義為外部I/O口,地址為 FFC0H,長度為8位。 一旦在頭文件或程序中對這些片外I/O口進行定義后,在程序中就可以自由
38、使用變量名與其實際地址的聯(lián)系,以便使程序員能用軟件模擬MCS-51的硬件操作。,(1) 位變量C51定義。使用C51編程時,定義了位變量后,就可以用定義了的變量來表示MCS-51的位尋址單元。 位變量的C51定義的一般語法格式如下: 位類型標識符(bit) 位變量名; 例如:bit direction_bit ;/* 把direction_bit定義為位變量 */bi
39、t look_pointer ;/* 把look_pointer定義為位變量 */,6 位變量的C51定義,(2) 函數(shù)可包含類型為"bit"的參數(shù),也可以將其作為返回值。例如: bit func(bit b0, bit b1) /* 變量b0,b1作為函數(shù)的參數(shù) */ { return (b1); /* 變量b1作為函數(shù)的返回值 *
40、/ } 注意,使用(#pragma disable)或包含明確的寄存器組切換(using n)的函數(shù)不能返回位值,否則編輯器將會給出一個錯誤信息。,…,(3) 對位變量定義的限制。位變量不能定義成一個指針,如不能定義:bit * bit_pointer。不存在位數(shù)組,如不能定義:bit b_array[ ]。 在位定義中,允許定義存儲類型,位變量都被放入一個位段,此段總位于MCS-5
41、1片內(nèi)的RAM區(qū)中。因此,存儲類型限制為bdata和idata,如果將位變量的存儲類型定義成其它存儲類型都將編譯出錯。,例1 先定義變量的數(shù)據(jù)類型和存儲類型:bdata int ibase; /* 定義ibase為bdata整型變量 */bdata char bary[4]; /* bary[4]定義為bdata字符型數(shù)組 */然后可使用"sbit"定義可獨立尋址訪問的對象位:s
42、bit mybit0 = ibase^0 ; /* mybit0定義為ibase的第0位 */sbit mybit15 = ibase^15;/* mybit0定義為ibase的第15位 */sbit ary07 = bary[0]^7 ; /* Ary07定義為abry[0]的第7位 */sbit ary37 = bary[3]^7 ; /* Ary37定義為abry[3]的第7位 */,對象ibase和bary也可以
43、字節(jié)尋址: ary37=0; /* bary[3]的第7位賦值為0 */ bary[3]='a'; /* 字節(jié)尋址,bary[3] 賦值為'a' */ sbit定義要位尋址對象所在字節(jié)基址對象的存儲類型為"bdata",否則只有絕對的特殊位定義(sbit)是合法的。"^"操作符后的最大值依賴于指定的基類型,對于char/uchar而言是
44、0~7,對于int/uint而言是0~15,對于long/ulong而言是0~31。,7 C51構(gòu)造數(shù)據(jù)類型,7.1 基于存儲器的指針 基于存儲器的指針以存儲器類型為參量,它在編譯時才被確定。因此,為指針選擇存儲器的方法可以省掉,以便這些指針的長度為一個字節(jié)(idata *,data *,pdata *)或2個字節(jié)(code *,xdata *)。編譯時,這類操作一般被"行內(nèi)"(inline)編碼
45、,而無需進行庫調(diào)用。 基于存儲器的指針定義舉例: char xdata *px;,在xdata存儲器中定義了一個指向字符型(char)的指針變量px。指針自身在默認存儲區(qū)(決定于編譯模式),長度為2個字節(jié)(值為0~0xFFFF)。 char data * pdx; 除了明確定義指針位于MCS-51內(nèi)部存儲區(qū)(data)外,其它與上例相同,它與編譯模式無關(guān)。
46、 char xdata *data pdx;,struct time { char hour ; char min; char sec; struct time xdata *pxtime; } 在結(jié)構(gòu)struct time中,除了其它結(jié)構(gòu)成員外,還包含有一個具有和struct time相同的指針pxtime,time位于外部數(shù)據(jù)
47、存儲器(xdata),指針pxtime具有兩個字節(jié)長度。,struct time idata *ptime ; 這個聲明定義了一個位于默認存儲器中的指針,它指向結(jié)構(gòu)time,time位于idata存儲器中,結(jié)構(gòu)成員可以通過MCS-51的@R0或@R1 進行間接訪問,指針ptime為1個字節(jié)長。 ptime→pxtime→hour = 12; 使用上面的關(guān)于struct time和struct
48、 idata *ptime的定義,指針"pxtime"被從結(jié)構(gòu)中間接調(diào)用,它指向位于xdata存儲器中的time結(jié)構(gòu)。結(jié)構(gòu)成員hour被賦值為12。,7.2一般指針 一般指針包括3個字節(jié):1個字節(jié)存儲類型和2個字節(jié)偏移地址,即,其中,第一字節(jié)代表了指針的存儲器類型,存儲器類型編碼如下:,例如,以xdata類型的0x1234地址為指針可以表示如下:,當用常數(shù)作指針時,必須注意正確定義存儲器類型和偏移量。 例
49、如,將常數(shù)值0x41寫入地址為0x8000的外部數(shù)據(jù)存儲器。 #define XBYTE ( (char *) 0x20000L) XBYTE[0x8000] = 0x41 ; 其中,XBYTE被定義為(char *)0x20000L,0x20000L為一般指針,其存儲類型為2,偏移量為0000H,這樣XBYTE成為指向xdata零地址的指針。而XBYTE[8000]則是外部數(shù)據(jù)存儲器的0x80
50、00絕對地址。,8 模塊化程序開發(fā)過程,圖4 程序開發(fā)過程,C51 程序開發(fā)過程,8.1 混合編程,1.命名規(guī)則,表5 函數(shù)名的轉(zhuǎn)換,例2 用匯編語言編寫函數(shù)"toupper",參數(shù)傳遞發(fā)生在寄存器R7中。UPPER SEGMENT CODE ;程序段PUBLIC _TOUPPER ;入口地址PSEG UPPER
51、 ; 程序段_TOUPPER: MOV A,R7 ;從R7中取參數(shù) CJNE A,# 'a',$+3 JC UPPERET CJNE A, # 'z'+1 ,$+3 JNC UP
52、PERET CLR ACC ,5 UPPERET:MOV R7 ,A ;返回值放在R7中 RET ;返回到C,2.參數(shù)傳遞規(guī)則,表6 參數(shù)傳遞的寄存器選擇,func1(int a) "a"是第一個參數(shù),在R6,R7中傳遞。
53、 func2 (int b, int c, int *d ) "b"是第一個參數(shù),在R6,R7中傳遞;"c"是第二個參數(shù),在R4,R5中傳遞;"d"是第三個參數(shù),在R1,R2,R3中傳遞。 func3(long e , long f ) "e"是第一個參數(shù),在R4~R7中傳遞;"f"是第二個參數(shù),不能在寄存器中傳
54、遞,只能在參數(shù)傳遞段中傳遞。 func4(float g , char h ) "g"是第一個參數(shù),在R4~R7中傳遞;"h"是第二個參數(shù),必須在參數(shù)傳遞段中傳遞。,表7 函數(shù)返回值的寄存器,在匯編子程序中,當前選擇的寄存器組及寄存器ACC、B、DPTR和PSW都可能改變。當被C調(diào)用時,必須無條件地假設(shè)這些寄存器的內(nèi)容已被破壞。如果已在連接/定位程序時選擇了覆蓋,那么每個匯編子
55、程序包含一個單獨的程序段是必要的,因為在覆蓋過程中,函數(shù)間參量通過子程序各自的段參量計算。匯編子程序的數(shù)據(jù)區(qū)甚至可包含在覆蓋部分中,但應(yīng)注意下面兩點: (1) 所有段名必須以C51類似的方法建立。 (2) 每個有局部變量的匯編程序必須指定自己的數(shù)據(jù)段,這個數(shù)據(jù)段只能為其它函數(shù)訪問作參數(shù)傳遞用。所有參數(shù)一個接一個被傳遞,由其它函數(shù)計算的結(jié)果保存入棧。,8.2 覆蓋和共享,1.覆蓋 單片機片內(nèi)存儲
56、空間有限,連接器/定位器通常重新啟用程序不再用的位置。這就是說,若一個程序不再調(diào)用,也不由其它程序調(diào)用(甚至間接調(diào)用),那么在其它程序執(zhí)行完之前,這個程序不再運行。這個程序的變量可以放在與其它程序完全相同的RAM空間,很像可重用的寄存器。這種技術(shù)就是覆蓋。在匯編中直接通過手工完成的這些空間分配,C語言中可以由連接器自動管理。若有幾個不相關(guān)聯(lián)的程序時,它可以使RAM單元比手工考慮要用的少。,2.共享1) 共享變量,2) 共享函數(shù)/子程序
57、 C中函數(shù)若是全局的(公用的),可以放在調(diào)用的函數(shù)之后。若函數(shù)是模塊專用的,它可以定義為靜態(tài)函數(shù),這樣它不能被其它模塊調(diào)用。C語言的ANSI標準建議所有函數(shù)在主函數(shù)前要有原型(進行說明),然后實際函數(shù)可在主函數(shù)之后或其它模塊中。 匯編語言中,子程序使用標號可在給定模塊的任何位置。匯編器首先掃描得到所有的符號名,然后值就可填入LCALL或LJMP。一個模塊或另一模塊共享子程序,一個使用PUBLIC而另一個使用
58、EXTERN。當指定為EXTERN,符號類型(CODE,DATA,XDATA,IDATA,BIT或NUMBER)必須特別加以指定,以便連接器可以確定放在一起的正確類型。,8.3 庫和連接器/定位器 1. 庫,表 9 C51的編譯庫,2.連接器/定位器 1) 組合程序模塊 將幾個不同程序模塊組合為一個模塊,并自動從庫中挑選模塊嵌入目標文件。輸入文件按命令行中出現(xiàn)的順序處理。通常的程序模塊
59、是由C51編譯器或A51宏匯編生成的可重入的目標文件。,2) 組合段 將具有相同段名的可重定位段組合成單一的段。在一個程序模塊中定義的一個段成為部分段。一個部分段在源文件中以下列形式指定: (1) 名字 每個重定位段有一個名字,它可與來自其它模塊的同名的可重定位段組合。絕對段沒有名字。 (2) 類型 類型表明段所屬的地址空間CODE,XDATA,DATA或BIT。,(3) 定位方式 可重定位
60、段的定位方式有PAGE,INPAGE,INBLOCK,BITADD RESSABLE或UNIT。INPAGE表明段必須放入一頁(高8位地址相同)中以使用短轉(zhuǎn)移和調(diào)用指令。INBLOCK段應(yīng)使用ACALL,必須放在2048字節(jié)塊中。因為沒有連接器可以靈活地判知調(diào)用和轉(zhuǎn)移是否在塊內(nèi)。可重定位的其它限制是:PAGE--不能超過256字節(jié);BITADDRESSABLE--必須放在可位尋址的內(nèi)部RAM空間;UNIT--允許段從任意字節(jié)開始(對位變
61、量是位)。 (4) 長度 一個段的長度。,(5) 基址 段的首址。對于絕對段,地址由匯編器賦予,對于可重定位段,地址由L51決定。在處理程序模塊時,L51自動產(chǎn)生段表(MAP),該表包含了每個段的類型、基址、長度、可重定位性和名字。 L51自動將所具有相同名字的所有部分段組合到單一可重定位段中。例如,三個程序模塊包含字段VAR,在組合時,三個段的長度相加,從而組合段的長度也增加了。,對組合段有下列規(guī)則:
62、① 所有具有相同名的部分段必須有相同類型 (CODE,DATA,IDATA,XDATA或BIT)。 ② 組合段的長度不能超過存儲區(qū)的物理長度。 ③ 每個組合的部分段的定位方法也必須相同。 ④ 絕對段相互不組合,它們被直接拷貝到輸出文件。,3) 存儲器分配,表10 MCS-51系列的物理存儲區(qū),4) 采用覆蓋技術(shù)使用數(shù)據(jù)存儲器 通過采用一定的覆蓋技術(shù),M
63、CS-51系列少量的片內(nèi)數(shù)據(jù)存儲器可由L51有效地使用。由C51編譯器或是A51匯編器生成的參數(shù)和局部變量(若使用它們的函數(shù)不相互調(diào)用)可在存儲器中覆蓋。這樣,所用的存儲器得到相當程度地減少。 為完成數(shù)據(jù)覆蓋,L51分析所有不同函數(shù)間的調(diào)用,使用該信息可以確定哪個數(shù)據(jù)和位段可被覆蓋。使用控制參數(shù)OVERLAY和NOOVERLAY可允許或禁止覆蓋。OVERLAY是默認值,用它可產(chǎn)生非常緊湊的數(shù)據(jù)區(qū)。,5) 決定外部參考地址
64、 具有相同名的外部符號(EXTERN)和公用符號(PUBLIC)被確定后,外部符號指向其它模塊中的地址。一個已聲明的外部符號用具有相同名字的功用符號確定,外部參考地址由其公共參考地址確定。這還與類型(DATA,IDATA,XDATA,CODE,BIT或NUMBER)有關(guān),如果類型不符或未發(fā)現(xiàn)外部符號參考地址的公用符號,則會產(chǎn)生錯誤。公用符號的絕對地址在段定位后決定。,6) 絕對地址計算 定義絕對地址并計算可重定
65、位段的地址。在段分配和外部公用參考地址處理完后,程序模塊中所有可重定位地址和外部地址要進行計算,此時生成的目標文件中的符號信息(DEBUG)被改變以反映新的值。,7) 產(chǎn)生絕對目標文件 可執(zhí)行程序以絕對目標格式產(chǎn)生。該絕對目標文件可包含附加的符號信息(DEBUG),從而使符號調(diào)試成為可能。符號信息可用參數(shù)NODEBUGSYMBOLS,NODEBUGPUBLICS和NODEBUGLINES禁止。輸出文件是可執(zhí)行的,并可由仿真
66、器裝入調(diào)試或被OHS51翻譯為Intel HEX格式文件以供EPROM固化。,8) 產(chǎn)生映像文件 產(chǎn)生一個反映每個處理步驟的映像文件,它顯示有關(guān)連接/定位過程的信息和程序符號,并包含一個公用和外部符號的交叉參考報告。映像文件包含下列信息: ① 文件名和命令行參數(shù)。 ② 模塊的文件名和模塊名。 ③ 一個包含段地址、類型、定位方法和名字的存儲器分配表。該表可在命令行中用NOMA
67、P參考禁止。 ④ 段和符號的所有錯誤列表。列表文件末尾顯示出所有出錯的原因。,⑤ 一個包含輸入文件中符號信息的符號表。該信息由MODULES,SYMBOLS,PUBLICS和LINES名組成,LINES是C編譯器產(chǎn)生的行號。符號信息可用參數(shù)NOSYMBOLS,NOPUBLICS和NOLINES完全或部分禁止。 ⑥ 一個按字母順序排列的有關(guān)所有PUBLIC和EXTERN符號的交叉參考報告,其中顯示出符號類
68、型和模塊名。第一個顯示的模塊名是定義了PUBLIC符號的模塊,后面的模塊名是定義了EXTERN符號的模塊。在命令行輸入?yún)?shù)IXREF可產(chǎn)生此報告。 ⑦ 在連接器/定位器運行期間檢測到的錯誤同時顯示在屏幕和文件尾部。,8.4 程序優(yōu)化,以下選擇對提高程序效率有很大影響: (1) 盡量選擇小存儲模式以避免使用MOVX指令。 (2) 使用大模式(COMPACT/LARGE)應(yīng)仔細考慮要放在內(nèi)部數(shù)據(jù)
69、存儲器的變量要求是經(jīng)常用的或是用于中間結(jié)果的。訪問內(nèi)部數(shù)據(jù)存儲器要比訪問外部數(shù)據(jù)存儲器快得多。內(nèi)部RAM由寄存器組、位數(shù)據(jù)區(qū)和其它用戶用“data”類型定義的變量共享。由于內(nèi)部RAM容量的限制(128~256字節(jié),由使用的單片機決定),必須權(quán)衡利弊以解決訪問效率和這些對象的數(shù)量之間的矛盾。,(3) 要考慮操作順序,完成一件事后再做一件事。 (4) 注意程序編寫細則。例如,若使用for(;;)循環(huán),DJNZ指令比CJNE指令
70、更有效,可減少重復(fù)循環(huán)次數(shù)。 (5) 若編譯器不能使用左移和右移完成乘除法,應(yīng)立即修改,例如,左移為乘2。 (6) 用邏輯AND/&取模比用MOD / %操作更有效。 (7) 因計算機基于二進制,仔細選擇數(shù)據(jù)存儲器和數(shù)組大小可節(jié)省操作。,(8) 盡可能使用最小的數(shù)據(jù)類型,MCS-51系列是8位機,顯然對具有"char"類型的對象的操作比"int"或
71、"long"類型的對象的操作要方便得多。 (9) 盡可能使用"unsigned"數(shù)據(jù)類型。MCS-51系列CPU并不直接支持有符號數(shù)的運算。因而C51編譯器必須產(chǎn)生與之相關(guān)的更多的程序代碼以解決這個問題。 (10) 盡可能使用局部函數(shù)變量。編譯器總是嘗試在寄存器里保持局部變量。這樣,將循環(huán)變量(如for和while循環(huán)中的計數(shù)變量)說明為局部變量是最好的。使用&quo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 51單片機c語言程序設(shè)計源代碼
- avr單片機c語言程序設(shè)計實驗指導(dǎo)書
- 單片機匯編語言及程序設(shè)計
- 80c51的c語言程序設(shè)計教學(xué)課件ppt單片機
- 《單片機c程序設(shè)計》實驗報告
- 單片機c語言程序的結(jié)構(gòu)和設(shè)計
- 51單片機脈沖產(chǎn)生程序設(shè)計
- stc新型單片機的isp程序設(shè)計
- 《單片機c語言程序設(shè)計實訓(xùn) 100 例—基于 8051+proteus仿真》案例
- 單片機c語言程序設(shè)計實訓(xùn)100例--基于8051-proteus仿真1
- 單片機點陣可移位顯示程序c語言
- 基于51單片機的頻率計設(shè)計,c語言程序
- 基于at89s52單片機的電機控制c語言程序設(shè)計畢業(yè)論文
- 單片機原理與c51程序設(shè)計--chap07
- 單片機原理與c51程序設(shè)計--chap03
- 單片機原理與c51程序設(shè)計--chap11
- 基于c語言單片機秒表設(shè)計
- 51單片機100例程序設(shè)計
- 《c語言程序設(shè)計》
- c語言程序設(shè)計
評論
0/150
提交評論