2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩78頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第5章 單片機(jī)的C語言程序設(shè)計(jì),1 C語言與MCS-512 C51數(shù)據(jù)類型及在MCS-51中的存儲(chǔ)方式3 C51數(shù)據(jù)的存儲(chǔ)類型與MCS-51存儲(chǔ)結(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)點(diǎn),編譯器能自動(dòng)完成變量的存儲(chǔ)單元的分配,編程者可以

2、專注于應(yīng)用軟件的設(shè)計(jì),可以對(duì)常用的接口芯片編制通用的驅(qū)動(dòng)函數(shù),對(duì)常用的功能模塊和算法編制相應(yīng)的函數(shù),可以方便地進(jìn)行信號(hào)處理算法和程序的移植,從而加快單片機(jī)應(yīng)用系統(tǒng)的開發(fā)速度。 當(dāng)代碼長度超過4KB以上時(shí),C51比匯編語言更具有明顯的優(yōu)勢(shì)。,C-51與ASM-51相比,有如下優(yōu)點(diǎn):1.  對(duì)單片機(jī)的指令系統(tǒng)不要求了解,僅要求對(duì)8051 的存貯器結(jié)構(gòu)有初步了解;2.  寄存器分配、

3、不同存貯器的尋址及數(shù)據(jù)類型等細(xì)節(jié)可由編譯器管理;3.  程序有規(guī)范的結(jié)構(gòu),可分成不同的函數(shù),這種方式可使程序結(jié)構(gòu)化;,4.  具有將可變的選擇與特殊操作組合在一起的能力,改善了程序的可讀性;5.  提供的庫包含許多標(biāo)準(zhǔn)子程序,具有較強(qiáng)的數(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個(gè)字節(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個(gè)字節(jié) MOV R1,#00H MOV DPTR,#2000HL11: MOVX A,@DPTR CJNE A,#00H,L16 ;取出內(nèi)

7、容與00H相等嗎? INC R1 ;取出個(gè)數(shù)加1L16: INC DPTR DJNZ R0,L11 ;未完繼續(xù) MOV DPTR,#2100H MOV A,R1 MOVX @DPTR,A ;相同數(shù)個(gè)數(shù)送2100HL1E: SJMP L1E END,例:查找零的個(gè)數(shù)(在2000H--200FH中查出有幾個(gè)字節(jié)是零,把個(gè)數(shù)放在210

8、0H單元中),★查找零的個(gè)數(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; /* 把個(gè)數(shù)放在2100H單元中 */},1 C語言與MCS–51,用匯編語言編程時(shí),必須要考慮其存儲(chǔ)器結(jié)構(gòu),尤其必須考慮其片內(nèi)數(shù)據(jù)存儲(chǔ)器與特殊功能寄存器正確、合理的使用以及按實(shí)際地址處理端口數(shù)據(jù)。 用C語言編程中,對(duì)數(shù)據(jù)類型與變量的定義,必須要與單片機(jī)的存儲(chǔ)結(jié)構(gòu)相關(guān)聯(lián),否

10、則編譯器不能正確地映射定位。 用C語言編寫單片機(jī)程序與標(biāo)準(zhǔn)C語言程序的不同之處就在于根據(jù)單片機(jī)存儲(chǔ)結(jié)構(gòu)及內(nèi)部資源定義相應(yīng)的C語言中的數(shù)據(jù)類型和變量。,用C語言編寫的應(yīng)用程序必須經(jīng)單片機(jī)的C語言編譯器(簡稱C51),轉(zhuǎn)換生成單片機(jī)可執(zhí)行的代碼程序?,F(xiàn)在支持MCS–51系列單片機(jī)的C語言編譯器有很多種。 如American Automation、Auocet、BSO/TASKING、DUNFIELD SHAREWARE

11、、KEIL/Franklin等。 其中KEIL/Franklin以它的代碼緊湊和使用方便等特點(diǎn)優(yōu)于其它編譯器。本章是針對(duì)這種編譯器介紹 MCS–51單片機(jī)C語言程序設(shè)計(jì)。,2 C51數(shù)據(jù)類型及在MCS-51中的存儲(chǔ)方式,2.1 C51的數(shù)據(jù)類型 KEIL/Franklin C51編譯器支持的數(shù)據(jù)類型有:位型(bit)、無符號(hào)字符(unsigned char)、有符號(hào)字符(singed char)、無符號(hào)整型

12、(unsigned int )、有符號(hào)整型(signed int )、無符號(hào)長整型(unsigned long )、有符號(hào)長整型(signed long )、浮點(diǎn)型(float)和指針類型等。,表.1 C51的數(shù)據(jù)類型,2.2 C51數(shù)據(jù)在MCS-51中的存儲(chǔ)方式,位變量(bit):與MCS-51硬件特性操作有關(guān)的可定義成位變量。位變量必須定位在MCS-51單片機(jī)片內(nèi)RAM的位尋址空間中。 字符變量(char):字符變量的長度為

13、1 字節(jié)即8位。對(duì)于無符號(hào)變量(unsigned char)的值域范圍是0~255。對(duì)于有符號(hào)字符變量(signed char),最具有重要意義的位是最高位上的符號(hào)標(biāo)志位(msb)。此位為1代表"負(fù)",為0代表"正"。有符號(hào)字符變量和無符號(hào)字符變量在表示0~127的數(shù)值時(shí),其含義是一樣的,都是0~0x7F。負(fù)數(shù)一般用補(bǔ)碼表示,即用11111111表示-1, 用11111110表示-2……。,整型變

14、量(int): 整型變量的長度為16位。MCS-51系列單片機(jī)將int型變量的高位字節(jié)數(shù)存放在低地址字節(jié)中,低位字節(jié)數(shù)存放在高地址字節(jié)中。有符號(hào)整型變量(signed int)也使用msb位作符號(hào)標(biāo)志位,并使用二進(jìn)制補(bǔ)碼表示數(shù)值??芍苯邮褂脦追N專用的機(jī)器指令來完成多字節(jié)的加、減、乘、除運(yùn)算。整型變量值0x1234以圖1所示的方式存放在內(nèi)存中。,圖1 整型數(shù)的存儲(chǔ)結(jié)構(gòu),+0+1,地址,+0+1+2+3,地址,圖2 長整型變量的

15、存儲(chǔ)結(jié)構(gòu),浮點(diǎn)型變量(float): 浮點(diǎn)型變量為32位,占4個(gè)字節(jié),許多復(fù)雜的數(shù)學(xué)表達(dá)式都采用浮點(diǎn)變量數(shù)據(jù)類型。用符號(hào)位表示數(shù)的符號(hào),用階碼和尾數(shù)表示數(shù)的大小。 用它們進(jìn)行任何數(shù)學(xué)運(yùn)算都需要使用由編譯器決定的各種不同效率等級(jí)的庫函數(shù)。C51的浮點(diǎn)變量數(shù)據(jù)類型的使用格式與IEEE-754標(biāo)準(zhǔn)有關(guān),具有24位精度,尾數(shù)的高位始終為"1",因而不保存,位的分布如下:● 1位符號(hào)位?!?8位指數(shù)位?!?/p>

16、 23位尾數(shù)。,符號(hào)位是最高位,尾數(shù)為低23位,內(nèi)存中按字節(jié)存儲(chǔ)順序如下:,其中,S為符號(hào)位,1表示負(fù),0表示正;E為階碼;M為23位尾數(shù),最高位為"1"。 浮點(diǎn)變量值 -12.5的十進(jìn)制為:0xC1480000,它按圖3所示方式存于內(nèi)存中。,+0+1+2+3,地址,圖3 浮點(diǎn)數(shù)的存儲(chǔ)結(jié)構(gòu),在編程時(shí),如果只強(qiáng)調(diào)運(yùn)算速度而不進(jìn)行負(fù)數(shù)運(yùn)算時(shí),最好采用無符號(hào)(unsigned)格式。

17、 無符號(hào)字符類型的使用:無論何時(shí),應(yīng)盡可能使用無符號(hào)字符變量,因?yàn)樗苤苯颖籑CS-51所接受?;谕瑯拥脑颍矐?yīng)盡量使用位變量。有符號(hào)字符變量雖然也只占用一個(gè)字節(jié),但需要進(jìn)行額外的操作來進(jìn)行測(cè)試代碼的符號(hào)位。,使用簡化形式定義數(shù)據(jù)類型。其方法是在源程序開頭使用#define語句自定義簡化的類型標(biāo)識(shí)符。例如:#define uchar unsigned char #define uint unsigned in

18、t 這樣,在編程中,就可以用uchar代替unsigned char,用uint代替unsigned int來定義變量。,3 C51數(shù)據(jù)的存儲(chǔ)類型與MCS-51存儲(chǔ)結(jié)構(gòu),表 2 C51存儲(chǔ)類型與MCS-51存儲(chǔ)空間的對(duì)應(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ū)。指令用一個(gè)或兩個(gè)周期來訪問數(shù)據(jù)段?!?數(shù)據(jù)段中有兩

19、個(gè)小段,第一個(gè)子段包含四組寄存器組。另外一個(gè)子段叫做位尋址段BDATA,包括16 個(gè)字節(jié)共128 位每一位都可單獨(dú)尋址?!?對(duì)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ū)單片機(jī)內(nèi)部RAM的位尋址區(qū)叫做位尋址段BDATA區(qū), 包括16 個(gè)字節(jié)共128位??梢栽贒ATA 區(qū)的位尋址區(qū)定義變量(非浮點(diǎn)型) ,這個(gè)變量就可進(jìn)行位尋址,并且可以聲明位變量。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 系列的一些單片機(jī)如8052有附加的128字節(jié)的內(nèi)部RAM, 位于從80H開始的地址空間中,這部分加上低128字節(jié)的內(nèi)部RAM共256字節(jié),被稱為IDATA。因?yàn)镮DATA區(qū)的地址和SFR的地址是重疊的,通過區(qū)分所訪問

22、的存儲(chǔ)區(qū)來解決地址重疊問題,因此IDATA 區(qū)只能通過間接尋址來訪問. IDATA 段也可存放使用比較頻繁的變量,使用寄存器作為指針進(jìn)行尋址,在寄存器中設(shè)置8 位地址進(jìn)行間接尋址。和外部存儲(chǔ)器尋址比較,它的指令執(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ū) 外部存儲(chǔ)區(qū)的最低地址的256個(gè)字節(jié),稱為PDATA區(qū)。通過P0口的地址對(duì)其尋址,使用指令MOVX @Rn,需要兩個(gè)指令周期。unsigned int pdata unit_id[2];float pdata outp_value;,XDATA區(qū) 8051單片機(jī)的外部RAM,存儲(chǔ)空間為64K,采用16 位地址尋址稱作外部數(shù)據(jù)區(qū)簡稱XDATA區(qū)。這個(gè)區(qū)通常包括一

24、些RAM 如SRAM 或一些需要通過總線接口的外圍器件。unsigned char xdata system_status=0;char xdata inp_string[16];,CODE區(qū) 程序存儲(chǔ)區(qū)稱為CODE區(qū),使用MOVC A,@DPTR 訪問。代碼段的數(shù)據(jù)是不可改變的8051 的代碼段不可重寫一般代碼段中可存放數(shù)據(jù)表、跳轉(zhuǎn)向量和狀態(tài)表。對(duì)CODE 段的訪問和對(duì)XDATA 段的訪問的時(shí)間是一樣的,代碼段中的對(duì)象在

25、編譯的時(shí)候初始化。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存儲(chǔ)類型及其數(shù)據(jù)長度和值域,帶存儲(chǔ)類型的變量的定義的一般格式為 數(shù)

26、據(jù)類型 存儲(chǔ)類型 變量名;,帶存儲(chǔ)類型的變量定義舉例:char data var1;bit bdata flags;float idata x,y,z;unsigned int pdata var2;unsigned char vector[3][4];,表 4 存儲(chǔ)模式說明,4 MCS-51特殊功能寄存器(SFR)的C51定義,MCS-51單片機(jī)中,除了程序計(jì)數(shù)器PC和4組工作寄存器組外,

27、其它所有的寄存器均為特殊功能寄存器(SFR),分散在片內(nèi)RAM區(qū)的高128字節(jié)中,地址范圍為80H~0FFH。SFR中有11個(gè)寄存器具有位尋址能力,它們的字節(jié)地址都能被8整除,即字節(jié)地址是以8或0為尾數(shù)的。 為了能直接訪問這些SFR, C51提供了一種自主形式的定義方法,這種定義方法與標(biāo)準(zhǔn)C語言不兼容,只適用于對(duì)MCS-51系列單片機(jī)進(jìn)行C語言編程。,特殊功能寄存器C51定義的一般語法格式如下:sfr sfr-nam

28、e = int constant; "sfr"是定義語句的關(guān)鍵字,其后必須跟一個(gè)MSC-51單片機(jī)真實(shí)存在的特殊功能寄存器名,"="后面必須是一個(gè)整型常數(shù),不允許帶有運(yùn)算符的表達(dá)式,是特殊功能寄存器"sfr-name"的字節(jié)地址,這個(gè)常數(shù)值的范圍須在SFR地址范圍內(nèi),位于0x80~0xFF。 例如:sfr SCON=0x98; /* 串口控制寄存

29、器地址98H */sfr TMOD=0x89;/* 定時(shí)/計(jì)數(shù)器方式控制寄存器地址89H */,MCS-51系列單片機(jī)的特殊功能寄存器的數(shù)量與類型不盡相同,因此一般將所有特殊的"sfr"定義放入一個(gè)頭文件中,該文件應(yīng)包括MCS-51單片機(jī)系列機(jī)型中的SFR定義。C51編譯器的"reg51.h"頭文件就是這樣一個(gè)文件。 在新的MCS-51系列產(chǎn)品中,SFR在功能上經(jīng)常組合為16位值

30、,當(dāng)SFR的高字節(jié)地址直接位于低字節(jié)之后時(shí),對(duì)16位SFR的值可以直接進(jìn)行訪問。如52子系列的定時(shí)器/計(jì)數(shù)器2就是這種情況。為了有效地訪問這類SFR,可使用關(guān)鍵字"sfr16"來定義,其定義語句的語法格式與8位SFR相同,只是"="后面的地址必須用16位SFR的低字節(jié)地址,即低字節(jié)地址作為"sfr16"的定義地址。,例如: sfr16 T2 = 0xCC /

31、*定時(shí)器/計(jì)數(shù)器2:T2低8位地址為0CCH,T2高8位地址為0CDH*/ 這種定義適用于所有新的16位SFR,但不能用于定時(shí)器/計(jì)數(shù)器0和1。 對(duì)于位尋址的SFR中的位,C51的擴(kuò)充功能支持特殊位的定義,像SFR一樣不與標(biāo)準(zhǔn)C兼容,使用"sbit"來定義位尋址單元。,第一種格式: sbit bit-name = sfr-name^int constant; "

32、;sbit"是定義語句的關(guān)鍵字,后跟一個(gè)尋址位符號(hào)名(該位符號(hào)名必須是MCS-51單片機(jī)中規(guī)定的位名稱),"="后的"sfr-name"必須是已定義過的SFR的名字,"^"后的整常數(shù)是尋址位在特殊功能寄存器"sfr-name"中的位號(hào),必須是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é)地址,"^"符號(hào)后的i

34、nt constant為尋址位在特殊功能寄存器中的位號(hào)。例如: 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為尋址位的絕對(duì)位地址。例如: sbit OV=0XD2 ;/* 定義OV位地址為D2H */ sbit CY=0XD7 ;/* 定義CY位地址為D7H */ 特殊功能位代表了一個(gè)獨(dú)立的定義類,不能與其它位定義和位域互換。,5 MCS-51并行接口的C51定義,MCS-51系列單片機(jī)并行I/O接口除了芯片上的4個(gè)I/O口(P0 ~ P3)外,還可以在片外擴(kuò)展I/O口

36、。MCS-51單片機(jī)I/O口與數(shù)據(jù)存儲(chǔ)器統(tǒng)一編址,即把一個(gè)I/O口當(dāng)作數(shù)據(jù)存儲(chǔ)器中的一個(gè)單元來看待。 使用C51進(jìn)行編程時(shí),MCS-51片內(nèi)的I/O口與片外擴(kuò)展的I/O可以統(tǒng)一在一個(gè)頭文件中定義,也可以在程序中(一般在開始的位置)進(jìn)行定義,其定義方法如下:,對(duì)于MCS-51片內(nèi)I/O口按特殊功能寄存器方法定義。如:sfr P0=0x80 ; /* 定義P0口,地址為80H */sfr P1=0x90 ; /* 定義

37、P1口,地址為90H */,對(duì)于片外擴(kuò)展I/O口,則根據(jù)硬件譯碼地址,將其視作為片外數(shù)據(jù)存儲(chǔ)器的一個(gè)單元,使用#define語句進(jìn)行定義。例如#include #define PORTA XBYTE [0xFFC0] absacc.h是C51中絕對(duì)地址訪問函數(shù)的頭文件,將PORTA定義為外部I/O口,地址為 FFC0H,長度為8位。 一旦在頭文件或程序中對(duì)這些片外I/O口進(jìn)行定義后,在程序中就可以自由

38、使用變量名與其實(shí)際地址的聯(lián)系,以便使程序員能用軟件模擬MCS-51的硬件操作。,(1) 位變量C51定義。使用C51編程時(shí),定義了位變量后,就可以用定義了的變量來表示MCS-51的位尋址單元。 位變量的C51定義的一般語法格式如下: 位類型標(biāo)識(shí)符(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ù)不能返回位值,否則編輯器將會(huì)給出一個(gè)錯(cuò)誤信息。,…,(3) 對(duì)位變量定義的限制。位變量不能定義成一個(gè)指針,如不能定義:bit * bit_pointer。不存在位數(shù)組,如不能定義:bit b_array[ ]。 在位定義中,允許定義存儲(chǔ)類型,位變量都被放入一個(gè)位段,此段總位于MCS-5

41、1片內(nèi)的RAM區(qū)中。因此,存儲(chǔ)類型限制為bdata和idata,如果將位變量的存儲(chǔ)類型定義成其它存儲(chǔ)類型都將編譯出錯(cuò)。,例1 先定義變量的數(shù)據(jù)類型和存儲(chǔ)類型:bdata int ibase; /* 定義ibase為bdata整型變量 */bdata char bary[4]; /* bary[4]定義為bdata字符型數(shù)組 */然后可使用"sbit"定義可獨(dú)立尋址訪問的對(duì)象位: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位 */,對(duì)象ibase和bary也可以

43、字節(jié)尋址: ary37=0; /* bary[3]的第7位賦值為0 */ bary[3]='a'; /* 字節(jié)尋址,bary[3] 賦值為'a' */ sbit定義要位尋址對(duì)象所在字節(jié)基址對(duì)象的存儲(chǔ)類型為"bdata",否則只有絕對(duì)的特殊位定義(sbit)是合法的。"^"操作符后的最大值依賴于指定的基類型,對(duì)于char/uchar而言是

44、0~7,對(duì)于int/uint而言是0~15,對(duì)于long/ulong而言是0~31。,7 C51構(gòu)造數(shù)據(jù)類型,7.1 基于存儲(chǔ)器的指針 基于存儲(chǔ)器的指針以存儲(chǔ)器類型為參量,它在編譯時(shí)才被確定。因此,為指針選擇存儲(chǔ)器的方法可以省掉,以便這些指針的長度為一個(gè)字節(jié)(idata *,data *,pdata *)或2個(gè)字節(jié)(code *,xdata *)。編譯時(shí),這類操作一般被"行內(nèi)"(inline)編碼

45、,而無需進(jìn)行庫調(diào)用。 基于存儲(chǔ)器的指針定義舉例: char xdata *px;,在xdata存儲(chǔ)器中定義了一個(gè)指向字符型(char)的指針變量px。指針自身在默認(rèn)存儲(chǔ)區(qū)(決定于編譯模式),長度為2個(gè)字節(jié)(值為0~0xFFFF)。 char data * pdx; 除了明確定義指針位于MCS-51內(nèi)部存儲(chǔ)區(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)成員外,還包含有一個(gè)具有和struct time相同的指針pxtime,time位于外部數(shù)據(jù)

47、存儲(chǔ)器(xdata),指針pxtime具有兩個(gè)字節(jié)長度。,struct time idata *ptime ; 這個(gè)聲明定義了一個(gè)位于默認(rèn)存儲(chǔ)器中的指針,它指向結(jié)構(gòu)time,time位于idata存儲(chǔ)器中,結(jié)構(gòu)成員可以通過MCS-51的@R0或@R1 進(jìn)行間接訪問,指針ptime為1個(gè)字節(jié)長。 ptime→pxtime→hour = 12; 使用上面的關(guān)于struct time和struct

48、 idata *ptime的定義,指針"pxtime"被從結(jié)構(gòu)中間接調(diào)用,它指向位于xdata存儲(chǔ)器中的time結(jié)構(gòu)。結(jié)構(gòu)成員hour被賦值為12。,7.2一般指針 一般指針包括3個(gè)字節(jié):1個(gè)字節(jié)存儲(chǔ)類型和2個(gè)字節(jié)偏移地址,即,其中,第一字節(jié)代表了指針的存儲(chǔ)器類型,存儲(chǔ)器類型編碼如下:,例如,以xdata類型的0x1234地址為指針可以表示如下:,當(dāng)用常數(shù)作指針時(shí),必須注意正確定義存儲(chǔ)器類型和偏移量。 例

49、如,將常數(shù)值0x41寫入地址為0x8000的外部數(shù)據(jù)存儲(chǔ)器。 #define XBYTE ( (char *) 0x20000L) XBYTE[0x8000] = 0x41 ; 其中,XBYTE被定義為(char *)0x20000L,0x20000L為一般指針,其存儲(chǔ)類型為2,偏移量為0000H,這樣XBYTE成為指向xdata零地址的指針。而XBYTE[8000]則是外部數(shù)據(jù)存儲(chǔ)器的0x80

50、00絕對(duì)地址。,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"是第一個(gè)參數(shù),在R6,R7中傳遞。

53、 func2 (int b, int c, int *d ) "b"是第一個(gè)參數(shù),在R6,R7中傳遞;"c"是第二個(gè)參數(shù),在R4,R5中傳遞;"d"是第三個(gè)參數(shù),在R1,R2,R3中傳遞。 func3(long e , long f ) "e"是第一個(gè)參數(shù),在R4~R7中傳遞;"f"是第二個(gè)參數(shù),不能在寄存器中傳

54、遞,只能在參數(shù)傳遞段中傳遞。 func4(float g , char h ) "g"是第一個(gè)參數(shù),在R4~R7中傳遞;"h"是第二個(gè)參數(shù),必須在參數(shù)傳遞段中傳遞。,表7 函數(shù)返回值的寄存器,在匯編子程序中,當(dāng)前選擇的寄存器組及寄存器ACC、B、DPTR和PSW都可能改變。當(dāng)被C調(diào)用時(shí),必須無條件地假設(shè)這些寄存器的內(nèi)容已被破壞。如果已在連接/定位程序時(shí)選擇了覆蓋,那么每個(gè)匯編子

55、程序包含一個(gè)單獨(dú)的程序段是必要的,因?yàn)樵诟采w過程中,函數(shù)間參量通過子程序各自的段參量計(jì)算。匯編子程序的數(shù)據(jù)區(qū)甚至可包含在覆蓋部分中,但應(yīng)注意下面兩點(diǎn): (1) 所有段名必須以C51類似的方法建立。 (2) 每個(gè)有局部變量的匯編程序必須指定自己的數(shù)據(jù)段,這個(gè)數(shù)據(jù)段只能為其它函數(shù)訪問作參數(shù)傳遞用。所有參數(shù)一個(gè)接一個(gè)被傳遞,由其它函數(shù)計(jì)算的結(jié)果保存入棧。,8.2 覆蓋和共享,1.覆蓋 單片機(jī)片內(nèi)存儲(chǔ)

56、空間有限,連接器/定位器通常重新啟用程序不再用的位置。這就是說,若一個(gè)程序不再調(diào)用,也不由其它程序調(diào)用(甚至間接調(diào)用),那么在其它程序執(zhí)行完之前,這個(gè)程序不再運(yùn)行。這個(gè)程序的變量可以放在與其它程序完全相同的RAM空間,很像可重用的寄存器。這種技術(shù)就是覆蓋。在匯編中直接通過手工完成的這些空間分配,C語言中可以由連接器自動(dòng)管理。若有幾個(gè)不相關(guān)聯(lián)的程序時(shí),它可以使RAM單元比手工考慮要用的少。,2.共享1) 共享變量,2) 共享函數(shù)/子程序

57、 C中函數(shù)若是全局的(公用的),可以放在調(diào)用的函數(shù)之后。若函數(shù)是模塊專用的,它可以定義為靜態(tài)函數(shù),這樣它不能被其它模塊調(diào)用。C語言的ANSI標(biāo)準(zhǔn)建議所有函數(shù)在主函數(shù)前要有原型(進(jìn)行說明),然后實(shí)際函數(shù)可在主函數(shù)之后或其它模塊中。 匯編語言中,子程序使用標(biāo)號(hào)可在給定模塊的任何位置。匯編器首先掃描得到所有的符號(hào)名,然后值就可填入LCALL或LJMP。一個(gè)模塊或另一模塊共享子程序,一個(gè)使用PUBLIC而另一個(gè)使用

58、EXTERN。當(dāng)指定為EXTERN,符號(hào)類型(CODE,DATA,XDATA,IDATA,BIT或NUMBER)必須特別加以指定,以便連接器可以確定放在一起的正確類型。,8.3 庫和連接器/定位器 1. 庫,表 9 C51的編譯庫,2.連接器/定位器 1) 組合程序模塊 將幾個(gè)不同程序模塊組合為一個(gè)模塊,并自動(dòng)從庫中挑選模塊嵌入目標(biāo)文件。輸入文件按命令行中出現(xiàn)的順序處理。通常的程序模塊

59、是由C51編譯器或A51宏匯編生成的可重入的目標(biāo)文件。,2) 組合段 將具有相同段名的可重定位段組合成單一的段。在一個(gè)程序模塊中定義的一個(gè)段成為部分段。一個(gè)部分段在源文件中以下列形式指定: (1) 名字 每個(gè)重定位段有一個(gè)名字,它可與來自其它模塊的同名的可重定位段組合。絕對(duì)段沒有名字。 (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é)塊中。因?yàn)闆]有連接器可以靈活地判知調(diào)用和轉(zhuǎn)移是否在塊內(nèi)??芍囟ㄎ坏钠渌拗剖牵篜AGE--不能超過256字節(jié);BITADDRESSABLE--必須放在可位尋址的內(nèi)部RAM空間;UNIT--允許段從任意字節(jié)開始(對(duì)位變

61、量是位)。 (4) 長度 一個(gè)段的長度。,(5) 基址 段的首址。對(duì)于絕對(duì)段,地址由匯編器賦予,對(duì)于可重定位段,地址由L51決定。在處理程序模塊時(shí),L51自動(dòng)產(chǎn)生段表(MAP),該表包含了每個(gè)段的類型、基址、長度、可重定位性和名字。 L51自動(dòng)將所具有相同名字的所有部分段組合到單一可重定位段中。例如,三個(gè)程序模塊包含字段VAR,在組合時(shí),三個(gè)段的長度相加,從而組合段的長度也增加了。,對(duì)組合段有下列規(guī)則:

62、① 所有具有相同名的部分段必須有相同類型 (CODE,DATA,IDATA,XDATA或BIT)。 ② 組合段的長度不能超過存儲(chǔ)區(qū)的物理長度。 ③ 每個(gè)組合的部分段的定位方法也必須相同。 ④ 絕對(duì)段相互不組合,它們被直接拷貝到輸出文件。,3) 存儲(chǔ)器分配,表10 MCS-51系列的物理存儲(chǔ)區(qū),4) 采用覆蓋技術(shù)使用數(shù)據(jù)存儲(chǔ)器 通過采用一定的覆蓋技術(shù),M

63、CS-51系列少量的片內(nèi)數(shù)據(jù)存儲(chǔ)器可由L51有效地使用。由C51編譯器或是A51匯編器生成的參數(shù)和局部變量(若使用它們的函數(shù)不相互調(diào)用)可在存儲(chǔ)器中覆蓋。這樣,所用的存儲(chǔ)器得到相當(dāng)程度地減少。 為完成數(shù)據(jù)覆蓋,L51分析所有不同函數(shù)間的調(diào)用,使用該信息可以確定哪個(gè)數(shù)據(jù)和位段可被覆蓋。使用控制參數(shù)OVERLAY和NOOVERLAY可允許或禁止覆蓋。OVERLAY是默認(rèn)值,用它可產(chǎn)生非常緊湊的數(shù)據(jù)區(qū)。,5) 決定外部參考地址

64、 具有相同名的外部符號(hào)(EXTERN)和公用符號(hào)(PUBLIC)被確定后,外部符號(hào)指向其它模塊中的地址。一個(gè)已聲明的外部符號(hào)用具有相同名字的功用符號(hào)確定,外部參考地址由其公共參考地址確定。這還與類型(DATA,IDATA,XDATA,CODE,BIT或NUMBER)有關(guān),如果類型不符或未發(fā)現(xiàn)外部符號(hào)參考地址的公用符號(hào),則會(huì)產(chǎn)生錯(cuò)誤。公用符號(hào)的絕對(duì)地址在段定位后決定。,6) 絕對(duì)地址計(jì)算 定義絕對(duì)地址并計(jì)算可重定

65、位段的地址。在段分配和外部公用參考地址處理完后,程序模塊中所有可重定位地址和外部地址要進(jìn)行計(jì)算,此時(shí)生成的目標(biāo)文件中的符號(hào)信息(DEBUG)被改變以反映新的值。,7) 產(chǎn)生絕對(duì)目標(biāo)文件 可執(zhí)行程序以絕對(duì)目標(biāo)格式產(chǎn)生。該絕對(duì)目標(biāo)文件可包含附加的符號(hào)信息(DEBUG),從而使符號(hào)調(diào)試成為可能。符號(hào)信息可用參數(shù)NODEBUGSYMBOLS,NODEBUGPUBLICS和NODEBUGLINES禁止。輸出文件是可執(zhí)行的,并可由仿真

66、器裝入調(diào)試或被OHS51翻譯為Intel HEX格式文件以供EPROM固化。,8) 產(chǎn)生映像文件 產(chǎn)生一個(gè)反映每個(gè)處理步驟的映像文件,它顯示有關(guān)連接/定位過程的信息和程序符號(hào),并包含一個(gè)公用和外部符號(hào)的交叉參考報(bào)告。映像文件包含下列信息: ① 文件名和命令行參數(shù)。 ② 模塊的文件名和模塊名。 ③ 一個(gè)包含段地址、類型、定位方法和名字的存儲(chǔ)器分配表。該表可在命令行中用NOMA

67、P參考禁止。 ④ 段和符號(hào)的所有錯(cuò)誤列表。列表文件末尾顯示出所有出錯(cuò)的原因。,⑤ 一個(gè)包含輸入文件中符號(hào)信息的符號(hào)表。該信息由MODULES,SYMBOLS,PUBLICS和LINES名組成,LINES是C編譯器產(chǎn)生的行號(hào)。符號(hào)信息可用參數(shù)NOSYMBOLS,NOPUBLICS和NOLINES完全或部分禁止。 ⑥ 一個(gè)按字母順序排列的有關(guān)所有PUBLIC和EXTERN符號(hào)的交叉參考報(bào)告,其中顯示出符號(hào)類

68、型和模塊名。第一個(gè)顯示的模塊名是定義了PUBLIC符號(hào)的模塊,后面的模塊名是定義了EXTERN符號(hào)的模塊。在命令行輸入?yún)?shù)IXREF可產(chǎn)生此報(bào)告。 ⑦ 在連接器/定位器運(yùn)行期間檢測(cè)到的錯(cuò)誤同時(shí)顯示在屏幕和文件尾部。,8.4 程序優(yōu)化,以下選擇對(duì)提高程序效率有很大影響: (1) 盡量選擇小存儲(chǔ)模式以避免使用MOVX指令。 (2) 使用大模式(COMPACT/LARGE)應(yīng)仔細(xì)考慮要放在內(nèi)部數(shù)據(jù)

69、存儲(chǔ)器的變量要求是經(jīng)常用的或是用于中間結(jié)果的。訪問內(nèi)部數(shù)據(jù)存儲(chǔ)器要比訪問外部數(shù)據(jù)存儲(chǔ)器快得多。內(nèi)部RAM由寄存器組、位數(shù)據(jù)區(qū)和其它用戶用“data”類型定義的變量共享。由于內(nèi)部RAM容量的限制(128~256字節(jié),由使用的單片機(jī)決定),必須權(quán)衡利弊以解決訪問效率和這些對(duì)象的數(shù)量之間的矛盾。,(3) 要考慮操作順序,完成一件事后再做一件事。 (4) 注意程序編寫細(xì)則。例如,若使用for(;;)循環(huán),DJNZ指令比CJNE指令

70、更有效,可減少重復(fù)循環(huán)次數(shù)。 (5) 若編譯器不能使用左移和右移完成乘除法,應(yīng)立即修改,例如,左移為乘2。 (6) 用邏輯AND/&取模比用MOD / %操作更有效。 (7) 因計(jì)算機(jī)基于二進(jìn)制,仔細(xì)選擇數(shù)據(jù)存儲(chǔ)器和數(shù)組大小可節(jié)省操作。,(8) 盡可能使用最小的數(shù)據(jù)類型,MCS-51系列是8位機(jī),顯然對(duì)具有"char"類型的對(duì)象的操作比"int"或

71、"long"類型的對(duì)象的操作要方便得多。 (9) 盡可能使用"unsigned"數(shù)據(jù)類型。MCS-51系列CPU并不直接支持有符號(hào)數(shù)的運(yùn)算。因而C51編譯器必須產(chǎn)生與之相關(guān)的更多的程序代碼以解決這個(gè)問題。 (10) 盡可能使用局部函數(shù)變量。編譯器總是嘗試在寄存器里保持局部變量。這樣,將循環(huán)變量(如for和while循環(huán)中的計(jì)數(shù)變量)說明為局部變量是最好的。使用&quo

溫馨提示

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

評(píng)論

0/150

提交評(píng)論