www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 單片機 > 單片機
[導(dǎo)讀]1 編譯器支持的數(shù)據(jù)類型1.1 C-51 編譯器支持下列數(shù)據(jù)類型:數(shù) 據(jù) 類 型長 度值 域bit1 字節(jié)0 或 1signed char1 字節(jié)-128~+127unsigned char1 字節(jié)0~255signed int2 字節(jié)-32768~+32867unsigned int2 字節(jié)0~65535s

1 編譯器支持的數(shù)據(jù)類型

 

1.1 C-51 編譯器支持下列數(shù)據(jù)類型:

 

 

 

數(shù) 據(jù) 類 型

 

長 度

 

值 域

 

bit

 

1 字節(jié)

 

0 或 1

 

signed char

 

1 字節(jié)

 

-128~+127

 

unsigned char

 

1 字節(jié)

 

0~255

 

signed int

 

2 字節(jié)

 

-32768~+32867

 

unsigned int

 

2 字節(jié)

 

0~65535

 

signed long

 

4 字節(jié)

 

-2147483648~+2147483647

 

unsigned long

 

4 字節(jié)

 

0~4294967295

 

float

 

4 字節(jié)

 

±1.176E-38~±3.40E+38

 

指針

 

1~3 字節(jié)

 

對象地址

 

sbit

 

1 位

 

0 或 1

 

sfr

 

1 字節(jié)

 

0~255

 

sfr16

 

2 字節(jié)

 

0~65535

 

 

 

編譯的數(shù)據(jù)類型(如結(jié)構(gòu))包含上表所列的數(shù)據(jù)類型。由于8051系列是8位機,因而不存在字節(jié)校準問題。這意味著數(shù)據(jù)結(jié)構(gòu)成員是順序放置的。

數(shù)據(jù)類型的轉(zhuǎn)換:當(dāng)計算結(jié)果隱含著另外一種數(shù)據(jù)類型時,數(shù)據(jù)類型可以自動進行轉(zhuǎn)換,例如,將一個位變量賦給一個整型變量時,位型值自動轉(zhuǎn)換為整型值,有符號變量的符號也能自動進行處理。這些轉(zhuǎn)換也可以用C語言的標準指令進行人工轉(zhuǎn)換。

1.2 數(shù)據(jù)類型的物理結(jié)構(gòu)

1.2.1 bit

 

 

“bit”類型只有1位,不允許有位指針和位數(shù)組。位對象始終位于8051 CPU的可尋址RAM空間。如果程序控制流允許,L51將位對象交迭。

 

1.2.2 signed/unsigned char;data/idata/pdata 指針

“char”類型標量和基于存貯器的“data/idata/pdata”指針具有1個字節(jié)長度(8 bits)。

1.2.3 signed/unsigned int/short;xdata/code 指針

“int”和“short”類型標量及指向xdata/code區(qū)域的指針具有2字節(jié)長度(16

bits)。

整型值(或偏移)0x1234以下面方式保存在內(nèi)存中:

地址: +0 +1

內(nèi)容: 0x12 0x34

1.2.4 signed/unsigned long

“long”類型標量長為4個字節(jié)(32 bits),值0x12345678以下面方式放置:

地址: +0 +1 +2 +3

內(nèi)容: 0x12 0x34 0x56 0x78

 

1.2.5 “一般”指針

“一般”指針包括3個字節(jié):2字節(jié)偏移和1字節(jié)存貯器類型:

地址: +0 +1 +2

內(nèi)容: 存貯器類型 偏移高位 偏移低位

第一個字節(jié)代表了指針的存貯器類型,存貯器類型編碼如下:

存貯器類型 IDATA XDATA PDATA DATA CODE

值 1 2 3 4 5

使用其它類型值可能導(dǎo)致不可預(yù)測的程序動作。

XDATA類型的0x1234地址作為指針表示如下:

地址: +0 +1 +2

內(nèi)容: 0x02 0x12 0x34

 

當(dāng)用常數(shù)作指針時,必須注意正確定義存貯器類型和偏移。下例將值0x41寫入絕對地址為0x8000的外部數(shù)據(jù)存貯器:

#define XBYTE ((char *)0x20000L)

XBYTE[0x8000]=0x41;

上例中用其它常數(shù)索引或索引變量也起作用。這樣,各種存貯器類型的絕對地址可以一種非常有效的方式訪問。但有一個例外,即SFR。

 

注意:絕對地址定義為“long”型常量,低16位包含偏移,高8位表明了xdata類型。為了表示這種指針,必須用長整數(shù)來定義存貯器類型。

C51編譯器不檢查指針常數(shù),用戶必須選擇有實際意義的值。

 

1.2.6 float

“float”類型為4個字節(jié)(32位),使用的格式與IEEE-754標準(32位)具有24位精度,尾數(shù)的高位始終為“1”,因而不保存,位的分布如下:

l 1位符號

l 8位指數(shù)位

l 23位尾數(shù)

符號位是最高位,尾數(shù)為最低的位,內(nèi)存中按字節(jié)存貯如下:

地址: +0 +1 +2 +3

內(nèi)容: MMMM MMMM MMMM MMMM E MMM MMMM S EEE EEEE

其中: S:符號位,1=負,0=正

E:指數(shù)(在兩個字節(jié)中),偏移為127

M:23位尾數(shù),最高位“1”

浮點值——12.5的十六進制為0xC1480000,它按下面方式存貯:

地址: +0 +1 +2 +3

內(nèi)容: 0x00 0x00 0x48 0xc1

8051不包括捕獲浮點錯誤(例外)的中斷向量。用戶軟件因此必須對錯誤條件作出適當(dāng)反應(yīng)。下面推薦一種方法(也可以用其它可靠辦法):“union”用來保存浮點值,這個“union”必須包括一個“float”和一個“unsigned long”,以根據(jù)IEEE對錯誤作出響應(yīng)。除了通常浮點值外,IEEE標準可能出錯的條件以下面二進制值表示,為檢查可能出現(xiàn)的計算錯誤,可在計算后進行檢查。因為當(dāng)執(zhí)行一個運算時考慮了每個運算符的錯誤狀態(tài)并且該狀態(tài)被送到結(jié)果中。

NaN 0xFFFFFFF 不是一個數(shù)

+INF 0x7F80000 正無窮(正溢出)

-INF 0XFF80000 負無窮(負溢出)

1.3 C-51 的擴充定義

1.3.1 特殊功能寄存器的聲明

MSC-51 系列包括多種寄存器,其中一些具有特殊功能,如定時器,端口的控制寄存器等,為了能夠直接訪問這些寄存器,C51編譯器提供了一種定義的自主形式,這是必要的,因為這些定義與標準C語言是不兼容的。

為了支持這些特殊功能寄存器(SFR)的聲明,引入了關(guān)鍵詞“sfr”,語法如下:

sfr-dcl:sfr sfr_name=int_constant

例:

sfr p0=0x80;

sfr p1=0x90;

必須注意的是“sfr”后不是一個地址而是一個名字。因此上例中名字P0和P1(port0和port1)定義為特殊功能寄存器并被賦予相應(yīng)的絕對地址,名字可按意愿自由選取,源文件中不應(yīng)有先定義的sfr名字。

“=”號后的地址必須是常數(shù),不允許帶有運算符的表達式,這個常數(shù)表達式必須在特殊功能寄存器的地址范圍內(nèi),位于0X80到0XFF之間。

8051系列寄存器數(shù)量和類型是極其不同的,因此建議將所有特別的“sfr”聲明放入一個頭文件,頭文件包括8051一些系列成員中的SFR定義。進一步的定義可由用戶用一文件編輯器產(chǎn)生。

 

1.3.2 對SFR的16位數(shù)據(jù)訪問

在新的8051系列產(chǎn)品中,SFR在功能上經(jīng)常組合為16位的,為了有效的訪問這類SFR,使用定義“sfr16”,當(dāng)“SFR”的高端直接位于低端后時,對SFR16位的訪問是可能的。例如8052的定時器2就是這種情況,16位聲明的語法與“sfr”相同,SFR低地址部分必須作為sfr16的地址:

例:sfr16 T2=0xCC /*Timer2:T2L=0CCH,T2H=0CDH */

sfr16 RCAP2=0xCA /*RCAP2L=0CAH,PCAP2H=0CBH */

本例中,T2(由T2L和T2H組成)和RCAP2(由RCAP2L和RCAP2H組成)被定義為16位SFR,即使在這種情況下,聲明中的名字后仍不是賦值語句,而是一個SFR地址,高字節(jié)必須直接位于低字節(jié)之后,這種聲明適用于所有新的SFR,但不能用于Timer0和Timer1。

 

1.3.3 SBIT:特殊功能位聲明

在典型的8051應(yīng)用問題中,經(jīng)常需要單獨訪問SFR中的位,C51擴充功能使之成為可能,特殊位,象SFR一樣,不與標準C語言兼容,使用保留字“sbit”可訪問位尋址對象。與SFR聲明一樣,用保留字“sbit”聲明某些特殊位接受符號名,“=”后語句將絕對值地址賦給變量名,這種地址分配有三種方法:

方法1:sfr_name^int_constant

當(dāng)字節(jié)是特殊功能寄存器的地址可用這個方法。sfr_name必須是已定義的SFR的名字,“^”后的語句定義了基地址上的特殊位的位置,該位置必須是一個0~7的數(shù)。

例: sfr PSW="0xD0";

sfr LE="0xA8";

sbit OV="PSW"^2;

sbit CY="PSW"^7;

方法2:int_constant^int_constant

這種方法以一整常數(shù)作基地址,該值必須在0x80~0xFF之間,并能被8整除,確定位的位置方法同上。

例: sbit OV="0xD0"^2;

sbit CV="0xD0"^7;

sbit EA="0xA8"^7;

方法3: int_constant

這種方法是將位的絕對地址賦給變量,地址必須位于0x80~0xFF之間。

例: sbit OV="0xD2";

sbit CY="0xD7";

sbit EA="0xAF";

特殊功能位代表了一個獨立的聲明類,它不能與其它聲明和位域互換。

 

1.3.4 BIT:位標量聲明

除了通常的C數(shù)據(jù)類型外,C51編譯器支持“bit”數(shù)據(jù)類型,對此有下列擴充與限制:

(1) 函數(shù)可包含類型為“bit”的參數(shù),也可將其作為返回值。

bit bfunc(bit b0,bit b1){

/*……*/

return(b1);

}

注:使用禁止中斷(#pragma disable)或包含明確的寄存器組切換(using n)的函數(shù)不能返回位值,在這種情況下,編譯器會識別出來并產(chǎn)生一個錯誤信息。

(2) 位標量聲明的語法及C聲明的語義

static bit dirction_bit;

extern bit lock_printer_port;

bit display_invers;

(3) 對于位聲明的限制

l 位不能聲明為一個指針(bit *bit_poiter)

l 不存在位數(shù)組(bit b_array[5])

位聲明中允許定義存貯器類型,位都被放入一個位段,它總是在8051內(nèi)部RAM中,因此存貯器類型限制為DATA或IDATA,聲明為其它存貯器類型都將導(dǎo)致編譯出錯。

 

1.3.5 可位尋址對象

可位尋址對象指可以字節(jié)或位尋址的對象,當(dāng)對象位于MSC-51可尋址RAM中時會有這種情況,C51允許帶“bdata”類型的對象放入可位尋址存貯器中。

bdata int ibase; /*位尋址指針 int*/

bdata char bary[4]; /*位尋址數(shù)組 arrray*/

使用“sbit”聲明可獨立訪問可位尋址對象的位:

sbit mybit0=ibase^0;

sbit mybit15=ibase^15;

sbit ary07=bary[0]^7;

sbit ary37=bary[3]^7;

對象“ibase”和“bary”也可位尋址:

ary37=0; /*尋址“bary[3]”中的位7*/

ibase=-1; /*尋址字節(jié)地址*/

mybit15=0; /*尋址“ibase”的位15*/

sbit聲明要求基址對象的存貯器類型為“bdata”,否則只有絕對的位聲明方法是合法的。位位置(‘^’操作符號后)的最大值依賴于指定的基類型,這個值于char/uchar而言是0~7,對于int/uint/short/ushort而言是0~15,對于long/ulong而言是0~31。

在編譯器內(nèi)存貯器類型bdata與data一樣操作,并且只作與可再定位的sbit的運算。注:可位尋址的的段長最大不能超過16字節(jié),可再定位的sbit聲明自動轉(zhuǎn)為公共的(PBULIC)以使它們能被其它C模塊使用。

模塊1: sbit ary37=bary[3]^7;

模塊2: extern bit ary37;

sbit聲明也可為結(jié)構(gòu)和函數(shù)所用:

union lft {float mf;long ml;} ;

bdata struct bad { char ml; union lft u; }tcp;

sbit tcpf31=tcp.u.ml^31; /*浮點限制*/

sbit tcpml0=tcp.ml^0;

sbit tcmpl7=tcp.ml.^7;

 

注:位位置的指定不能直接被float類型所用,如果需要這樣做,浮點標量必須與一個長整型標量一起放入一個聯(lián)合中并且位位置必須由長整型標題指定(見上例)。

1.4 存貯器類型

C51編譯器完全支持8051微處理器及其系列的結(jié)構(gòu),可完全訪問MCS-51硬件系統(tǒng)所有部分。每個變量可準確地賦予不同的存貯器類型(data,idata,pdata,xdata,code)。訪問內(nèi)部數(shù)據(jù)存貯器(idata)要比訪問外部數(shù)據(jù)存貯器(xdata)相對要快一些,因此,可將經(jīng)常使用的變量置于內(nèi)部數(shù)據(jù)存貯器中,而將較大及很少使用的數(shù)據(jù)單元置于外部數(shù)據(jù)存貯器中。

 

 

 

存貯器類型

 

描 述

 

data

 

直接尋址內(nèi)部數(shù)據(jù)存貯器,訪問變量速度最快(128bytes)

 

bdata

 

可位尋址內(nèi)部數(shù)據(jù)存貯器,允許位與字節(jié)混合訪問(16 bytes)

 

iIdata

 

間接尋址內(nèi)部數(shù)據(jù)存貯器,可訪問全部地址空間(256bytes)

 

pPdata

 

分頁(256bytes)外部數(shù)據(jù)存貯器,由操作碼MOVX @Ri訪問

 

xdata

 

外部數(shù)據(jù)存貯器(64K),由MOVX @DPTR訪問

 

code

 

代碼數(shù)據(jù)存貯器(64K),由MOVC @A+DPTR訪問

 

變量說明舉例:

data char charvar;

char code msg[]=”ENTER PARAMETER:”;

unsigned long xdata array[100];

float idata x,y,z;

unsigned char xdata vector[10][4][4];

sfr p0=0x80;

sbit RI="0x98";

char bdata flags;

sbit flago="flags"^0;

如果在變量說明時略去存貯器類型標志符,編譯器會自動選擇默認的存貯器類型。默認的存貯器類型進一步由控制指令SMALL、COMPACT和LARGE限制。例如:如果聲明char charvar,則默認的存貯器模式為SMALL,charvar放在data存貯器;如果使用COMPACT模式,則charvar放入idata存貯區(qū);在使用LARGE模式的情況下,charvar被放入外部存貯區(qū)或xdata存貯區(qū)。

1.5 存貯器模式

存貯器模式?jīng)Q定了自動變量和默認存貯器類型,參數(shù)傳遞區(qū)和無明確存貯區(qū)類型的說明。在固定的存貯器地址變量參數(shù)傳遞是C51的一個標準特征,在SMALL模式下參數(shù)傳遞是在內(nèi)部數(shù)據(jù)存貯區(qū)中完成的。LARGRE和COMPACT模式允許參數(shù)在外部存貯器中傳遞。C51同時也支持混合模式,例如在LARGE模式下生成的程序可將一些函數(shù)分頁放入SMALL模式中從而加快執(zhí)行速度。

 

 

 

存貯器模式

 

描 述

 

SMALL

 

參數(shù)及局部變量放入可直接尋址的內(nèi)部寄存器(最大128bytes,默認存貯器類型是DATA)

 

COMAPCT

 

參數(shù)及局部變量放入分頁外內(nèi)部存貯區(qū)(最大256bytes,默認存貯器類型是PDATA)

 

LARGE

 

參數(shù)及局部變量直接放入外部數(shù)據(jù)存貯器(最大64K,默認存貯器類型是XDATA)

 

 

1.6 指針

Franklin C-51支持“基于存貯器的”和“一般指針”。

 

1.6.1 基于存貯器的指針

基于存貯器的指針由C源代碼中存貯器類型決定并在編譯時確定,用這種指針可高效訪問對象且只需一個字節(jié)(idata*,data*,pdata*)或2個字節(jié)(code*,xdata*)。操作較短指針的代碼被縮短,一般被“內(nèi)行”編碼;庫調(diào)用不再必要。

聲明舉例:

 

 

char xdata *pt

 

在xdata存貯器中聲明一個指向?qū)ο箢愋蜑?ldquo;char”的指針。指針默認自身在默認存貯區(qū)(決定于編譯模式),長度為2字節(jié)。(值為0~0xFFFF)

 

char xdata *data pdx;

 

除了指針明確位于內(nèi)部數(shù)據(jù)存貯器(data)中外,與上例相同。它與編譯模式無關(guān)。

 

data char xdata *pdx;

 

本例與上例完全相同。存貯器類型定義既可放在聲明的開頭也可直接放在聲明的對象之前。這種形式是為了與早期C-51編譯器版本兼容。

 

上面例子闡明了指針的一般聲明及使用。它們與所有的數(shù)據(jù)類型和存貯器類型相關(guān)。所有用于一般指針的操作同樣可用于基于存貯器的指針。

 

1.6.2 一般指針

“一般”指針需3個字節(jié):1個字節(jié)為存貯類型,2個字節(jié)為偏移量。存貯器類型決定了對象所用的8051存貯器空間,偏移量指向?qū)嶋H地址。一個“一般”指針可訪問任何變量而不管它在8051存貯器空間中的位置。這樣就允許一般性函數(shù),如memcpy將數(shù)據(jù)從任意一個地址拷貝到另一個地址空間。

 

1.6.3 基于存貯器的指針與一般指針的轉(zhuǎn)換

一個已定位指針可轉(zhuǎn)換為一個一般指針(3字節(jié))及副本。這在某些時候是很有用的。例如庫函數(shù)包含一個一般指針變量,象printf(),sprintf(),gets()等包含一個一般指針變量,如同以前的編譯器和庫版本一樣。這些函數(shù)因而廣泛適用。

例:extern int printf(void *format,…);

在printf調(diào)用中,2字節(jié)指針自動轉(zhuǎn)換為一個3字節(jié)指針,而printf的原型正需要一個一般指針(3字節(jié))作為其第一參量。

注:如果沒有函數(shù)原型,函數(shù)調(diào)用的參量中指針總是轉(zhuǎn)換為一般指針。如果函數(shù)確實需要一個短指針作參量,這會產(chǎn)生錯誤,為了避免在程序中發(fā)生這類錯誤,需要使用頭文件,或某些函數(shù)聲明函數(shù)原型。這將保證讓編譯器轉(zhuǎn)換為所需類型,否則會產(chǎn)生類型不匹配錯誤。

例:指針定義說明

 

 

指 針 說 明

 

長 度

 

指 向

 

float *p;

 

3 字節(jié)

 

所有8051存貯器空間中的“float”(一般指針)

 

char data *dp;

 

1字節(jié)

 

“data”存貯器中的“char”

 

int idata *ip;

 

1字節(jié)

 

“idata”中的“int”

 

long pdata *pp;

 

1字節(jié)

 

“pdata”中的“long”

 

char xdata *xp;

 

2字節(jié)

 

“xdata”中的“char”

 

int code *cp;

 

2字節(jié)

 

“code”中的“int”

 

 

1.6.4 抽象指針類型

抽象指針類型用來在每個存貯區(qū)訪問任意絕對地址,或來產(chǎn)生絕對CALLs。在這個過程中,常數(shù)類型或字符型、整型都用抽象類型作了原則性修改(類型整理)以允許進行絕對訪問或調(diào)用。

例:

char xdata *px;

char idata *pi;

char code *pc;

char c;

int i;

pc = (void*)main;

i = ((int(code*)(void))0xFF00(); /*LCALL 0FF00H */

c = *((char code*)0x8000); /*char [code[0x8000]]*/

i = *((int code*)0x1200); /*int from code[0x1200]*/

px = *((char xdata *xdata*)0x4000); /*x ptr from xdata[0x4000]*/

px = ((char xdata *xdata*)0x4000)[0]; /*同上*/

px = ((char xdata *xdata *)0x4000)[1] /*x ptr from xdata[0x4002]*/

1.7 寄存器組定義

8051系列的器件包含4個相同的寄存器組,每個寄存器組包括8個寄存器(R0~R7),C51編譯器可使在一函數(shù)中決定用哪一寄存器組成為可能。絕對寄存器的訪問可用AREGS/NOAREGS和REGISTERBANK來控制。

定義一個帶擴展性的函數(shù)語法如下:

返回類型 函數(shù)名([參數(shù)])[模式][再入][中斷 n]using n

再入和中斷將在后兩節(jié)討論。

例:void rb_function(void) using 3;

“using”不允許用于外部函數(shù),它對函數(shù)的目標代碼影響如下:

l 函數(shù)入口處將當(dāng)前寄存器保存入棧;

l 指它的寄存器還會改變;

l 函數(shù)退出前寄存器組被恢復(fù)。

“using”定義對于返回一個寄存器內(nèi)的值的函數(shù)是無用的。編程者必須十分小心以保證任何寄存器切換都只在仔細控制的區(qū)域發(fā)生。如果不做到這一點將會產(chǎn)生不正確的函數(shù)結(jié)果。即使當(dāng)編程者使用同一寄存器組時,帶“using”屬性的函數(shù)原則上也不能返回一個位值。

實際產(chǎn)生的代碼決定于編譯器及不同開關(guān)條件,有時用命令產(chǎn)生絕對的寄存器地址,當(dāng)需要進行這樣的地址計算時,使用REGISTERBANK指令的影響只是計算Arn寄存器使用的地址,而必進行實際切換。

1.8 中斷服務(wù)程序

C51編譯器及其對C語言的擴充允許編程者對中斷的所有方面進行控制。這種支持能使系統(tǒng)編程者創(chuàng)建高效的中斷服務(wù)程序,用戶只需在普通和高級方式下關(guān)心中斷及必要的寄存器組切換操作,C51編譯器將產(chǎn)生最合適的代碼。

 

1.8.1 中斷服務(wù)程序的定義

使用中斷服務(wù)函數(shù)的完整語法如下:

返回值 函數(shù)名([參數(shù)])[模式][再入] interrupt n[using n]

“interrupt”后接一個0~31的常數(shù),不允許使用表達式。

中斷不允許用于外部函數(shù),它對函數(shù)目標代碼的影響如下:

l 當(dāng)使用函數(shù)時,SFR中的ACC、B、DPH、DPL和PSW(當(dāng)需要時)入棧;

l 如不使用寄存器組切換,甚至中斷函數(shù)所需的所有工作寄存器(Rn)都入棧;

l 函數(shù)退出前,所有的寄存器內(nèi)容出棧;

l 函數(shù)由8051控制命令“RETI”終止。

 

1.8.2 開發(fā)中斷過程時的規(guī)則

l 不能進行參數(shù)傳遞,如果中斷過程包括任何參數(shù)聲明,編譯器將產(chǎn)生一個錯誤信息;

l 無返回值,如果想定義一個返回值將產(chǎn)生錯誤,然而,如果返回整型值編譯器將不產(chǎn)生錯誤信息,因為整型值是默認值,因而編譯器不能清楚識別。

l 編譯器會識別對中斷過程的直接調(diào)用并拒絕它們,在任何情況下不能直接調(diào)用中斷過程,因為退出該過程是由操作碼RETI完成的。RETI影響8051芯片的硬件中斷系統(tǒng),由于硬件上沒有中斷請求存在,因而這個操作碼的結(jié)果是不定的并且通常是致命的。由于疏忽,可能用指針來間接調(diào)用它,這是值得注意的。

l 編譯器從絕對地址8n+3處產(chǎn)生一個中斷向量,其中n為中斷號,該向量包括一個到中斷過程的跳轉(zhuǎn),向量的產(chǎn)生可由指令NOINTVECTOR壓縮。因而用戶有能力從獨立的匯編模塊中提供中斷向量。

l C51編譯器允許0~31個中斷,究竟允許哪些中斷依賴于使用的8051系列芯片,編譯器不能檢查。

l 如果中斷程序中有浮點運算,必須保持浮點寄存器狀態(tài),當(dāng)沒有其它程序執(zhí)行浮點運算時,可能不保存,函數(shù)“fsave”和“fprestore”用來保存浮點狀態(tài)。

l 中斷過程調(diào)用的函數(shù)所使用的寄存器必須與中斷過程相同,當(dāng)沒有使用“using”指令時,編譯器會選擇一個寄存器組作絕對寄存器訪問,當(dāng)子程序使用另一個寄存器組時會發(fā)生錯誤,用戶必須保證按要求使用相應(yīng)寄存器組,C編譯器不會對此檢查。

例:

unsigned int interruptent;

unsigned char second;

time() interrupt 1 using 2 /*定時器0中斷服務(wù)程序,工作寄存器使用2區(qū)*/

{

if(++interruptcnt==4000) {

second++; /*秒計數(shù)加一*/

interruptcnt=0; /*清中斷計數(shù)*/

}

}

1.9 再入函數(shù)

再入函數(shù)可被遞歸調(diào)用,調(diào)用可發(fā)生在任何時候,即使是在中斷過程中。在實時處理的應(yīng)用問題中常常需要再入函數(shù)。

使用關(guān)鍵字“reentrant”可有選擇地定義函數(shù)有再入能力。在存貯器模式的基礎(chǔ)上為再入函數(shù)在內(nèi)部或外部存貯器中模擬了一個棧區(qū)域。由于MCS-51缺乏合適的尋址方法,使用棧結(jié)構(gòu)是相當(dāng)必要的。因而應(yīng)盡量少用再入函數(shù)。

定義一再入函數(shù)的語法如下:

返回值 函數(shù)名([參數(shù)])[模式]reetrant[interrupt n][using n]

例:

int calc(char i,int b) reentrant {

int x;

x=table[i];

return(x*b);

}

使用再入函數(shù)有如下規(guī)定:

l 不能傳遞類型為“bit”的參數(shù)。也不能聲明一個局部標量,再入功能不能包括位操作及MCS-51可位尋址區(qū)域。

l 不能在“alien”函數(shù)調(diào)用再入函數(shù)。

l 再入函數(shù)可同時有其它屬性,如“using”函數(shù)模式和“interrupt”。

l 再入函數(shù)不能同時有“alien”屬性,從而遵守PL/M規(guī)則。

l 返回地址及可能的PUSH/POP操作存入MCS-51的棧中或被執(zhí)行(不在再入棧中)。

l 在同一模塊中,任意模塊的再入函數(shù)(small reentrant,lage reentrant,compact reentrant)不能與具有不同模式的再入函數(shù)混合。

再入函數(shù)舉例:

/*這個再入函數(shù)可以從“main”及中斷程序中調(diào)用*/

int calc(char i,int b)reentrant {

int x;

x=table[i];

return(x*b);

}

1.10 參數(shù)傳遞

通過CPU的寄存器可傳遞至多三個參數(shù)。這樣產(chǎn)生與匯編子程序相當(dāng)?shù)挠行?shù)機制。如果寄存器被占用,或說明了“#pragma NOREGPARMS”,參數(shù)變量將使用固定的存貯器位置,存貯器模式?jīng)Q定了8051存貯器為參數(shù)提供的位置。

表:候選的參數(shù)寄存器

 

 

參數(shù)類型

 

char,1字節(jié)指針

 

int,2字節(jié)指針

 

long,float

 

一般指針

 

一個參數(shù)

 

R7

 

R6,R7

 

R4~R7

 

R1,R2,R3

 

二個參數(shù)

 

R5

 

R4,R5

 

R4~R7

 

R1,R2,R3

 

三個參數(shù)

 

R3

 

R2,R3

 

 

R1,R2,R3

 

 

函數(shù)的返回值放在CPU固定的寄存器中,列表如下。這樣,與匯編子程序的接口變得非常容易。

 

表:函數(shù)返回值的寄存器用法

 

 

返 回 值

 

寄 存 器

 

意 義

 

bit

 

進位標志 C

 

 

 

(unsigned) char

 

R7

 

 

 

(unsigned) int

 

R6,R7

 

高位在R6,低位在R7

 

(unsigned) long

 

R4~R7

 

高位在R4,低位在R7

 

float

 

R4~R7

 

32位IEEE格式

 

指 針

 

R1,R2,R3

 

類型選擇在R3,高位在R2,低位在R1

 

 

1.11 PL/M51接口

Franklin C51利用關(guān)鍵字“alien”提供了一個與Intel PL/M-51直接和簡單和接口,關(guān)鍵字“alien”在所有存貯器模式下可用于“extern”和“public”函數(shù)?,F(xiàn)有的PL/M-51程序利用C語言的強大功能可與Franklin C-51連接起來。

使用關(guān)鍵字“alien”,C51可用PL/M-51規(guī)定的參數(shù)傳遞方式工作。“alien”可用于外部或公共函數(shù),并可用于任一模式,這樣,已有的PL/M-51程序可加入到C-51中。Alien函數(shù)始終包含一個標準的參數(shù)數(shù)量,因此,C中定義的三點(…)記號不被接受,且會產(chǎn)生一個錯誤信息。

例:

extern alien char plm_function(unsigned char,unsigned int);

extern char c_function(unsigned char x,unsigned char y) {

return(x*y);

}

PL/M-51兼容函數(shù)必須定義以關(guān)鍵字“alien”。這樣,PL/M函數(shù)的參數(shù)傳遞及參數(shù)返回規(guī)定在C編譯器中才被考慮。

1.12 匯編接口

參數(shù)是通過固定的CPU寄存器傳給匯編程序的,當(dāng)使用“#pragma NOREGPARMS”時,則通過固定的存貯器位置傳遞參數(shù)。這樣就給匯編與Franklin C-51之間提供了一個非常簡潔的接口。返回值在CPU寄存器中。

下例為在匯編中用來編碼的“toupper”函數(shù),參數(shù)傳遞發(fā)生在寄存器中。

UPPER SEGMENT CODE ;程序代碼段

PUBLIC _toupper ;入口地址

RESG UPPER ;選擇程序代碼段

toupper: MOV A,R7 ;char 參數(shù)在寄存器R7中

CJNE A,#’a’,UPP1

UPP1: JC UPPERT

CJNE A,#’z’+1,UPP2

UPP2: JNE UPPRET

CLR ACC.5

UPPRET: MOV R7,A ;char 返回值在寄存器R7中

RET ;返回C

1.13 內(nèi)部函數(shù)

Franklin C-51支持下列內(nèi)部函數(shù)。內(nèi)部函數(shù)既是再入的又是有效的。

表:C51的內(nèi)部函數(shù)

 

 

函 數(shù)

 

描 述

 

memcpy,memsset,memchr,memmove,memcmp

 

ANSI的內(nèi)存操作功能

 

strcmp,strcpy

 

ANSI字符串處理功能

 

_crol_,_irol_,lrol_

 

左移字符、整數(shù)、長整數(shù)

 

_crolr_,_irolr_,lrolr_

 

右移字符、整數(shù)、長整數(shù)

 

_nop_

 

空操作

 

_testbit_

 

測試并清位(JBC指令)

 

 

1.14 代碼優(yōu)化

Franklin C51可將即使有經(jīng)驗的程序員編制的代碼進行優(yōu)化。用戶可選6個優(yōu)化級,另外,用OPTIMIZE(SIZE),NOREGPARMS和NOAREGS時會影響生成代碼的類型。C51的所有優(yōu)化如下:

(1) 一般優(yōu)化:

l 常數(shù)折迭:發(fā)生在一個表達式或地址計算中的幾個常數(shù)值組合為一個常數(shù)。

l 跳轉(zhuǎn)優(yōu)化:跳轉(zhuǎn)轉(zhuǎn)到最終的目標地址,以提高程序效率。

l 死碼消除:不可執(zhí)行代碼(死碼)可從程序中去掉。

l 寄存器變量:只要有可能,自動變量和參量放入寄存器中,為這些變量保留的數(shù)據(jù)存貯器將去除。

l 通過寄存器傳遞參數(shù):寄存器中可傳遞最多三個參數(shù)。

l 全局公共子式消除:相同的子表達式或地址計算(多次發(fā)生在同一函數(shù)中)將被識別出來,并且只要有可能,將只計算一次。

(2) 基于8051的優(yōu)化:

l 窺孔(PEEPHOLE)優(yōu)化:只要能節(jié)省存貯空間或執(zhí)行時間,復(fù)雜的運算都將化簡。

l 訪問優(yōu)化:常數(shù)和變量直接包含在操作中。

l 數(shù)據(jù)覆蓋:函數(shù)的數(shù)據(jù)和位移被標記為OVERLAYABLE,被L51用其它數(shù)據(jù)和位覆蓋。

l CASE/SWITCH優(yōu)化:SWITCH/CASE語句優(yōu)化為一個跳轉(zhuǎn)或一串跳轉(zhuǎn)。

(3) 代碼生成選項:

l OPTMIZE(SIZE):共同的“C”操作被子程序代替:程序碼長被壓縮。

l NOAREGS:不使用絕對寄存器訪問,程序代碼在這種方式下獨立于寄存器組。

l NOREGPARMS:參數(shù)傳遞總是在本數(shù)據(jù)段完成,程序代碼與早期C-51版本兼容。

1.15 C庫

C-51編譯器包含6個不同的編譯庫,可根據(jù)不同函數(shù)的需要進行優(yōu)化,這些庫幾乎支持所有的ANSI函數(shù)調(diào)用。因此,用此標準的C程序可在編譯和連接后立即運行。

 

 

 

描 述

 

C51S.LIB

 

SMALL模式,無浮點運算

 

C51FPS.LIB

 

浮點數(shù)學(xué)運算庫(SMALL模式)

 

C51C.LIB

 

COMPACT模式,無浮點運算

 

C51FPC.LIB

 

浮點運算庫(COMPACT模式)

 

C51L.LIB

 

LARGE模式,無浮點運算

 

C51FPL.LIB

 

浮點運算庫(LARGE模式)

 

C51編譯器包含的庫模塊,都有源代碼,對它們可作與硬件相關(guān)的修改。用戶改變對于現(xiàn)有硬件輸入和輸出結(jié)構(gòu)的兩個模塊,就可修改所有庫函數(shù),同樣也可以重新很快地構(gòu)造如“printf”和“puts”函數(shù)用LCD顯示。

L51連接器的檢查從而保證所有模塊都用一種模式編譯并自動選擇編譯庫,從而使用戶完全可以不用不同庫的細節(jié)。

1.16 配置文件

C51編譯器可根據(jù)不同的硬件環(huán)境由4個文件作出修改。下列配置文件包括在C-51軟件包中:

 

 

STARTUP51.51:

 

 

C51編譯器的啟動程序,所有的棧指針和存貯器,只要需要,將被初始化。

 

INIT.A51:

 

 

在文件中已明確初始化了變量作初始化。如果系統(tǒng)裝入“看門狗”,該文件可包含附加的“看門狗”刷新。

 

PUBCHAR.C:

 

函數(shù)“printf”、“puts”等的字符輸出核心程序,該程序可根據(jù)用戶硬件加以修改(如LCD顯示)。

 

GETKEY.C:

 

函數(shù)“getchar”、“scanf”等的字符輸入核心程序,該程序可根據(jù)硬件加以修改(如矩陣鍵盤)。

 

所有的文件都包含在C運行庫中,因此,不能在連接時指定調(diào)用。如果用戶改變一個文件,可將其編譯后與其它目標文件一起連接,因而不必改動運行庫。庫中原文件自動忽略。

例:

L51 DEMO1.OBJ,DEMO2.OBJ,STARTUP.OBJ,PUTCHAR.OBJ

本例將用戶建立的STARTUP.OBJ和PUTCHAR.OBJ連接起來

 

STARTUP.A51

文件STARTUP.51開頭包含一些C編譯結(jié)構(gòu)使用的EQU語句。每個EQU語句的功能描述如下:

IDATALEN 聲明系統(tǒng)開始時有多少內(nèi)存需要用0初始化。默認值為80H,因為幾乎每個

8051指令至少包含128字節(jié)內(nèi)部RAM。對于256字節(jié)內(nèi)部RAM的8052可使用100H。當(dāng)用戶程序在開始時需要使用0初始化的內(nèi)存時才有必要作改動。如果內(nèi)存初始化必須保持對掉電模式系統(tǒng)的完全抑制,IDATALEN應(yīng)設(shè)為0。這種情況下至少得保持所有位于段?C_LIB_DATA和?C_LIB_DBIT中的變量都置為0。否則有些庫函數(shù)不能完全發(fā)揮作用,?C_LIB_DATA段的長度因不同應(yīng)用問題而不同,其當(dāng)前長度可在MAP文件中找到。

XDATASTART

XDATALEN 表明了需要以0初始化的PDATA區(qū)首址和長度,XDATASTART指明了XDATA區(qū)首址,XDATALEN表明了需初始化的字節(jié)數(shù)。

PDATASTART

PDATALEN 表明了需以0初始化的PDATA區(qū)首址及長度,PDATASTART指明了首址,XDATALEN指定了長度。

LBPSTACK

LBPSTACKTOP 定義了SMALL模式下創(chuàng)建的再入函數(shù)使用的棧區(qū)。LBPSTACK表明是否對棧指針(變量?C_LBP)初始化,LBPSTACKTOP指明了棧頂首址。對于具有256字節(jié)內(nèi)部RAM的8051系統(tǒng),當(dāng)存貯區(qū)作首址為0XFF的棧時,可不初始化。C51不作棧區(qū)是否滿足特定應(yīng)用的檢查,用戶必須自己進行測試。

XBPSTACK

XBPSTACKTOP 為在LARGE模式下創(chuàng)建的再入函數(shù)定義了棧區(qū),XBPSTACK表明指針(變量?C_XBP)是否初始化,XBPSTACKTOP指定了棧頂?shù)刂?。?dāng)存貯區(qū)作為首址為0Xffff(在XDATA區(qū))的棧時,可不作初始化。同上一樣,C51不作棧檢查,需要用戶自己測試。

PBPSTACK

PBPSTACKTOP 為在COMPACT模式下創(chuàng)建的再入函數(shù)定義了棧區(qū),PBPSTACK表明棧指針(變量?C_PBP)是否初始化。PBPSTACKTOP指定了棧頂?shù)刂?。?dāng)存貯區(qū)作為首址為0Xff(在PDATA區(qū))的棧時,可不作初始化。同上一樣,C51不作棧檢查,需要用戶自己測試。

PPAGEENABLE

PPAGE 當(dāng)在COMPACT模式中用16位尋址XDATA存貯區(qū)時需要這些指令。對于使用LARGE模式的程序,可用它提高運行速度或減小代碼長度。PPAGEENABLE允許8051端口2的初始化,對端口2的尋址允許在任意XDATA頁256字節(jié)變量空間的映射。這兩個指令必須和L51的控制指令PDATA一起使用。PDATA指定了XDATA存貯器中PDATA區(qū)的首址。例:在STARTUP.A51中,PPAGEENABLE置為1,PPAGE置為10H。這種情況下PDATA區(qū)首址為1000H(10H頁),而L51必須包含一個值在1000和10FFH之間的控制語句:L51〈輸入模塊〉PDATA(1050H)。注:L51和C51都不對PPAGE/PDATA指令正確性進行檢查,用戶必須保證PPAGE和PDATA包含一個合適的值。

INIT.A51:

文件INIT.A51包含一個定義了“看門狗”刷新的宏。當(dāng)系統(tǒng)包括“看門狗”以及用戶變量初始化時間比“看門狗”刷新時間要長時,必須改變這個宏。這種情況下,宏WATCHCOG必須包含“看門狗”刷新的代碼。

例: ;Watchdog refresh for 80515 system

WATCHDOG MACRO

SETB WDT

SETB SWDT

ENDM

PUTCHAR.C

文件PUTCHAR.C包含字符輸出的核心程序,該文件通過串行口輸出。這種情況下考慮了XON/XOFF協(xié)議,字符LF()被轉(zhuǎn)為字符串CR,LF,這在很多終端中是需要的。用戶可按自己的要求改變putchar()函數(shù)。

GETKEY.C

文件GETKEY.C包含字符輸入的核心程序,該文件從串行接口讀入一個字符,不作數(shù)據(jù)轉(zhuǎn)換,用戶可根據(jù)需要修改getkey()函數(shù)。

 

本節(jié)包含幾個怎樣提高8051程序效率的注解。

 

定位變量

經(jīng)常訪問的數(shù)據(jù)對象應(yīng)放入在片內(nèi)數(shù)據(jù)RAM中,這可在任一模式(COMPACT/LARGE)下用輸入存貯器類型的方法實現(xiàn)。訪問片內(nèi)數(shù)據(jù)RAM要比訪問外部數(shù)據(jù)存貯器快得多。片內(nèi)RAM由寄存器組,位數(shù)據(jù)區(qū)棧和其它由用戶用“data”類型定義的變量共享。由于片內(nèi)RAM容量的限制(128~256字節(jié),由使用的處理器決定),必須權(quán)衡利弊以解決訪問效率和這些對象的數(shù)量之間的矛盾。

 

總是使用可能的最小數(shù)據(jù)類型

8051系列CPU都是8位機,因此,顯然對具有“char”類型的對象的操作比“int”或“long”類型的對象方便得多。建議編程者只要滿足要求,應(yīng)盡量使用最小數(shù)據(jù)類型。

C51編譯器直接支持所有的字節(jié)操作,因而如果不是運算符要求,就不作“int”類型的轉(zhuǎn)換,這可用一個乘積運算來清楚說明,兩個“char類型”對象的乘積與8051操作碼“MUL AB”剛好相符。如果用整型量完成同樣的運算,則需要調(diào)用庫函數(shù)。

 

只要有可能,使用“unsigned”數(shù)據(jù)類型

8051系列CPU并不直接支持有符號數(shù)的運算。因而C51編譯器必須產(chǎn)生與之相關(guān)的更多的代碼以解決這個問題。如果使用無符號類型,產(chǎn)生的代碼要少得多。

 

只要有可能,使用局部函數(shù)變量

編譯器總是嘗試在寄存器里保持局中變量。這樣,將索引變量(如FOR和WHILE循環(huán)中計數(shù)變量)聲明為局部變量是最好的,這個優(yōu)化步驟只為局部變量執(zhí)行。使用“unsigned char/int”的對象通常能獲得最好的結(jié)果。

 

2 C51編譯器控制指令

 

編譯選項可能被控制指令激活、禁止或改變。這些指令可在命令行輸入或在源文件上加入#pragma給預(yù)處理器。控制指令分為兩組,即首要的和一般的,并可分為三類:源控制、目標控制、列表控制。見表2.1編譯控制指令。“P/G”列表明指令是首要的或是一般的,首要指令僅出現(xiàn)一次,一般指令按需要可出現(xiàn)多次。

 

表2.1 編譯控制指令

 

 

分 類

 

P/G

 

 

指 令

 

縮 寫

 

默 認 值

 

 

P

G

G

G

P

 

DEFINE

SAVE

RESTORE

DISABLE

[NO]EXTEND

 

DF

——

 

EXTEND

 

目 標

 

P

P

P

P

P

P

G

G

G

P

P

P

 

[NO]DEBUG

[NO]OBJECT

OPTIMIZE(n)

SMALL

COMPACT

LARGE

[NO]REGPARMS

REGISTERBANK(n)

[NO]AREGS

[NO]INTVECTER

OBJECTEXTEND

ROM()

 

[NO]DB

[NO]OJ

OT

SM

CP

LA

[NO]RP

RB

[NO]AR

[NO]IV

OE

 

NODEBUG

OBJECT(名字.OBJ)

OPTIMIZE(2)

SMALL

REGPARMS

REGISTERBANK(0)

AREGS

INTVECTOR

ROM(LARGE)

 

列 表

 

P

P

P

P

P

P

P

G

P

 

[NO]LISTINCLUDE

[NO]SYMBOLS

[NO]PREPRINT

[NO]CODE

[NO]PRINT

[NO]CODE

PAGELENGTH(n)

EJECT

PAGEWIDTH(n)

 

[NO]LC

[NO]SB

[NO]PP

[NO]CD

[NO]PR

[NO]CO

PL

EJ

PW

 

NOLISTINCLUDE

NOSYMBOLS

NOPREPRINT

NOCODE

PRINT(名字.OBJ)

CODE

PAGELENGTH(69)

PAGEWIDTH(132)

 

2.1 源控制

2.1.1 DEFINE

名 字: DEFINE

縮 寫: DF

變 量: 一個或幾個由逗號分開的名字,與C語言的命令規(guī)格一致。

默認值: 無

DEFINE 指令定義了在命令行使用的名字,可為“if”,“ifdef”及“ifndef”等預(yù)處理命令作條件編譯,定義的名字被精確拷貝,因而對大小寫敏感。

例: C51 DEMO.C DEFINE(check,NoExtRam)

 

2.1.2 SAVE/RESTORE

名 字: SAVE/RESTORE

縮 寫: 無

變 量: 無

默認值: 無

SAVE指令存儲當(dāng)前的ARGES,REGPARMS,OPTIMIZE因子和優(yōu)化選項的SPEEDSIZE設(shè)置。這樣,上面所述的設(shè)置被保留下來,例如在#INCLUDE語句之前用SAVE保護,然后用RESTORE指令恢復(fù)。

SAVE/RESTORE只能在源文件中以#pragma語句的參數(shù)形式出現(xiàn),而不能用于命令行。

例:

#pragma save

#pragma noregparms

extern void test1(char c,int I);

extern char test2(long l,float f);

#pragma restore

兩個外部函數(shù)的寄存器內(nèi)參數(shù)傳遞被禁止,然后SAVE指令時的設(shè)置被恢復(fù)。

 

2.1.3 DISABLE

名 字: DISABLE

縮 寫: 無

變 量: 無

默認值:無

DISABLE指令在一個函數(shù)執(zhí)行期間禁止中斷發(fā)生。DISABLE必須在函數(shù)前以#pragma指定并且只能用在一個函數(shù)中,因此它是由編譯器內(nèi)部設(shè)置的,每個要禁止的中斷在函數(shù)前必須包括一個獨立的#pragma指定,而不能用于命令行。

例: typedef using char uchar;

#pragma disable /*Disable interrupts */

uchar dfunc(uchar p1,uchar p2) {

return(p1*P2+P2*p1);

}

 

2.1.4 EXTEND/NOEXTEND

名 字: EXTEND/NOEXTEND

縮 寫: 無

變 量: 無

默認值: EXTEND

EXTEND指令支持ANSI-C對C51的特殊擴展。NOEXTEND指令使編譯器只處理ANSI-C。不同的保留字如bit,reentrant,using等對編譯器來說是未知的。

例: C51 DEMO.C NOEXTEND

#pragma NOEXTEND

2.2 目標控制

2.2.1 DEBUG/NODEBUG

名 字: DEBUG/NODEBUG

縮 寫: DB/NODB

變 量: 無

默認值:NODEBUG

DEBUG指令指示編譯器將調(diào)試信息加入到目標文件中,該信息對于符號調(diào)試而言是必需的,它包括全局和局部變量的定義及其地址、以及函數(shù)名及其行號。目標模塊中的調(diào)試信息在用L51連接過程中一直保持有效,它也可被與dscope-51或intel兼容的仿真器使用。NODEBUG指令指示在目標文件中不加入調(diào)試信息。QTH建議用戶要加入DB信息。

例: C51 DEMO.C DEBUG

#pragma db

 

2.2.2 OBJECT/NOOBJECT

名 字: OBJECT/NOOBJECT

縮 寫: OJ/NOOJ

變 量: 括號內(nèi)文件名

默認值: OBJECT(bname.OBJ)

OBJECT(filename)指令改變生成的目標文件名,默認值是路徑名加上基本擴展名“.OBJ”,NOOBJECT指令不產(chǎn)生目標文件。

例: C51 DEMO.C NOOBJEECT

#pragma oj(demo.obj)

 

2.2.3 OBJECTEXTEND

名 字: OBJECTEXTEND

縮 寫: OE

變 量: 無

默認值: 無

OBJECTEXTEND使編譯器產(chǎn)生的目標文件包含附加的變量類型定義信息。這個信息可在目標模塊具有相同名字的時候?qū)⑺鼈儏^(qū)別開來以供不同的仿真器使用。

注:QTH系列仿真器不需要該控制項。

 

2.2.4 OPTIMIZE

名 字: OPTIMIZE

縮 寫: OT

變 量: 括號內(nèi)一個0~5的十進制數(shù),另外可選OPTIMIZE(SIZE)和OPTIMIZE(SPEED)

以決定優(yōu)化重點是放在代碼長度上還是執(zhí)行速度上。

默認值:OPTIMIZE(2,SPEED)。

OPTIMIZE指令設(shè)置優(yōu)化級,在這種設(shè)置中,高一級的優(yōu)化級包含前一級較低的優(yōu)化級的設(shè)置。

(1) OPTIMIZE(0)

l 常數(shù)折疊:編譯時只要有可能,編譯器就執(zhí)行包含常數(shù)的計算,包括執(zhí)行地址計算。

l 簡單訪問化:對8051系統(tǒng)內(nèi)部數(shù)據(jù)和地址進行訪問優(yōu)化。

l 跳轉(zhuǎn)優(yōu)化:編譯器總是將跳轉(zhuǎn)延遲至最終目標上,因此跳轉(zhuǎn)到跳轉(zhuǎn)的指令被消除。

(2) OPTIMIZE(1)

l 死碼消除:無用的代碼將被消除。

l 跳轉(zhuǎn)否決:根據(jù)一個測試反饋,條件轉(zhuǎn)移被仔細檢查,以決定是否能夠進行簡化或消除。

(3) OPTIMIZE(2)

l 數(shù)據(jù)覆蓋:適用于靜態(tài)覆蓋的數(shù)據(jù)和位段被鑒別并標記出來。L51有這樣一個功能,通過對全局數(shù)據(jù)流的分析,選擇可靜態(tài)覆蓋的段。

(4) OPTIMIZE(3)

l “窺孔”優(yōu)化:冗余的MOV指令被刪去,這也包括不必要的、從存貯器裝入對象及裝入常數(shù)的操作。另外,當(dāng)它能節(jié)省存貯器空間或執(zhí)行時間時,復(fù)雜操作由簡單操作所取代。

(5) OPTIMIZE(4)

l 寄存器變量:自動和參數(shù)變量位于寄存器中,只要有可能,將不為這些就是變量保留數(shù)據(jù)存貯器空間。

l 擴展訪問優(yōu)化:由IDATA,XDATA和CODE區(qū)域來的變量直接包含在操作中,因此在大多數(shù)時候裝入中間寄存器是不必要的。

l 局部公共子式的消除:如果表達式中有一個重復(fù)執(zhí)行的計算,只要有可能,第一次計算的結(jié)果將被用于后續(xù)的計算,因此可以從代碼中消除繁雜的計算。

l CASE/SWITCH優(yōu)化:CASE/SWITCH語句作為跳轉(zhuǎn)表或跳轉(zhuǎn)串被優(yōu)化。

(6) OPTIMIZE(5)

l 全局公共子式消除:只要有可能,函數(shù)內(nèi)相同的子表達式只計算一次。中間結(jié)果存入一個寄存器以代替新的計算。

l 簡單循環(huán)優(yōu)化:以常量占據(jù)一段內(nèi)存的循環(huán)被轉(zhuǎn)化并在運行時被優(yōu)化。OPTIMIZE(5)包括了從0級到4的所有優(yōu)化。

例: C51 SAMPLE.C OPTIMIZE(4)

#pragma ot(5,SIZE)

#pragma ot(size)

注: 全局優(yōu)化從優(yōu)化級4開始。同時,一個完整的函數(shù)被優(yōu)化時,如果分配給生成優(yōu)

化代碼所必要的數(shù)據(jù)結(jié)構(gòu)的內(nèi)存不夠,全局優(yōu)化只執(zhí)行一部分,或根本不執(zhí)行。

 

2.2.5 SMALL/COMPACT/LARGE

名 字: SMALL/COMPACT/LARGE

縮 寫: 無

變 量: 無

默認值: SMALL

SMALL,COMPACT,LARGE這些指令控制存貯器模式選擇。存貯器模式對不同的變量定義有所影響。

SMALL:

所有函數(shù)和過程變量及局部數(shù)據(jù)段被定義在8051系統(tǒng)內(nèi)部數(shù)據(jù)存貯器,因此以這種模式訪問數(shù)據(jù)對象是非常有效的。這種模式的缺點是地址空間有限。

COMPACT:

所有函數(shù)和過程變量及局部數(shù)據(jù)段被定義在8051系統(tǒng)外部數(shù)據(jù)存貯器中,這個存貯區(qū)可達256字節(jié)(1頁)。這種模式使用訪問外部數(shù)據(jù)存貯器的簡潔形式(@R0/R1)。

LARGE:

所有變量和局部變量數(shù)據(jù)段定義在8051系統(tǒng)的外部數(shù)據(jù)存貯器中,可訪問達64K字節(jié)的地址空間。因此,它需要通過數(shù)據(jù)指針(DPTR),這是一種效率不高的數(shù)據(jù)訪問形式。

注意:調(diào)用子程序的棧始終放在內(nèi)部存貯器中。

例: C51 SAMPLE.C LARGE

#pragma compact

2.2.6 REGPARMS/NOREGPARMS

名 字: REGPARMS/NOREGPARMS

縮 寫: RP/NORP

變 量: 無

默認值: REGPARMS

使用REGPARMS指令時,編譯器在寄存器內(nèi)至多傳遞三個參數(shù)。該指令產(chǎn)生的參數(shù)傳遞代碼與早期的C51版本兼容。

REGPARMS和NOREGPARMS指令可以在源程序中定義多次。這樣就允許程序的某一節(jié)使用寄存器進行參數(shù)傳遞,而其它函數(shù)仍然用原來的傳遞方式,匯編語言函數(shù)及庫文件(已經(jīng)存在的)則不必更改。

例: C51 DEMO.C NOREGPARMS

#pragma RP

 

2.2.7 REGISTERBANK

名 字: REGISTERBANK

縮 寫: RB

變 量: 括號內(nèi)一個0~3的數(shù)

默認值: REGISTERBANK(0)

REGISTERBANK指令選擇當(dāng)前調(diào)用時使用的寄存器組,除非使用“using”標志。當(dāng)能夠計算寄存器的絕對數(shù)量時,生成代碼可能使用寄存器訪問的絕對形式,用助記符“Arn”來表示。

與“using n”相比,REGISTERBANK不轉(zhuǎn)換寄存器組!

有返回值的函數(shù)必須始終使用同一個寄存器組。否則,返回值可能放在錯誤的寄存器組中。

例: C51 DEMO.C REGISTERBANK

#pragma rp(3)

 

2.2.8 AREGS/NOAREGS

名 字: AREGS/NOAREGS

縮 寫: AR/NOAR

變 量: 無

默認值: AREGS

AREGS使編譯器使用絕對寄存器尋址方式,絕對寄存器尋址方式提高了效率。例如:PUSH和POP指令只能直接(絕對)尋址。用REGSITERBANK指令可建立指定使用的寄存器組。NOAREG指令關(guān)閉絕對尋址。未使用NOAREGS指令編譯的函數(shù)不依賴于寄存器組,即它們可使用8051所有的寄存器。AREGS/NOAREGS指令可在程序中定義多次,然而,這只能在函數(shù)外使用。

例: C51 DEMO.C NOAREGS

#pragma AREGS

 

2.2.9 INTVECTOR/NOINTVECTOR

名 字: INTVECTOR/NOINTVECTOR

縮 寫: IV/NOIV

變 量: 無

默認值: INTVECTOR

INTVECTOR指令使編譯器產(chǎn)生3字節(jié)跳轉(zhuǎn)(LJMP)目標值。這些向量放在絕對地址8n+3處,n為中斷號。NOINTVECTOR指令可以防止產(chǎn)生這些中斷向量,這種靈活性使用戶可以利用其它編程工具提供的中斷服務(wù)子程序。

例: C51 SAMPLE.C NOINTVECTOR

#pragma noiv

 

2.2.10 ROM

ROM指令用來決定程序內(nèi)存的大小,它影響跳轉(zhuǎn)指令的編碼。

ROM(SMALL):

以CALL和JMP指令作為ACALL和AJMP指令的編碼,最大程序空間可達2K字節(jié),整個用戶程序必須分布在這2K字節(jié)空間內(nèi)。

ROM(COMPACT):

CALL指令以LCALL編碼,函數(shù)內(nèi)JMP指令以AJMP編碼,因此函數(shù)長度不得超過2K字節(jié),而整個程序長度不得超過64K字節(jié),這種用法必須根據(jù)不同的目的而決定,看其是否比標準設(shè)置ROM(LARGE)效果更佳。

ROM(LARGE)

將CALL和JMP指令以LCALL和LJMP編碼。這樣就允許不加限制地使用整個地址空間,用戶程序最大可達64K字節(jié)。

例: C51 DEMO.C ROM(SMALL)

#pragma ROM(SMALL)

2.3 列表控制

2.3.1 LISTINCLUDE

名 字: LISTINCLUDE/NOLISTINCLUDE

縮 寫: LC/NOLC

變 量: 無

默認值: NOLISTINCLUDE

LISTINCLUDE指令導(dǎo)致在列表文件中出現(xiàn)頭文件的內(nèi)容。QTH仿真器建議用戶使用默認值。

 

2.3.2 SYMBOLS/NOSYMBOLS

名 字: SYMBOLS/NOSYMBOLS

縮 寫: SB/NOSB

變 量: 無

默認值: NOSYMBOL

SYMBOLS,NOSYMBOLS指令在編譯時產(chǎn)生一個被程序模塊使用過的符號表。對于每一個符號對象,包含了存貯器登錄,存貯類型,偏移和對象大小。

例: C51 DEMO.C SB

#pragma sb

 

2.3.3 PREPRINT/NOPREPRINT

名 字: PREPRINT/NOPREPRINT

縮 寫: PP/NOPP

變 量: 括號內(nèi)可選的文件名

默認值: NOPREPRINT

PREPRINT指令產(chǎn)生一個預(yù)處理器列表,宏調(diào)用被擴展并且注釋被刪除。如果PREPRINT指令不帶變量,則源文件名加上擴展名“·I”作為列表文件名,如果不用此名,則須指定一個文件名。

例: C51 DEMO.C PP(DEMO.LST)

 

2.3.4 CODE/NOCODE

名 字: CODE/NOCODE

縮 寫: CD/NOCD

變 量: 無

默認值: NOCODE

CODE指令在列表文件后附加上一個匯編記憶表,源程序中的每個函數(shù)被表示為匯編代碼。

 

2.3.5 PRINT/NOPRINT

名 字: PRINT/NOPRINT

縮 寫: PR/NOPR

變 量: 括號內(nèi)文件名

默認值: PRINT(bname.LST)

PRINT指令使編譯器用路徑,源文件名及擴展名“.LST”為每個被編譯的程序產(chǎn)生一個列表文件,該列表文件名可以用PRINT選項重新定義,當(dāng)使用NOPRINT時,將不產(chǎn)生列表文件。QTH仿真器建議用戶使用默認值。

 

2.3.6 COND/NOCOND

名 字: COND/NOCOND

縮 寫: CO/NOCO

變 量: 無

默認值: COND

指令COND和NOCOND決定源文件中條件編譯部分是否出現(xiàn)在列表文件中,COND選項禁止向列表文件輸出跳過的行。每當(dāng)預(yù)處理器檢測到該指令時,該指令就會對該行產(chǎn)生影響。QTH仿真器建議用戶使用默認值。

 

2.3.7 PAGELENGTH

名 字: PAGELENGTH

縮 寫: PL

變 量: 括號內(nèi)一個最大為65535十進制數(shù)

默認值: PAGELENGTH(69)

PAGELENGTH指令指定了列表文件中每頁的行數(shù)。默認值為69頁。包括抬頭和空行。

例: C51 DEMO.C PAGELENGTH(60)

#pragma pl(60)

 

2.3.8 PAGEWIDTH

名 字: PAGEWIDTH

縮 寫: PW

變 量: 括號內(nèi)一個78~132的十進制數(shù)

默認值: PATHWIDTH(132)

PAGEWIDTH指定了每行的字符數(shù)。若超過此數(shù),該行將變?yōu)閮尚谢蚨嘈?。QTH仿真器建議用戶使用默認值。

 

2.3.9 EJECT

名 字: EJECT

縮 寫: EJ

變 量: 無

默認值: 無

EJECT指令使列表文件換頁。該指令只能用在源文件上,且必須是#pragma的一部分。

 

3 C庫函數(shù)

C-51軟件包的庫包含標準的應(yīng)用程序,每個函數(shù)都在相應(yīng)的頭文件(.h)中有原型聲明。如果使用庫函數(shù),必須在源程序中用預(yù)編譯指令定義與該函數(shù)相關(guān)的頭文件(包含了該函數(shù)的原型聲明)。例如:

#include

#include

如果省掉頭文件,編譯器則期望標準的C參數(shù)類型,從而不能保證函數(shù)的正確執(zhí)行。

3.1 CTYPE.H:字符函數(shù)

在CTYPE.H頭文件中包含下列一些庫函數(shù):

 

函數(shù)名: isalpha

原 型: extern bit isalpha(char)

功 能: isalpha檢查傳入的字符是否在‘A’-‘Z’和‘a’-‘z’之間,如果為真返回

值為1,否則為0。

 

函數(shù)名: isalnum

原 型: extern bit isalnum(char)

功 能: isalnum檢查字符是否位于‘A’-‘Z’,‘a’-‘z’或‘0’-‘9’之間,為真返

回值是1,否則為0。

 

函數(shù)名: iscntrl

原 型: extern bit iscntrl(char)

功 能: iscntrl檢查字符是否位于0x00~0x1F之間或0x7F,為真返回值是1,否則為0。

 

函數(shù)名: isdigit

原 型: extern bit isdigit(char)

功 能: isdigit檢查字符是否在‘0’-‘9’之間,為真返回值是1,否則為0。

 

函數(shù)名: isgraph

原 型: extern bit isgraph(char)

功 能: isgraph檢查變量是否為可打印字符,可打印字符的值域為0x21~0x7E。若為可

打印,返回值為1,否則為0。

 

函數(shù)名: isprint

原 型: extern bit isprint(char)

功 能: 除與isgraph相同外,還接受空格字符(0X20)。

 

函數(shù)名: ispunct

原 型: extern bit ispunct(char)

功 能: ispunct檢查字符是否位為標點或空格。如果該字符是個空格或32個標點和格式

字符之一(假定使用ASCII字符集中128個標準字符),則返回1,否則返回0。Ispunct對下列字符返回1:

(空格)!“$%^&()+,-./:<=>?_[‘~{

}

 

函數(shù)名: islower

原 型: extern bit islower(char)

功 能: islower檢查字符變量是否位于‘a’-‘z’之間,為真返回值是1,否則為0。

 

函數(shù)名: isupper

原 型: extern bit isupper(char)

功 能: isupper檢查字符變量是否位于‘A’-‘Z’之間,為真返回值是1,否則為0。

 

函數(shù)名: isspace

原 型: extern bit isspace(char)

功 能: isspace檢查字符變量是否為下列之一:空格、制表符、回車、換行、垂直制表

符和送紙。為真返回值是1,否則為0。

 

函數(shù)名: isxdigit

原 型: extern bit isxdigit(char)

功 能: isxdigit檢查字符變量是否位于‘0’-‘9’,‘A’-‘F’或‘a’-‘f’之間,

為真返回值是1,否則為0。

 

函數(shù)名: toascii

原 型: toascii(c)((c)&0x7F);

功 能: 該宏將任何整型值縮小到有效的ASCII范圍內(nèi),它將變量和0x7F相與從而去掉低

7位以上所有數(shù)位。

 

函數(shù)名: toint

原 型: extern char toint(char)

功 能: toint將ASCII字符轉(zhuǎn)換為16進制,返回值0到9由ASCII字符‘0’到‘9’得

到,10到15由ASCII字符‘a’-‘f’(與大小寫無關(guān))得到。

函數(shù)名: tolower

原 型: extern char tolower(char)

功 能: tolower將字符轉(zhuǎn)換為小寫形式,如果字符變量不在‘A’-‘Z’之間,則不作轉(zhuǎn)

換,返回該字符。

 

函數(shù)名: ­_tolower

原 型: tolower(c);(c-‘A’+‘a’)

功 能: 該宏將0x20參量值逐位相或。

 

函數(shù)名: toupper

原 型: extern char toupper(char)

功 能: toupper將字符轉(zhuǎn)換為大寫形式,如果字符變量不在‘a’-‘z’之間,則不作轉(zhuǎn)

換,返回該字符。

 

函數(shù)名: _toupper

原 型: _toupper(c);((c)-‘a’+’A’)

功 能: _toupper宏將c與0xDF逐位相與。

3.2 STDIO.H:一般I/O函數(shù)

C51編譯器包含字符I/O函數(shù),它們通過處理器的串行接口操作,為支持其它I/O機制,只需修改getkey()和putchar()函數(shù),其它所有I/O支持函數(shù)依賴這兩個模塊,不需要改動。在使用8051串行口之前,必須將它們初始化,下例以2400波特率,12MHz初始化串口:

SCON=0x52 /*SCON*/

TMOD=0x20 /*TMOD*/

TR1=1 /*Timer 1 run flag*/

TH1=0Xf3 /*TH1*/

其它工作模式和波特率等細節(jié)問題可以從8051用戶手冊中得到。

 

函數(shù)名: _getkey

原 型: extern char _getkey();

功 能: _getkey()從8051串口讀入一個字符,然后等待字符輸入,這個函數(shù)是改變整個

輸入端口機制應(yīng)作修改的唯一一個函數(shù)。

 

函數(shù)名: getchar

原 型: extern char _getchar();

功 能: getchar()使用_getkey從串口讀入字符,除了讀入的字符馬上傳給putchar函數(shù)

以作響應(yīng)外,與_getkey相同。

 

函數(shù)名: gets

原 型: extern char *gets(char *s,int n);

功 能: 該函數(shù)通過getchar從控制臺設(shè)備讀入一個字符送入由‘s’指向的數(shù)據(jù)組。考

慮到ANSI標準的建議,限制每次調(diào)用時能讀入的最大字符數(shù),函數(shù)提供了一個字符計數(shù)器‘n’,在所有情況下,當(dāng)檢測到換行符時,放棄字符輸入。

 

函數(shù)名: ungetchar

原 型: extern char ungetchar(char);

功 能: ungetchar將輸入字符推回輸入緩沖區(qū),因此下次gets或getchar可用該字符。

ungetchar成功時返回‘char’,失敗時返回EOF,不可能用ungetchar處理多個字符。

 

函數(shù)名: _ungetchar

原 型: extern char _ungetchar(char);

功 能: _ungetchar將傳入字符送回輸入緩沖區(qū)并將其值返回給調(diào)用者,下次使用getkey

時可獲得該字符,寫回多個字符是不可能的。

 

函數(shù)名: putchar

原 型: extern putchar(char);

功 能: putchar通過8051串口輸出‘char’,和函數(shù)getkey一樣,putchar是改變整個

輸出機制所需修改的唯一一個函數(shù)。

 

函數(shù)名: printf

原 型: extern int printf(const char*,…);

功 能: printf以一定格式通過8051串口輸出數(shù)值和串,返回值為實際輸出的字符數(shù),

參量可以是指針、字符或數(shù)值,第一個參量是格式串指針。

注:允許作為printf參量的總字節(jié)數(shù)由C51庫限制,因為8051結(jié)構(gòu)上存貯空間有限,在SMALL和COMPACT模式下,最大可傳遞15個字節(jié)的參數(shù)(即5個指針,或1個指針和3個長字節(jié)),在LARGE模式下,至多可傳遞40個字節(jié)的參數(shù)。格式控制串包含下列域(方括號內(nèi)的域是可能的):

%[flags][width][.precision]type

“width”域定義了參量欲顯示的字符數(shù),它必須是一個十進制數(shù),如果實際顯示的字符數(shù)小于“width”,輸出左端補以空格,如果“width”域以0開始,則左端補0。

“flag”域用來定義下面選項:

 

 

Falg

 

意 義

 

-

 

輸出左齊

 

+

 

輸出值如果是有符號數(shù)值,則加上+/-號

 

‘ ‘(空格)

 

輸出值如果為正則左邊補以空格顯示

 

#

 

如果它與0,x或X聯(lián)用,則在輸出前加上字符0、0x,0X。當(dāng)與值類型g、G、f、e、E聯(lián)用時,‘#’使輸出數(shù)產(chǎn)生一個十進制小數(shù)點。

 

b,B

 

它們與格式類型d、i、o、u、x、X聯(lián)用,這樣參量類型被接受為‘[unsigned]char’,如:%bu,%bd或%bx。

 

L,L

 

它們與格式類型d、i、o、u、x、X聯(lián)用,這樣參量類型被接受為‘[unsigned]long’,如:%lu,%ld或%lx。

 

*

 

下一個參量不作輸出。

 

 

“type“域定義參量如下類型:

 

 

字 符

 

類 型

 

輸 出 格 式

 

d

 

int

 

有符號十進制數(shù)(16位)

 

U

 

int

 

無符號十進制數(shù)

 

o

 

int

 

無符號八進制數(shù)

 

X,x

 

int

 

無符號十六進制數(shù)

 

f

 

float

 

[-]dddd.dddd形式的浮點數(shù)

 

e,E

 

float

 

[-]d.ddddE[sign]dd形式的浮點數(shù)

 

g,G

 

float

 

e或f形式浮點數(shù),看哪一種輸出形式好。

 

c

 

char

 

字符

 

s

 

pointer

 

指向一個帶結(jié)束符號的串

 

p

 

pointer

 

帶存貯器指示符和偏移的指針。M:aaaa。

M:=C(ode),D(ata),I(data),P(data) aaaa:指針偏移值。

 

 

例子:

printf(“Int-Val%d,Char-Val%bd,Long-Val%d”,I,c,l);

printf(“String%s,Character%c”,array,character);

printf(“Pointer%p”,&array[10]);

 

函數(shù)名: sprintf

原 型: extern int sprintf(char *s,const char*,…);

功 能: sprintf與printf相似,但輸出不顯示在控制臺上,而是通過一個指針S,送入

可尋址的緩沖區(qū)。

注:sprintf允許輸出的參量總字節(jié)數(shù)與printf完全相同。

 

函數(shù)名: puts

原 型: extern int puts(const char*,…);

功 能: puts將串‘s’和換行符寫入控制臺設(shè)備,錯誤時返回EOF,否則返回一非負數(shù)。

 

函數(shù)名: scanf

原 型: extern int scanf(const char*,…);

功 能: scanf在格式串控制下,利用getcha函數(shù)由控制臺讀入數(shù)據(jù),每遇到一個值(符

號格式串規(guī)定),就將它按順序賦給每個參量,注意每個參量必須都是指針。scanf返回它所發(fā)現(xiàn)并轉(zhuǎn)換的輸入項數(shù)。若遇到錯誤返回EOF。格式串包括:

l 空格、制表符等,這些空白字符被忽略。

l 字符,除需匹配的“%”(格式控制字符)外。

l 轉(zhuǎn)換指定字符“%”,后隨幾個可選字符;賦值抑制符“*”,一個指定最大域?qū)挼臄?shù)。

注:scanf參量允許的總字節(jié)數(shù)與printf相同,格式控制串可包括下列域(方括號內(nèi)是可選的):

%[flags][width]type

格式串總是以百分號開始,每個域包含一個或多個字符或數(shù)。

“width”域定義了參量可接受的字符數(shù),“width”必須是一個正十進制數(shù)。如果實際輸入字符數(shù)量小于“width”,則不會進行填充。

‘flag’域用來定義下面選項:

 

 

Flag

 

意 義

 

*

 

輸入被忽略

 

b,h

 

它們用作格式類型d,i,o,u和x的前綴,用這些變量可定義參量是字符指針還是無符號字符指針。如%bu,%bd,%bx。

 

L

 

它們被作格式類型d,i,o,u和x的前綴,使用這個前綴可定義參量是長指針還是無符號字長指針。如%lu,%ld,%lx。

 

 

“type”域定義參量為如下類型:

 

 

描 述 符

 

類 型

 

輸 入 格 式

 

d

 

ptr to int

 

有符號十進制數(shù)(16位)

 

i

 

ptr to int

 

如C中記號一樣,整型值

 

u

 

ptr to int

 

無符號十進制數(shù)

 

o

 

ptr to int

 

無符號八進制數(shù)

 

x

 

ptr to int

 

無符號十六進制數(shù)

 

f,e,g

 

ptr to float

 

浮點數(shù)

 

c

 

ptr to char

 

一個字符

 

s

 

ptr to string

 

一個字串

 

例子:

scanf(“%d%bd%ld”,&i,&c,&l);

scanf(“%f”,&f);

scanf(“%3s,%c”,&string[0],&character);

 

函數(shù)名: sscanf

原 型: extern int sscanf(const *s,const char*,…);

功 能: sscanf與scanf方式相似,但串輸入不是通過控制臺,而是通過另一個以空結(jié)束

的指針。

注:sscanf參量允許的總字節(jié)數(shù)由C-51庫限制,這是因為8051處理器結(jié)構(gòu)內(nèi)存的限制,在SMALL和COMPACT模式,最大允許15字節(jié)參數(shù)(即至多5個指針,或2個指針,2個長整型或1個字符型)的傳遞。在LARGE模式下,最大允許傳送40個字節(jié)的參數(shù)。

3.3 STRING.H:串函數(shù)

串函數(shù)通常將指針串作輸入值。一個串就包括2個或多個字符。串結(jié)以空字符表示。在函數(shù)memcmp,memcpy,memchr,memccpy,memmove和memset中,串長度由調(diào)用者明確規(guī)定,使這些函數(shù)可工作在任何模式下。

 

函數(shù)名: memchr

原 型: extern void *memchr(void *sl, char val,int len);

功 能: memchr順序搜索s1中的len個字符找出字符val,成功時返回s1中指向val的

指針,失敗時返回NULL。

 

函數(shù)名: memcmp

原 型: extern char memcmp(void *sl, void *s2,int len);

功 能: memcmp逐個字符比較串s1和s2的前l(fā)en個字符。相等時返回0,如果串s1大

于或小于s2,則相應(yīng)返回一個正數(shù)或負數(shù)。

 

 

函數(shù)名: memcpy

原 型: extern void *memcpy(void *dest, void *src,int len);

功 能: memcpy由src所指內(nèi)存中拷貝len個字符到dest中,返回批向dest中的最后一

個字符的指針。如果src和dest發(fā)生交迭,則結(jié)果是不可預(yù)測的。

 

函數(shù)名: memccpy

原 型: extern void *memccpy(void *dest, void *src,char val,int len);

功 能: memccpy拷貝src中l(wèi)en個字符到dest中,如果實際拷貝了len個字符返回NULL。

拷貝過程在拷貝完字符val后停止,此時返回指向dest中下一個元素的指針。

 

函數(shù)名: memmove

原 型: extern void *memmove(void *dest, void *src,int len);

功 能: memmove工作方式與memcpy相同,但拷貝區(qū)可以交迭。

 

函數(shù)名: memset

原 型: extern void *memset(void *s, char val,int len);

功 能: memset 將val值填充指針s中l(wèi)en個單元。

 

函數(shù)名: strcat

原 型: extern char *strcat(char *s1, char *s2);

功 能: strcat將串s2拷貝到串s1結(jié)尾。它假定s1定義的地址區(qū)足以接受兩個串。返

回指針指向s1串的第一字符。

 

函數(shù)名: strncat

原 型: extern char *strncat(char *s1, char *s2,int n);

功 能: strncat拷貝串s2中n個字符到串s1結(jié)尾。如果s2比n短,則只拷貝s2。

 

函數(shù)名: strcmp

原 型: extern char strcmp(char *s1, char *s2);

功 能: strcmp比較串s1和s2,如果相等返回0,如果s1s2則返回

一個正數(shù)。

 

函數(shù)名: strncmp

原 型: extern char strncmp(char *s1, char *s2,int n);

功 能: strncmp比較串s1和s2中前n個字符,返回值與strncmp相同。

 

函數(shù)名: strcpy

原 型: extern char *strcpy(char *s1, char *s2);

功 能: strcpy將串s2包括結(jié)束符拷貝到s1,返回指向s1的第一個字符的指針。

 

函數(shù)名: strncpy

原 型: extern char *strncpy(char *s1, char *s2,int n);

功 能: strncpy與strcpy相似,但只拷貝n個字符。如果s2長度小于n,則s1串以‘0’

補齊到長度n。

 

函數(shù)名: strlen

原 型: extern int strlen(char *s1);

功 能: strlen返回串s1字符個數(shù)(包括結(jié)束字符)。

函數(shù)名: strchr,strpos

原 型: extern char *strchr(char *s1, char c);

extern int strpos(char *s1,char c);

功 能: strchr搜索s1串中第一個出現(xiàn)的‘c’字符,如果成功,返回指向該字符的別指

針,搜索也包括結(jié)束符。搜索一個空字符返回指向空字符的指針而不是空指針。

strpos與strchr相似,但它返回字符在串中的位置或-1,s1串的第一個字符位置是0。

 

函數(shù)名: strrchr,strrpos

原 型: extern char *strrchr(char *s1, char c);

extern int strrpos(char *s1,char c);

功 能: strrchr搜索s1串中最后一個出現(xiàn)的‘c’字符,如果成功,返回指向該字符的

指針,否則返回NULL。對s1搜索也返回指向字符的指針而不是空指針。

strrpos與strrchr相似,但它返回字符在串中的位置或-1。

 

函數(shù)名: strspn,strcspn,strpbrk,strrpbrk

原 型: extern int strspn(char *s1, char *set);

extern int strcspn(char *s1,char *set);

extern char *strpbrk(char *s1,char *set);

extern char *strpbrk(char *s1,char *set);

功 能: strspn搜索s1串中第一個不包含在set中的字符,返回值是s1中包含在set里

字符的個數(shù)。如果s1中所有字符都包含在set里,則返回s1的長度(包括結(jié)束符)。如果s1是空串,則返回0。

strcspn與strspn類似,但它搜索的是s1串中的第一個包含在set里的字符。strpbrk與strspn很相似,但它返回指向搜索到字符的指針,而不是個數(shù),如果未找到,則返回NULL。

strrpbrk與strpbrk相似,但它返回s1中指向找到的set字集中最后一個字符的指針。

3.4 STDLIB.H:標準函數(shù)

函數(shù)名: atof

原 型: extern double atof(char *s1);

功 能: atof將s1串轉(zhuǎn)換為浮點值并返回它。輸入串必須包含與浮點值規(guī)定相符的數(shù)。

C51編譯器對數(shù)據(jù)類型float和double相同對待。

 

函數(shù)名: atol

原 型: extern long atol(char *s1);

功 能: atol將s1串轉(zhuǎn)換成一個長整型值并返回它。輸入串必須包含與長整型值規(guī)定相

符的數(shù)。

 

函數(shù)名: atoi

原 型: extern int atoi(char *s1);

功 能: atoi將s1串轉(zhuǎn)換為整型數(shù)并返回它。輸入串必須包含與整型數(shù)規(guī)定相符的數(shù)。

3.5 MATH.H:數(shù)學(xué)函數(shù)

函數(shù)名: abs,cabs,fabs,labs

原 型: extern int abs(int va1);

extern char cabs(char val);

extern float fabs(float val);

extern long labs(long val);

功 能: abs決定了變量val的絕對值,如果val為正,則不作改變返回;如果為負,則

返回相反數(shù)。這四個函數(shù)除了變量和返回值的數(shù)據(jù)不一樣外,它們功能相同。

 

函數(shù)名: exp,log,log10

原 型: extern float exp(float x);

extern float log(float x);

extern float log10(float x);

功 能:exp返回以e為底x的冪,log返回x的自然數(shù)(e=2.718282),log10返回x以10

為底的數(shù)。

 

函數(shù)名: sqrt

原 型: extern float sqrt(float x);

功 能: sqrt返回x的平方根。

 

函數(shù)名:rand,srand

原 型: extern int rand(void);

extern void srand(int n);

功 能: rand返回一個0到32767之間的偽隨機數(shù)。srand用來將隨機數(shù)發(fā)生器初始化成

一個已知(或期望)值,對rand的相繼調(diào)用將產(chǎn)生相同序列的隨機數(shù)。

函數(shù)名: cos,sin,tan

原 型: extern float cos(flaot x);

extern float sin(flaot x);

extern flaot tan(flaot x);

功 能: cos返回x的余弦值。Sin返回x的正弦值。tan返回x的正切值,所有函數(shù)變量

范圍為-π/2~+π/2,變量必須在±65535之間,否則會產(chǎn)生一個NaN錯誤。

 

 

函數(shù)名: acos,asin,atan,atan2

原 型: extern float acos(float x);

extern float asin(float x);

extern float atan(float x);

extern float atan(float y,float x);

功 能: acos返回x的反余弦值,asin返回x的正弦值,atan返回x的反正切值,它們

的值域為-π/2~+π/2。atan2返回x/y的反正切,其值域為-π~+π。

 

函數(shù)名: cosh,sinh,tanh

原 型: extern float cosh(float x);

extern float sinh(float x);

extern float tanh(float x);

功 能: cosh返回x的雙曲余弦值;sinh返回x的雙曲正弦值;tanh返回x的雙曲正切

值。

 

函數(shù)名: fpsave,fprestore

原 型: extern void fpsave(struct FPBUF *p);

extern void fprestore (struct FPBUF *p);

功 能: fpsave保存浮點子程序的狀態(tài)。fprestore將浮點子程序的狀態(tài)恢復(fù)為其原始狀

態(tài),當(dāng)用中斷程序執(zhí)行浮點運算時這兩個函數(shù)是有用的。

3.6 ABSACC.H:絕對地址訪問

函數(shù)名: CBYTE,DBYTE,PBYTE,XBYTE

原 型: #define CBYTE((unsigned char *)0x50000L)

#define DBYTE((unsigned char *)0x40000L)

#define PBYTE((unsigned char *)0x30000L)

#define XBYTE((unsigned char *)0x20000L)

功 能: 上述宏定義用來對8051地址空間作絕對地址訪問,因此,可以字節(jié)尋址。CBYTE

尋址CODE區(qū),DBYTE尋址DATA區(qū),PBYTE尋址XDATA區(qū)(通過MOVX @R0命令),XBYTE尋址XDATA區(qū)(通過MOVX @DPTR命令)。

例:下列指令在外存區(qū)訪問地址0x1000

xval=XBYTE[0x1000];

XBYTE[0X1000]=20;

通過使用#define指令,用符號可定義絕對地址,如符號X10可與XBYTE[0x1000]地址相等:#define X10 XBYTE[0x1000]。

 

函數(shù)名: CWORD,DWORD,PWORD,XWORD

原 型: #define CWORD((unsigned int *)0x50000L)

#define DWORD((unsigned int *)0x40000L)

#define PWORD((unsigned int *)0x30000L)

#define XWORD((unsigned int *)0x20000L)

功 能:這些宏與上面相似,只是它們指定的類型為unsigned int。通過靈活的數(shù)據(jù)類型,

所有地址空間都可以訪問。

3.7 INTRINS.H:內(nèi)部函數(shù)

函數(shù)名: _crol_,_irol_,_lrol_

原 型: unsigned char _crol_(unsigned char val,unsigned char n);

unsigned int _irol_(unsigned int val,unsigned char n);

unsigned int _lrol_(unsigned int val,unsigned char n);

功 能:_crol_,_irol_,_lrol_以位形式將val左移n位,該函數(shù)與8051“RLA”指令

相關(guān),上面幾個函數(shù)不同于參數(shù)類型。

例:

#include

main()

{

unsigned int y;

y=0x00ff;

y=_irol_(y,4); /*y=0x0ff0*/

}

 

函數(shù)名: _cror_,_iror_,_lror_

原 型: unsigned char _cror_(unsigned char val,unsigned char n);

unsigned int _iror_(unsigned int val,unsigned char n);

unsigned int _lror_(unsigned int val,unsigned char n);

功 能:_cror_,_iror_,_lror_以位形式將val右移n位,該函數(shù)與8051“RRA”指令

相關(guān),上面幾個函數(shù)不同于參數(shù)類型。

例:

#include

main()

{

unsigned int y;

y=0x0ff00;

y=_iror_(y,4); /*y=0x0ff0*/

}

 

函數(shù)名: _nop_

原 型: void _nop_(void);

功 能:_nop_產(chǎn)生一個NOP指令,該函數(shù)可用作C程序的時間比較。C51編譯器在_nop_函

數(shù)工作期間不產(chǎn)生函數(shù)調(diào)用,即在程序中直接執(zhí)行了NOP指令。

例:

P()=1;

_nop_();

P()=0;

函數(shù)名: _testbit_

原 型:bit _testbit_(bit x);

功 能:_testbit_產(chǎn)生一個JBC指令,該函數(shù)測試一個位,當(dāng)置位時返回1,否則返回0。

如果該位置為1,則將該位復(fù)位為0。8051的JBC指令即用作此目的。 _testbit_只能用于可直接尋址的位;在表達式中使用是不允許的。

STDARG.H:變量參數(shù)表

C51編譯器允許再入函數(shù)的變量參數(shù)(記號為“…”)。頭文件STDARG.H允許處理函數(shù)的參數(shù)表,在編譯時它們的長度和數(shù)據(jù)類型是未知的。為此,定義了下列宏。

 

宏 名: va_list

功 能: 指向參數(shù)的指針。

 

宏 名: va_stat(va_list pointer,last_argument)

功 能: 初始化指向參數(shù)的指針。

 

宏 名: type va_arg(va_list pointer,type)

功 能:返回類型為type的參數(shù)。

 

宏 名: va_end(va_list pointer)

功 能: 識別表尾的啞宏。

3.8 SETJMP.H:全程跳轉(zhuǎn)

Setjmp.h中的函數(shù)用作正常的系列數(shù)調(diào)用和函數(shù)結(jié)束,它允許從深層函數(shù)調(diào)用中直接返回。

 

函數(shù)名: setjmp

原 型: int setjmp(jmp_buf env);

功 能: setjmp將狀態(tài)信息存入env供函數(shù)longjmp使用。當(dāng)直接調(diào)用setjmp 時返回值

是0,當(dāng)由longjmp調(diào)用時返回非零值,setjmp只能在語句IF或SWITCH中調(diào)用一次。

 

函數(shù)名: long jmp

原 型: long jmp(jmp_buf env,int val);

功 能:longjmp恢復(fù)調(diào)用setjmp時存在env中的狀態(tài)。程序繼續(xù)執(zhí)行,似乎函數(shù)setjmp

已被執(zhí)行過。由setjmp返回的值是在函數(shù)longjmp中傳送的值val,由setjmp調(diào)用的函數(shù)中的所有自動變量和未用易失性定義的變量的值都要改變。

3.9 REGxxx.H:訪問SFR和SFR-BIT地址

文件REG51.H,REG52.H和REG552.H允許訪問8051系列的SFR和SFR-bit的地址,這些文件都包含#include指令,并定義了所需的所有SFR名以尋址8051系列的外圍電路地址,對于8051系列中其它一些器件,用戶可用文件編輯器容易地產(chǎn)生一個“.h”文件。

下例表明了對8051 PORT0和PORT1的訪問:

#include

main() {

if(p0==0x10) p1=0x50;

}

 

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉