第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試_第1頁
第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試_第2頁
第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試_第3頁
第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試_第4頁
已閱讀5頁,還剩84頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試disable任課教師:劉忠國山東大學(xué)課程中心網(wǎng)站:

http:///G2S/stcmcu.cc宏晶官方網(wǎng)站:http://STC單片機(jī)編譯(匯編)/編程(燒錄)/仿真工具說明書;stc15系列單片機(jī)器件手冊等keilμvision軟件下載及指導(dǎo)手冊(Help→μvisionHelp)/KeilSoftware–Cx51編譯器用戶手冊:Cx51編譯器--對傳統(tǒng)和擴(kuò)展的8051微處理器的優(yōu)化的C編譯器和庫參考2第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試本章學(xué)習(xí)目標(biāo)掌握單片機(jī)C語言程序中的常用功能掌握KeilC的程序設(shè)計(jì)掌握IAP15W4K58S4單片機(jī)C語言程序調(diào)試過程3第五章單片機(jī)的C語言程序設(shè)計(jì)及仿真調(diào)試§5.1C51程序的基本語法5.1.1關(guān)鍵字5.1.2C51程序的一般結(jié)構(gòu)5.1.3數(shù)據(jù)類型5.1.4運(yùn)算符和表達(dá)式§5.2KeilC51程序的語句5.2.1表達(dá)式語句5.2.2條件語句5.2.3開關(guān)語句5.2.4循環(huán)語句5.2.5goto、break、continue和return語句§5.3函數(shù)5.3.1函數(shù)的定義與調(diào)用5.3.2KeilC51函數(shù)§5.4KeilC51庫函數(shù)§5.5預(yù)處理命令§5.6單片機(jī)C語言程序框架4匯編語言和C語言的選擇問題設(shè)計(jì)規(guī)模較小的嵌入式應(yīng)用系統(tǒng)時(shí),可以使用匯編語言。因?yàn)榇a一般不長,且較簡單。當(dāng)程序比較復(fù)雜,且沒有很好的注釋時(shí),使用匯編語言編寫的程序,可讀性和可維護(hù)性會(huì)很差,代碼的可重用性也比較低。使用C語言編程,編寫簡單、直觀易讀、便于維護(hù)、通用性好。在控制任務(wù)比較復(fù)雜或者具有大量運(yùn)算的系統(tǒng)中,C語言優(yōu)勢明顯。由于模塊化,用C語言編寫的程序具有很好的可移植性。5§5.1C51程序的基本語法1.標(biāo)準(zhǔn)C語言(ANSIC)的關(guān)鍵字(1)數(shù)據(jù)類型關(guān)鍵字1)基本數(shù)據(jù)類型void、char、int、float、double2)類型修飾關(guān)鍵字short、long、signed、unsigned3)復(fù)雜類型關(guān)鍵字struct、union、enum、typedef、sizeof4)存儲(chǔ)級別關(guān)鍵字auto、static、register、extern、const、volatile§5.1.1關(guān)鍵字6§5.1.1關(guān)鍵字(2)流程控制關(guān)鍵字1)跳轉(zhuǎn)結(jié)構(gòu)return、continue、break、goto2)分支結(jié)構(gòu)if、else、switch、

case、default3)循環(huán)結(jié)構(gòu)for、do、

while2.KeilC51編譯器支持的關(guān)鍵字bit、sbit、sfr、sfr16、data、bdata、idata、pdata、

xdata、

code、

interrupt、

reentrant、using7預(yù)處理命令

//以#開頭的命令,用于包含頭文件、定義常數(shù)等全局變量聲明

//全局變量雖然方便傳遞參數(shù),但不宜多函數(shù)1的聲明......函數(shù)n的聲明voidmain(void) //主函數(shù){

局部變量聲明

//局部變量只能在所定義的函數(shù)內(nèi)部引用

可執(zhí)行語句

函數(shù)調(diào)用

無限循環(huán)}§5.1.2C51程序的一般結(jié)構(gòu)8//一般函數(shù)的定義函數(shù)1(形式參數(shù)聲明){

局部變量聲明

可執(zhí)行語句}......函數(shù)n(形式參數(shù)聲明){

局部變量聲明

可執(zhí)行語句}§5.1.2C51程序的一般結(jié)構(gòu)9//中斷函數(shù)的實(shí)現(xiàn)voidISRname(void)interruptn//n為中斷號{

局部變量聲明

可執(zhí)行語句}注意如下幾點(diǎn):(1)所有函數(shù)以花括號“{”開始,以花括號“}”結(jié)束,包含在“{}”內(nèi)的部分稱為函數(shù)體?;ɡㄌ柋仨毘蓪Τ霈F(xiàn),如果一個(gè)函數(shù)內(nèi)有多對花括號,則最外層的花括號為函數(shù)體的范圍。為了增加程序的可讀性,應(yīng)采用縮進(jìn)方式書寫?!?.1.2C51程序的一般結(jié)構(gòu)10注意如下幾點(diǎn):(2)建議一行寫一條語句,每條語句最后必須以一個(gè)分號“;”結(jié)尾。(3)每個(gè)變量必須先定義后引用。在函數(shù)內(nèi)部定義的變量為局部變量,又稱為內(nèi)部變量,只有定義它的那個(gè)函數(shù)才能使用。在函數(shù)外部定義的變量為全局變量,又稱為外部變量,在定義它的那個(gè)程序文件中的函數(shù)都可以使用。(4)程序語句的注釋放在雙斜杠“//”之后,或者放在“/*......*/”之內(nèi)?!?.1.2C51程序的一般結(jié)構(gòu)111.常量和變量常量包括整形常量、浮點(diǎn)型常量、字符型常量(如‘a(chǎn)’:單引號字符

)

及字符串常量(雙引號單個(gè)或多個(gè)字符,如"a","Happy")等。變量是一種在程序執(zhí)行過程中其值不斷變化的量。使用一個(gè)變量之前,必須先進(jìn)行定義。§5.1.3數(shù)據(jù)類型

1.常量和變量2.?dāng)?shù)據(jù)類型(1)基本數(shù)據(jù)類型基本數(shù)據(jù)類型是不可以再分解為其他類型的數(shù)據(jù)類型。如char(字符型)、int(整型)、long(長整型)、float(浮點(diǎn)型)等。122.?dāng)?shù)據(jù)類型(2)構(gòu)造數(shù)據(jù)類型構(gòu)造數(shù)據(jù)類型是根據(jù)已定義的一個(gè)或多個(gè)數(shù)據(jù)類型用構(gòu)造的方法來定義的?!?.1.3

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

2.?dāng)?shù)據(jù)類型在C語言中,構(gòu)造類型有以下幾種:數(shù)組類型結(jié)構(gòu)類型聯(lián)合類型13(3)指針類型指針是一種特殊的,具有重要作用的數(shù)據(jù)類型。用來表示某個(gè)量在內(nèi)存中的地址。§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型(4)空類型函數(shù)調(diào)用后并不需要向調(diào)用者返回函數(shù)值,這種函數(shù)可以定義為“空類型”。其類型說明符為void。14C51編譯器除了支持上述數(shù)據(jù)類型外,還支持以下幾種擴(kuò)充數(shù)據(jù)類型:(1)bit:位類型。bit型變量的位地址由編譯器分配。(2)sfr:特殊功能寄存器,用來控制中斷、定時(shí)器、計(jì)數(shù)器、串口、I/O及其他部件。(3)sfr16:16位特殊功能寄存器。(4)sbit:位尋址?!?.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型bit與sbit的用法區(qū)別:定義的bit型變量的位地址在00H~7FH之間,具體地址值不定,由編譯器隨機(jī)分配。sbit位尋址:該數(shù)據(jù)類型用一個(gè)指定的變量作為基地址然后用其位的位置來得到一個(gè)實(shí)際的位地址。15(1)bit:位類型??梢远x一個(gè)位變量,但不能定義位指針,也不能定義位數(shù)組。

C51程序中,函數(shù)參數(shù)和返回值也可以是位變量。例:bit

finish_flag=0;bittestfunc(bitvar1,bitvar2){

...

return(0);};§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型所有bit型變量的都被定位在8051片內(nèi)RAM的可位尋址區(qū)20H~2FH,共16個(gè)字節(jié),所以最多只能聲明128個(gè)bit型位變量。16(2)sfr:字節(jié)尋址。語法如下:

sfrsfr_name=int_constant;如

sfrP0=0x80;

0x80為P0口的地址,“=”后為常數(shù),且這個(gè)常數(shù)必須在特殊功能寄存器的地址范圍內(nèi),即0x80到0xFF之間?!?.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型(3)sfr16:字尋址如sfr16DPTR=0x82;

指定DPTR的地址DPL=0x82,DPH=0x83。(4)sbit:位尋址。用于定義可位尋址變量??啥x8051片內(nèi)RAM的可尋址位,或特殊功能寄存器的可尋址位。17§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型(4)

sbit:位尋址。定義可位尋址變量。定義片內(nèi)RAM的可尋址位,

或特殊功能寄存器的可尋址位。C51編譯器提供了存儲(chǔ)類型bdata,bdata存儲(chǔ)類型變量位于片內(nèi)RAM的可位尋址區(qū),可字節(jié)尋址,或位尋址,因此bdata型變量可用sbit指定其中任意位為可位尋址變量。需注意:使用bdata和sbit定義的變量必須是全局變量,并且用sbit定義為位尋址變量時(shí)要求基址對象的存儲(chǔ)器類型必須為bdata

(特殊功能寄存器除外)。sbit聲明方法:

sbitbitname=bdata型變量或sfr_name^bit_number;其中,sfr_name

是已定義SFR的名字,bit_number是位號,其數(shù)值取決于基址對象的數(shù)據(jù)類型,對char和SFR而言是(0~7)

,對int型而言是(0~15),對long型而言是(0~31)。18§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型sbit聲明方法:

sbitbitname=bdata型變量或sfr_name^bit_number;其中,sfr_name

是已定義SFR的名字,bit_number是位號,其數(shù)值取決于基址對象的數(shù)據(jù)類型,對char和SFR而言是(0~7),對int型而言是(0~15),對long型而言是(0~31)。如:unsignedcharbdataflag;//flag為bdata型無符號字符變量int

bdata

ibase

;//定義ibase為bdata整型變量使用sbit可位尋址變量如下:

sbitflag0=flag^0

;//定義flag0為flag的第0位

sbitmybit15=ibase^15;//mybit15為ibase的第15位

sbitCY=PSW^7;//定義CY為PSW的第7位sbitP00=P0^0;//定義P0.0口線的名稱是P0019sbit可以有下面聲明方法:方法1:sbitbitname=sfr_name^bit_number;其中,sfr_name必須是已定義的SFR的名字,bit_number是位號(0~7)。如:sbitCY=PSW^7;//定義CY為PSW的第7位。方法2:sbitbitname=sfr_address^bit_number;

其中,sfr_address是SFR所在的地址(0x80~0xff),bit_number是位號(0~7)。如:sbitOV=0xD0^2;//定義PSW中的OV位方法3:sbitbitname=bit_address;其中,bit_address是位地址。如:sbitEA=0xAF;//第0xAF位為EA§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型20KeilC51編譯器支持的數(shù)據(jù)類型如表5-1所示。數(shù)據(jù)類型位數(shù)(bit)字節(jié)數(shù)(byte)取值范圍bit11/80或1signedchar81-128~+127unsignedchar810~255enum8/161or2-128~+127or-32768~+32767signedshort162-32768~+32767unsignedshort1620~65535signedint162-32768~+32767unsignedint1620~65535signedlong324-2147483648~+2147483647unsignedlong3240~4294967295float324+1.175494E38~+3.402823E+38sbit11/80或1sfr810~255sfr161620~65535表5-1KeilC51編譯器支持的數(shù)據(jù)類型§5.1.3

數(shù)據(jù)類型2.?dāng)?shù)據(jù)類型213.存儲(chǔ)器類型存儲(chǔ)器類型取值范圍data默認(rèn)存儲(chǔ)器類型,低128字節(jié)內(nèi)部RAM,DATA區(qū)(00H~7FH地址空間),訪問速度最快。bdata可位尋址內(nèi)部RAM,BDATA區(qū)(20H~2FH地址空間),允許位和字節(jié)混合訪問。idata256字節(jié)內(nèi)部RAM,IDATA區(qū)(00H~FFH地址空間),允許訪問全部內(nèi)部單元。pdata分頁尋址外部RAM,PDATA區(qū)(0000H~FFFFH地址空間),用MOVX@Ri指令訪問。xdata外部RAM,XDATA區(qū)(0000H~FFFFH地址空間),用MOVX@DPTR指令訪問。code程序存儲(chǔ)區(qū),CODE區(qū)(0000H~FFFFH地址空間),用MOVC@A+DPTR指令訪問。表5-2KeilC51編譯器支持的存儲(chǔ)器類型對變量定義格式:數(shù)據(jù)類型

[存儲(chǔ)器類型]變量名表;

§5.1.3

數(shù)據(jù)類型3.存儲(chǔ)器類型

例如:unsignedchardatabuffer;22存儲(chǔ)類型的指定:變量或參數(shù)的存儲(chǔ)類型可由存儲(chǔ)模式指定缺省類型,也可由關(guān)鍵字code、data、idata、xdata、pdata直接聲明指定。例如:unsigned

char

databuffer;

databuffer;//沒有指定數(shù)據(jù)類型,默認(rèn)為int型unsigned

char

code

numtab[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xFB,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};

//定義LED顯示字模(參見137頁)unsigned

char

xdata

arr[10][4][4];§5.1.3

數(shù)據(jù)類型3.存儲(chǔ)器類型對變量定義格式:數(shù)據(jù)類型

[存儲(chǔ)器類型]變量名表;

23§5.1.3

數(shù)據(jù)類型3.存儲(chǔ)器類型數(shù)據(jù)存儲(chǔ)類型的指定:變量或函數(shù)參數(shù)存儲(chǔ)類型可由存儲(chǔ)模式

(Small,large,Compact)(OptionsforTarget‘Target1’...選項(xiàng))指定缺省存儲(chǔ)類型;在small模式下,函數(shù)參數(shù)和局部變量位于由data定義的單片機(jī)片內(nèi)數(shù)據(jù)RAM(00~7FH)中;在compact模式下,函數(shù)參數(shù)和局部變量位于pdata定義的擴(kuò)展數(shù)據(jù)RAM中(訪問用MOVX@Ri)。在large模式下,函數(shù)參數(shù)和局部變量位于xdata定義的擴(kuò)展數(shù)據(jù)RAM中(訪問用MOVX@DPTR)數(shù)據(jù)存儲(chǔ)模式(Small,large,Compact)24在Xtal(MHz)右側(cè)框輸入6,其余按默認(rèn)設(shè)置。4-3匯編語言程序調(diào)試Project窗口,選中Target1,并單擊右鍵,出現(xiàn)浮動(dòng)菜單。浮動(dòng)菜單中選中OptionsforTarget‘Target1’...選項(xiàng)。出現(xiàn)OptionsforTarget‘Target1’對話框界面。在該界面中,點(diǎn)擊Target標(biāo)簽。在該標(biāo)簽界面中,按下面設(shè)置參數(shù):在此設(shè)置使用晶振的頻率

針對目標(biāo)硬件設(shè)置工具選項(xiàng)MemoryModel右側(cè)下拉選擇:Small,Compact,large的存儲(chǔ)模式。254.關(guān)于指針數(shù)據(jù)類型指針變量的值是一個(gè)地址,這個(gè)地址不僅可以是變量的地址,也可以是其他數(shù)據(jù)結(jié)構(gòu)的地址。KeilC51編譯器支持兩種指針類型:一般指針(GenericPointer)和存儲(chǔ)器指針(MemorySpecificPointer,

指定存儲(chǔ)區(qū)指針)。一般指針的聲明和使用均與標(biāo)準(zhǔn)C相同,同時(shí)還可以說明指針的存儲(chǔ)類型(見下頁)。char*s

;/*stringptr*/int*numptr;/*intptr*/§5.1.3

數(shù)據(jù)類型4.關(guān)于指針數(shù)據(jù)類型26一般指針的聲明和使用均與標(biāo)準(zhǔn)C相同,同時(shí)還可以說明指針的存儲(chǔ)類型。char*s

;/*stringptr*/int*numptr;/*intptr*/可用存儲(chǔ)類型標(biāo)識(shí)符指定一個(gè)通用指針的存儲(chǔ)區(qū)如:

char*xdatastrptr;/*genericptrstoredinxdata*/int*datanumptr;/*genericptrstoredindata*/long*idatavarptr;/*genericptrstoredinidata*/這些例子指向可能保存在任何存儲(chǔ)區(qū)中的變量但是指針分別保存在xdata、data和idata中。§5.1.3

數(shù)據(jù)類型4.關(guān)于指針數(shù)據(jù)類型27一般指針用3個(gè)字節(jié)存放:存儲(chǔ)器類型,存儲(chǔ)器地址高8位偏移量和低8位偏移量。

char

data*str;

//str指向data區(qū)中char型數(shù)據(jù)

int

xdata*pow;

//pow指向外部RAM的int型整數(shù)這種指針存放時(shí),只需1(或2)個(gè)字節(jié)就夠了,因只需存放偏移量。

存儲(chǔ)器指針(指定存儲(chǔ)區(qū)指針),說明時(shí)即指定了存儲(chǔ)類型,例如:

4.關(guān)于指針數(shù)據(jù)類型存儲(chǔ)類型Idata/data/bdatapdataxdataCode編碼值0x000xFE0x010xFF存放數(shù)據(jù)的存儲(chǔ)器類型存儲(chǔ)器類型是在編譯時(shí)需要的,既已指出,所以指針只需存偏移量即可,參考:KeilHelp:Cx51CompilerUser'sGuide→LanguageExtensions→Pointers28§5.1.3

數(shù)據(jù)類型4.關(guān)于指針數(shù)據(jù)類型象一般指針一樣可指定一個(gè)存儲(chǔ)器指針的保存存儲(chǔ)區(qū),即在指針聲明前加存儲(chǔ)類型標(biāo)識(shí)符,例如:unsignedcharxdata

*pt;

//pt本身依存儲(chǔ)模式存放unsignedcharxdata*datapt;//pt被保存在內(nèi)部RAM中unsignedcharxdata

*xdatapt;

//pt被保存在外部RAM中上面的語句都聲明pt為指向保存在外部RAM中unsignedchar數(shù)據(jù)的指針,但pt本身的保存位置卻不同。存儲(chǔ)器指針29運(yùn)算符是告訴編譯程序執(zhí)行特定算術(shù)或邏輯操作的符號,表達(dá)式則是由運(yùn)算符及運(yùn)算對象所組成的具有特定含義的一個(gè)式子。在任意一個(gè)表達(dá)式的后面加一個(gè)分號“;”就構(gòu)成了一個(gè)表達(dá)式語句。C51程序就是由多個(gè)表達(dá)式語句構(gòu)成的語句集合。運(yùn)算符可以分為賦值運(yùn)算符、算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、復(fù)合賦值運(yùn)算符、逗號運(yùn)算符、條件運(yùn)算符、指針和地址運(yùn)算符、強(qiáng)制類型轉(zhuǎn)換運(yùn)算符等?!?.1.4

運(yùn)算符和表達(dá)式301.賦值運(yùn)算符符號“=”為賦值運(yùn)算符,它的作用是將一個(gè)數(shù)據(jù)的值或表達(dá)式的值賦給一個(gè)變量。利用賦值運(yùn)算符將一個(gè)變量與一個(gè)表達(dá)式連接起來的式子成為賦值表達(dá)式,在賦值表達(dá)式的后面加一個(gè)分號“;”便構(gòu)成了賦值語句。§5.1.4

運(yùn)算符和表達(dá)式1.賦值運(yùn)算符312.算術(shù)運(yùn)算符算術(shù)運(yùn)算符用于各類數(shù)值運(yùn)算。包括加(+)、減或取負(fù)值(-)、乘(*)、除(/)、取余(或稱模運(yùn)算,%)、自增(++)、自減(--)共七種。在除法運(yùn)算中,如果是兩個(gè)整數(shù)相除,其結(jié)果為整數(shù),舍去小數(shù)部分。用算術(shù)運(yùn)算符將運(yùn)算對象連接起來的式子就是算術(shù)表達(dá)式。§5.1.4

運(yùn)算符和表達(dá)式

2.算術(shù)運(yùn)算符32計(jì)算一個(gè)算術(shù)表達(dá)式的值時(shí),要按照運(yùn)算符的優(yōu)先級高低順序進(jìn)行。算術(shù)運(yùn)算符中,取負(fù)值(-)的優(yōu)先級最高,其次是乘法(*)、除法(/)和取余(%)運(yùn)算符,加法(+)和減法(-)運(yùn)算符的優(yōu)先級最低。需要時(shí),可在算術(shù)表達(dá)式中必要的地方采用圓括號來改變優(yōu)先級,括號的優(yōu)先級最高。在使用自增(++)運(yùn)算符和自減(--)運(yùn)算符時(shí),要注意運(yùn)算符的位置。例如,++i和i++的意義完全不同,前者為在使用i之前先使i加1,而后者則是在使用i之后再使i加1。在實(shí)際應(yīng)用中,盡可能使用后者的方式,即i++的形式。§5.1.4

運(yùn)算符和表達(dá)式

2.算術(shù)運(yùn)算符333.關(guān)系運(yùn)算符關(guān)系運(yùn)算符用于比較運(yùn)算。包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)和不等于(!=)六種。前四種關(guān)系運(yùn)算符具有相同的優(yōu)先級,后兩種關(guān)系運(yùn)算符也具有相同的優(yōu)先級;但前四種的優(yōu)先級高于后兩種。用關(guān)系運(yùn)算符將兩個(gè)表達(dá)式連接起來即構(gòu)成關(guān)系表達(dá)式?!?.1.4

運(yùn)算符和表達(dá)式3.關(guān)系運(yùn)算符344.邏輯運(yùn)算符邏輯運(yùn)算符包括與(&&)、或(||)、非(!)3種,用于對包含關(guān)系運(yùn)算符的表達(dá)式(稱為條件)進(jìn)行合并或取非運(yùn)算。關(guān)系運(yùn)算符和邏輯運(yùn)算符通常用來判別某個(gè)或某些條件是否滿足,條件滿足時(shí)結(jié)果為1,條件不滿足時(shí)結(jié)果為0?!?.1.4

運(yùn)算符和表達(dá)式4.邏輯運(yùn)算符35與運(yùn)算符(&&)表示2個(gè)條件同時(shí)滿足時(shí)(即2個(gè)條件都為真時(shí)),返回結(jié)果才為真。或運(yùn)算符(||)用于檢查2個(gè)條件中是否有1個(gè)為真的運(yùn)算符,只要有1個(gè)條件為真,運(yùn)算結(jié)果就為真。邏輯非運(yùn)算符(!)表示對表達(dá)式的值取反。上述幾種運(yùn)算符的優(yōu)先級依次為(由高到低):邏輯非→算術(shù)運(yùn)算符→關(guān)系運(yùn)算符→邏輯與→邏輯或?!?.1.4運(yùn)算符和表達(dá)式4.邏輯運(yùn)算符365.位運(yùn)算符C語言提供了6種位運(yùn)算符:按位與(&)、按位或(|)、按位異或(^)、取反(~)、左移(<<)和右移(>>)。位運(yùn)算符的優(yōu)先級從高到低依次為:按位取反(~)→左移(<<)和右移()→按位與(&)→按位異或(^)→按位或(|)?!?.1.4

運(yùn)算符和表達(dá)式5.位運(yùn)算符其功能是參與運(yùn)算的兩數(shù)各對應(yīng)的二進(jìn)位進(jìn)行如下運(yùn)算:37(1)按位與運(yùn)算按位與運(yùn)算符“&”是雙目運(yùn)算符。其功能是參與運(yùn)算的兩數(shù)各對應(yīng)的二進(jìn)位相與。只有對應(yīng)的2個(gè)二進(jìn)位均為1時(shí),結(jié)果位才為1,否則為0。(2)按位或運(yùn)算按位或運(yùn)算符“|”是雙目運(yùn)算符。其功能是參與運(yùn)算的兩數(shù)各對應(yīng)的二進(jìn)位相或。只要對應(yīng)的2個(gè)二進(jìn)位有1個(gè)為1時(shí),結(jié)果位就為1?!?.1.4

運(yùn)算符和表達(dá)式5.位運(yùn)算符38(3)按位異或運(yùn)算按位異或運(yùn)算符“^”是雙目運(yùn)算符。其功能是參與運(yùn)算的兩數(shù)各對應(yīng)的二進(jìn)位相異或。當(dāng)2個(gè)對應(yīng)的二進(jìn)位相異時(shí),結(jié)果為1。(4)求反運(yùn)算求反運(yùn)算符“~”為單目運(yùn)算符,具有右結(jié)合性。其功能是對參與運(yùn)算的數(shù)的各二進(jìn)位按位求反?!?.1.4運(yùn)算符和表達(dá)式5.位運(yùn)算符39(5)左移運(yùn)算左移運(yùn)算符“<<”是雙目運(yùn)算符。其功能把“<<”左邊的運(yùn)算數(shù)的各二進(jìn)位全部左移若干位,由“<<”右邊的數(shù)指定移動(dòng)的位數(shù),高位丟棄,低位補(bǔ)0。(6)右移運(yùn)算右移運(yùn)算符“>>”是雙目運(yùn)算符。其功能是把“>>”左邊的運(yùn)算數(shù)的各二進(jìn)位全部右移若干位,“>>”右邊的數(shù)指定移動(dòng)的位數(shù)。對于有符號數(shù),右移時(shí),符號位將隨同移動(dòng)。當(dāng)為正數(shù)時(shí),最高位補(bǔ)0;為負(fù)數(shù)時(shí),符號位為1,最高位補(bǔ)1?!?.1.4

運(yùn)算符和表達(dá)式5.位運(yùn)算符406.復(fù)合賦值運(yùn)算符在賦值運(yùn)算符“=”之前加上其他二目運(yùn)算符可構(gòu)成復(fù)合賦值運(yùn)算符。構(gòu)成復(fù)合賦值表達(dá)式的一般形式為:

變量雙目運(yùn)算符=

表達(dá)式它等效于:變量=變量運(yùn)算符

表達(dá)式復(fù)合賦值運(yùn)算符有:+=,-=,*=,/=,%=,<<=,>>=,&=,^=,~=,|=。§5.1.4

運(yùn)算符和表達(dá)式6.復(fù)合賦值運(yùn)算符417.逗號運(yùn)算符逗號運(yùn)算符用于把若干表達(dá)式組合成一個(gè)表達(dá)式(稱為逗號表達(dá)式)。程序運(yùn)行時(shí),對于逗號表達(dá)式的處理,是從左至右依次計(jì)算出各個(gè)表達(dá)式的值,而整個(gè)逗號表達(dá)式的值是最右邊表達(dá)式的值。例如:inta1,a2,b=2,c=7,d=5;//第1行a1=(++b,c--,d+3);//第2行,a1的值為8a2=++b,c--,d+3;//第3行,

a2的值為4§5.1.4

運(yùn)算符和表達(dá)式

7.逗號運(yùn)算符428.條件運(yùn)算符條件運(yùn)算符(?:)是一個(gè)三目運(yùn)算符,用于條件求值。它要求有三個(gè)運(yùn)算對象,使用它可以將三個(gè)表達(dá)式連接構(gòu)成一個(gè)條件表達(dá)式。條件表達(dá)式的一般形式為:邏輯表達(dá)式?表達(dá)式1:表達(dá)式2其功能是,首先計(jì)算邏輯表達(dá)式的值,當(dāng)邏輯表達(dá)式的值為真(非0值)時(shí),將表達(dá)式1的值作為整個(gè)條件表達(dá)式的值;當(dāng)邏輯表達(dá)式的值為假(0值)時(shí),將表達(dá)式2的值作為整個(gè)條件表達(dá)式的值?!?.1.4

運(yùn)算符和表達(dá)式8.條件運(yùn)算符439.指針和地址運(yùn)算符變量的指針就是該變量的地址,而存放變量地址的變量稱為指針變量。為表示指針變量和它所指向的變量地址之間的關(guān)系,C語言有運(yùn)算符:取內(nèi)容(*)和取地址(&),其運(yùn)算的一般形式分別為:變量=*指針變量指針變量=&目標(biāo)變量取內(nèi)容(*)運(yùn)算的含義是將指針變量所指向的目標(biāo)變量的值賦給等號(=)左邊的變量;取地址(&)運(yùn)算的含義是將目標(biāo)變量的地址賦給等號(=)左邊的指針變量?!?.1.4

運(yùn)算符和表達(dá)式

9.指針和地址運(yùn)算符44unsignedchar*txp;

unsigned

char

txbuffer[50];txp=txbuffer;

例使用指針可以進(jìn)行外部擴(kuò)展I/O口的訪問。在C51中有兩種方法訪問外部I/O端口。方法1:使用自定義指針。由于片外I/O端口與片外存儲(chǔ)器統(tǒng)一編址,所以可以定義xdata類型的指針訪問外部I/O端口。例如,某單片機(jī)應(yīng)用系統(tǒng)中,使用8255(見第1版8.3節(jié))擴(kuò)展I/O端口,采用線選法對8255進(jìn)行地址譯碼,單片機(jī)的P2.7(A15)接8255的片選引腳,因8255的命令口地址為7FF3H,PA口地址為7FF0H,PB口地址為7FF1H,PC口地址為7FFF2H。訪問8255的C程序如下:§5.1.4

運(yùn)算符和表達(dá)式9.指針和地址運(yùn)算符458255因目前停產(chǎn)較少用,本版教材不再介紹(用法見第1版8.3節(jié))方法1:使用自定義指針訪問外部擴(kuò)展I/O口寫端口程序:charxdata

*com8255;

//定義指向外部存儲(chǔ)區(qū)(片外I/O端口)的指針

com8255=0x7ff3;

//使指針指向8255的控制口(命令口)地址7FF3H*com8255=0x81;//輸出命令字81H到命令口寄存器//

81H:PA,PB口都是模式0,直接輸出,PC口直接輸入以上C程序相當(dāng)于下面的匯編語言程序:

MOVDPTR,#7FF3H

MOVA,#81H

MOVX@DPTR,A具體命令介紹見見第1版8.3節(jié):并行接口擴(kuò)展方法,309頁圖8-5246方法1:使用自定義指針訪問外部擴(kuò)展I/O口讀端口程序:

charxdata*com8255;//定義指針

chari;com8255=0x7FF0;

//使指針指向8255的PA口地址7FF0Hi=*com8255;//讀PA端口內(nèi)容到變量i47§5.1.4

運(yùn)算符和表達(dá)式9.指針和地址運(yùn)算符為了方便訪問外部存儲(chǔ)器及I/O端口,在C51的absacc.h頭文件做了如下定義,利用這些定義可以方便地訪問外部I/O端口。#defineCBYTE((unsignedcharvolatile

code*)0)#defineDBYTE((unsignedcharvolatile

data*)0)#definePBYTE((unsignedcharvolatile

pdata*)0)#defineXBYTE((unsignedcharvolatile

xdata*)0)volatile修飾了的變量隨程序的執(zhí)行其值會(huì)被改變,“易變”方法2:使用C51預(yù)定義指針訪問外部擴(kuò)展I/O口48#defineXBYTE((unsignedcharvolatilexdata*)0)以XBYTE為例介紹上述宏定義使用方法,XBYTE使用格式:

XBYTE[地址]方法2:使用C51預(yù)定義指針訪問外部擴(kuò)展I/O口例如:#include<absacc.h>#define

PORTA

XBYTE[0x7ff0]

//其中,PORTA為程序定義的I/O端口名稱,[]內(nèi)的內(nèi)容//7ff0H為PORTA的地址voidmain(void){chara;

PORTA=0x81;//*輸出81H到端口7ff0Ha=PORTA;//讀端口7ff0H到變量a}定義XBYTE數(shù)組的首地址是0XBYTE[0x7ff0]的中括號內(nèi)的值0x7ff0,指出了(定義)數(shù)組XBYTE首地址的偏移地址4910.強(qiáng)制類型轉(zhuǎn)換運(yùn)算符強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的作用是將表達(dá)式或變量的類型強(qiáng)制轉(zhuǎn)換成為括號內(nèi)所指定的類型。強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的一般使用形式為:變量=(類型)表達(dá)式如:pxdata=(charxdata*)0x3000;//pxdata為在xdata中定義的char類型指針變量§5.1.4運(yùn)算符和表達(dá)式10.強(qiáng)制類型轉(zhuǎn)換運(yùn)算符50表達(dá)式語句是最基本的一種語句。在表達(dá)式的后面加一個(gè)分號“;”就構(gòu)成了表達(dá)式語句。表達(dá)式語句也可以僅由一個(gè)分號“;”構(gòu)成,這種語句稱為空語句??照Z句不執(zhí)行具體的動(dòng)作。程序設(shè)計(jì)時(shí),有時(shí)需要用到空語句。例如,使用循環(huán)語句延時(shí)程序中的循環(huán)體內(nèi)可以使用空語句?!?.2KeilC51程序的語句§5.2.1表達(dá)式語句51條件語句又稱為分支語句,使用關(guān)鍵字“if”構(gòu)成。C51提供了三種形式的條件語句。1.if(條件表達(dá)式){語句體;}§5.2.2條件語句522.if(條件表達(dá)式){

語句體1;}else{

語句體2;}3.if(條件表達(dá)式1){

語句體1;}elseif(條件表達(dá)式2){

語句體2;}……elseif(條件表達(dá)式m){

語句體m;}Else{

語句體n;}§5.2.2條件語句53開關(guān)語句也是一種用來實(shí)現(xiàn)多條件分支的語句?!璫ase常量表達(dá)式n:語句體n;

break;

default:語句體d}§5.2.3開關(guān)語句54switch(表達(dá)式){case常量表達(dá)式1:語句體1;

break;

case常量表達(dá)式2:語句體2;

break;1.while語句利用while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:while(條件表達(dá)式){

語句體;}§5.2.4循環(huán)語句552.do-while語句采用do-while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:do{

語句體;}while(條件表達(dá)式);3.for語句采用for語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:for([初值設(shè)定表達(dá)式];[循環(huán)條件表達(dá)式];[更新表達(dá)式]){

語句體;}§5.2.4循環(huán)語句56goto語句是一個(gè)無條件轉(zhuǎn)向語句,其一般形式為:goto語句標(biāo)號;break語句也可以用于跳出循環(huán)語句,其一般形式為:break;continue是一種中斷語句,其功能是中斷本次循環(huán),繼續(xù)下一次循環(huán),一般形式為:continue;return語句用于終止函數(shù)的執(zhí)行,并控制程序返回到調(diào)用該函數(shù)的位置。一般形式為:return(表達(dá)式);return;§5.2.5goto、break、continue和return語句57兩種函數(shù):KeilC51定義的標(biāo)準(zhǔn)庫函數(shù)和用戶自定義函數(shù)?!?.3.1函數(shù)的定義與調(diào)用§5.3函數(shù)58函數(shù)定義的一般形式為:函數(shù)返回值類型

函數(shù)名(形式參數(shù)表){

局部變量定義

函數(shù)體語句}函數(shù)調(diào)用的一般形式為:[變量=]函數(shù)名(實(shí)際參數(shù)表)5.3.2KeilC51函數(shù)C51的函數(shù)聲明對ANSIC作了擴(kuò)展,具體包括:1、中斷函數(shù)聲明中斷函數(shù)通過使用interrupt關(guān)鍵字和中斷號(0~31)來聲明。中斷號告訴編譯器中斷服務(wù)程序入口地址。IAP15W4K58S4單片機(jī)的中斷號及中斷服務(wù)程序入口地址如表5-3

中斷號中斷源入口地址中斷號中斷源入口地址0外部中斷INT00003H11外部中斷

INT3005BH1T0溢出中斷000BH12T2溢出中斷0063H2外部中斷INT10013H16外部中斷

INT40083H3T1溢出中斷001BH17串口3中斷008BH4串行口UART1中斷0023H18串口4中斷0093H5ADC中斷002BH19T3溢出中斷009BH6LVD中斷0033H20T4溢出中斷3H7PCA中斷003BH21比較器中斷00ABH8串行口UART2中斷0043H22PWM中斷00B3H9SPI中斷004BH23PWM異常檢測中斷00BBH10外部中斷

INT20053H59中斷服務(wù)函數(shù)的一般形式為:void

函數(shù)名(void)interrupt中斷號

[usingn]中斷函數(shù)通過使用interrupt關(guān)鍵字和中斷號來聲明。中斷號告訴編譯器中斷服務(wù)程序的入口地址。也就是說,C51通過中斷號來區(qū)分各個(gè)不同的中斷,而與中斷函數(shù)的名字無關(guān)。其中usingn用于選擇單片機(jī)不同的寄存器組,n為0~3的常整型數(shù),分別選中4個(gè)不同寄存器組中的一個(gè)。Using是一個(gè)可選項(xiàng),可以不用。不用時(shí),由編譯器自動(dòng)選擇一個(gè)寄存器組。60/785.3.2KeilC51函數(shù)1、中斷函數(shù)聲明5.3.2KeilC51函數(shù)1、中斷函數(shù)聲明例如,串行口1的中斷函數(shù)(4號中斷)可以聲明如下:

voidUART1_ISR(void)interrupt4[using1]{/*中斷服務(wù)程序的代碼*/}上述代碼聲明了串行口1中斷服務(wù)函數(shù)。其中,interrupt4指明是串行口1的中斷,using1指明采用工作寄存器區(qū)1區(qū),using1在中括號中,說明該部分可省略。其他中斷函數(shù)的定義與此類似。中斷函數(shù)具體是哪個(gè)中斷的函數(shù),與中斷號有關(guān),而與函數(shù)名(如UART1_ISR)無關(guān)

,但一般賦予與相應(yīng)中斷相符合的名稱。無輸入?yún)?shù)無返回參數(shù)615.3.2KeilC51函數(shù)-——2、指定工作寄存器區(qū)當(dāng)需要指定函數(shù)中使用的工作寄存器區(qū)時(shí),使用關(guān)鍵字using后跟一個(gè)0到3的數(shù),對應(yīng)著工作寄存器0到3區(qū)。例如,在下面的函數(shù)中使用了工作寄存器1區(qū)(相當(dāng)于PSW.4=0,PSW.3=1):

unsignedcharGetKey(void)using1{/*用戶程序代碼*/}

指定工作寄存器區(qū)62程序狀態(tài)標(biāo)志寄存器PSW(8位)RS1,RS0(PSW.4~PSW.3):工作寄存器組選擇控制位,其詳細(xì)介紹見后續(xù)內(nèi)容。OV(PSW.2):溢出標(biāo)志位。指示運(yùn)算過程中是否發(fā)生了溢出,在執(zhí)行指令過程中自動(dòng)形成。位號D7D6D5D4D3D2D1D0符號CYACF0RS1RS0OVF1PRS1RS0OVP(PSW.0):奇偶標(biāo)志位累加器ACC中1的個(gè)數(shù)為偶數(shù),P=0;否則P=1。每個(gè)指令周期都由硬件來置“1”或清“0”。在具有奇偶校驗(yàn)的串行數(shù)據(jù)通信中,可根據(jù)P設(shè)置奇偶校驗(yàn)位。P63工作寄存器組的選擇:PSW寄存器中的RS1和RS0兩位組合決定當(dāng)前使用的工作寄存器組。可通過位操作指令修改RS1和RS0的內(nèi)容,選擇不同的工作寄存器組。RS1(PSW.4)RS0(PSW.3)工作寄存器組工作寄存器地址000R7~R0對應(yīng)的地址為07H~00H011R7~R0對應(yīng)的地址為0FH~08H102R7~R0對應(yīng)的地址為17H~10H113R7~R0對應(yīng)的地址為1FH~18H表3-1工作寄存器組選擇18H~1FH10H~17H08H~0FH00H~07H3區(qū)(R7~R0)2區(qū)(R7~R0)1區(qū)(R7~R0)0區(qū)(R7~R0)645.3.2KeilC51函數(shù)——2、指定存儲(chǔ)模式用戶可以使用small,compact及l(fā)arge說明存儲(chǔ)模式。例如:

voidfun1(void)small{}提示:small說明的函數(shù)內(nèi)部變量全部使用內(nèi)部RAM。關(guān)鍵的、經(jīng)常性的、耗時(shí)的地方可以這樣聲明,以提高運(yùn)行速度。2、指定存儲(chǔ)模式65用compact說明時(shí),函數(shù)參數(shù)和局部變量位于pdata定義的擴(kuò)展數(shù)據(jù)RAM中。用large說明時(shí),函數(shù)參數(shù)和局部變量位于xdata定義的擴(kuò)展數(shù)據(jù)RAM中。5.3.2KeilC51函數(shù)——3、函數(shù)的重入一個(gè)可重入函數(shù),簡單來說,就是可以被中斷的函數(shù),即可以在這個(gè)函數(shù)執(zhí)行的任何時(shí)刻中斷它,可重入函數(shù)可以被遞歸調(diào)用。遞歸或可重入函數(shù)在單片機(jī)系統(tǒng)中容易產(chǎn)生問題,因?yàn)閱纹瑱C(jī)和PC不同,PC使用(調(diào)用)堆棧傳遞參數(shù),且靜態(tài)變量以外的內(nèi)部變量都在堆棧中;而單片機(jī)一般使用寄存器傳遞參數(shù),

內(nèi)部變量一般在固定的RAM中,函數(shù)重入時(shí)會(huì)破壞(覆蓋)上次調(diào)用的數(shù)據(jù)。可在函數(shù)前聲明函數(shù)的不可重入性(不可中斷性)。若聲明為不可重入(中斷)的,則該函數(shù)調(diào)用過程中將不可被中斷。typedefunsignedcharuchar;#pragmadisable/*DisableInterrupts*/uchardfunc(ucharp1,ucharp2){return(p1*p2+p2*p1);}66(#pragma的作用是設(shè)定編譯器的狀態(tài)或者指示編譯器完成一些特定的動(dòng)作)5.3.2KeilC51函數(shù)——3、函數(shù)的重入可用以下兩種方法解決函數(shù)的重入(及不可中斷)問題:第一種方法:

在相應(yīng)的函數(shù)前使用“#pragmadisable”聲明,即只允許主程序或中斷之一調(diào)用該函數(shù)(函數(shù)調(diào)用后不再被中斷)。第二種方法:

將該函數(shù)說明為可重入的。如下:

voidfunc(param...)reentrant{...};因?yàn)閱纹瑱C(jī)內(nèi)部堆??臻g的限制,C51沒有像大系統(tǒng)那樣使用調(diào)用堆棧:一般在C語言中調(diào)用過程時(shí),會(huì)把過程的參數(shù)和過程中使用的局部變量入棧。KeilC51編譯后將生成一個(gè)可重入變量堆棧,然后就可以模擬通過調(diào)用堆棧傳遞變量的方法。67這樣函數(shù)重入時(shí),不用擔(dān)心變量數(shù)據(jù)被覆蓋的問題。

5.3.2KeilC51函數(shù)——3、函數(shù)的重入為了提高效率,C51沒有提供這種調(diào)用堆棧,而是提供一種壓縮棧。每個(gè)過程被給定同一個(gè)空間,用于存放局部變量。過程中的每個(gè)變量都存放在這個(gè)空間的固定位置。當(dāng)遞歸調(diào)用這個(gè)過程時(shí),會(huì)導(dǎo)致變量被覆蓋。在某些實(shí)時(shí)應(yīng)用中,非重入函數(shù)是不可取的。因?yàn)椋瘮?shù)調(diào)用時(shí)可能會(huì)被中斷程序中斷,而在中斷程序中可能再次調(diào)用這個(gè)函數(shù),所以C51允許將函數(shù)定義成重入函數(shù)。重入函數(shù)可被遞歸調(diào)用和多重調(diào)用,而不用擔(dān)心變量被覆蓋,因C51可模擬生成一個(gè)可重入變量堆棧{隨存儲(chǔ)模式(small,compact,large)不同,堆??稍诓煌拇鎯?chǔ)器區(qū)(idata,pdata,xdata)},每次函數(shù)調(diào)用時(shí)的局部變量都會(huì)被單獨(dú)保存。因?yàn)檫@些堆棧是模擬的,重入函數(shù)一般都比較大,運(yùn)行起來也比較慢。不常使用685.3.2KeilC51函數(shù)——3、函數(shù)的重入由于一般可重入函數(shù)由主程序和中斷調(diào)用(即遞歸調(diào)用),所以通常中斷程序使用與主程序不同的工作寄存器組。另外,對可重入函數(shù),在相應(yīng)的函數(shù)前面加上開關(guān)#pragmanoaregs,以禁止編譯器使用絕對寄存器尋址,可生成不依賴于寄存器組的代碼。所以對不依賴于寄存器組的函數(shù)可被其他使用了不同的寄存器組的多個(gè)函數(shù)調(diào)用。externcharfunc();#pragmaNOAREGSnoaregfunc

()

{k=func()+func();}#pragmaAREGSaregfunc()using3

{k=noaregfunc()+func();

}不常使用69本征庫函數(shù)是指編譯時(shí)直接將固定的代碼插入到當(dāng)前行,而不是用匯編語言中的ACALL和LCALL指令實(shí)現(xiàn)調(diào)用,從而大大提高函數(shù)的訪問效率。非本征庫函數(shù)則必須由ACALL和LCALL指令實(shí)現(xiàn)調(diào)用。KeilC51提供了9個(gè)本征庫函數(shù),如表5-4所示。使用本征庫函數(shù)時(shí),須在源程序中包含頭文件(含有函數(shù)原型聲明),即用預(yù)處理命令#include<INTRINS.H>。§5.4.1本征庫函數(shù)§5.4KeilC51庫函數(shù)70函數(shù)名及定義功能說明unsignedchar_crol_(unsignedcharval,unsignedcharn)將字符型數(shù)據(jù)val循環(huán)左移n位,相當(dāng)于RL指令。unsignedint_irol_(unsignedintval,unsignedcharn)將整型數(shù)據(jù)val循環(huán)左移n位,相當(dāng)于RL指令。unsignedlong_lrol_(unsignedlongval,unsignedcharn)將長整型數(shù)據(jù)val循環(huán)左移n位,相當(dāng)于RL指令。unsignedchar_cror_(unsignedcharval,unsignedcharn)將字符型數(shù)據(jù)val循環(huán)右移n位,相當(dāng)于RR指令。unsignedint_iror_(unsignedintval,unsignedcharn)將整型數(shù)據(jù)val循環(huán)右移n位,相當(dāng)于RR指令。unsignedlong_lror_(unsignedlongval,unsignedcharn)將長整型數(shù)據(jù)val循環(huán)右移n位,相當(dāng)于RR指令。bit_testbit_(bitx)相當(dāng)于JBCbit指令unsignedchar_chkfloat_(floatval)測試并返回浮點(diǎn)數(shù)狀態(tài)。void_nop_(void)產(chǎn)生一個(gè)NOP指令。表5-4KeilC51編譯器提供的本征庫函數(shù)§5.4.1

本征庫函數(shù)71_chkfloat_函數(shù)返回一個(gè)unsignedchar值包含下面的狀態(tài)信息:返回值意義0

標(biāo)準(zhǔn)浮點(diǎn)數(shù)1

浮點(diǎn)數(shù)02+INF正溢出3-INF負(fù)溢出4NaN(不是一個(gè)數(shù))錯(cuò)誤狀態(tài)§5.4KeilC51庫函數(shù)5.4.2字符判斷轉(zhuǎn)換庫函數(shù)(表5-5)72字符判斷轉(zhuǎn)換庫函數(shù)的原型聲明在頭文件CTYPE.H中定義。函數(shù)名及定義功能說明bit

isalpha(char

c)檢查參數(shù)字符是否為英文字母,是則返回1,否則返回0bit

isalnum(char

c)檢查參數(shù)字符是否為英文字母或數(shù)字字符,是則返回1,否則返回0bit

iscntrl(char

c)檢查參數(shù)字符是否為控制字符(值在0x00~0x1f之間或等于0x7f)是則返回1,否則返回0bit

isdigit(char

c)檢查參數(shù)字符是否為十進(jìn)制數(shù)字0~9,是則返回1,否則返回0bit

isgraph(char

c)檢查參數(shù)字符是否為可打印字符(不包括空格),值域0x21~0x7e,是則返回1,否則返回0bit

isprint(char

c)檢查參數(shù)字符是否為可打印字符(包括空格),值域0x20~0x7e,是則返回1,否則返回0bit

ispunct(char

c)檢查參數(shù)字符是否為標(biāo)點(diǎn)、空格或格式字符,是則返回1,否則返回0bit

islower(char

c)檢查參數(shù)字符是否為小寫英文字母,是則返回1,否則返回0bit

isupper(char

c)檢查參數(shù)字符是否為大寫英文字母,是則返回1,否則返回0bit

isspace(char

c)檢查參數(shù)字符是否為空格、制表符、回車、換行、垂直制表符和送紙(值為0x09~0x0d,或?yàn)?x20),是則返回1,否則返回0bit

isxdigit(char

c)檢查參數(shù)字符是否為十六進(jìn)制數(shù)字字符,是則返回1,否則返回0char

toint(char

c)將ASCII字符的0~9、a~f(大小寫無關(guān))轉(zhuǎn)換為十六進(jìn)制數(shù)字,返回值為0H~9H,0AH~0FHchar

tolower(char

c)將大寫字符轉(zhuǎn)換成小寫形式,如果字符參數(shù)不在A~Z之間,則該函數(shù)不起作用char

_tolower(char

c)將字符參數(shù)c與常數(shù)0x20逐位相或,從而將大寫字符轉(zhuǎn)換成小寫字符char

toupper(char

c)將小寫字符轉(zhuǎn)換成大寫形式,如果字符參數(shù)不在a~z之間,則該函數(shù)不起作用char

_toupper(char

c)將字符參數(shù)c與常數(shù)0xdf逐位相與,從而將小寫字符轉(zhuǎn)換成大寫字符char

toascii(char

c)將任何字符參數(shù)值縮小到有效的ASCII范圍內(nèi),即將c與0x7f相與,去掉第7位以上的位§5.4KeilC51庫函數(shù)5.4.2字符判斷轉(zhuǎn)換庫函數(shù)(表5-5)73函數(shù)名及定義功能說明bit

isupper(char

c)檢查參數(shù)字符是否為大寫英文字母,是則返回1,否則返回0bit

isspace(char

c)檢查參數(shù)字符是否為空格、制表符、回車、換行、垂直制表符和送紙(值為0x09~0x0d,或?yàn)?x20),是則返回1,否則返回0bit

isxdigit(char

c)檢查參數(shù)字符是否為十六進(jìn)制數(shù)字字符,是則返回1,否則返回0char

toint(char

c)將ASCII字符的0~9、a~f(大小寫無關(guān))轉(zhuǎn)換為十六進(jìn)制數(shù)字,返回值為0H~9H,0AH~0FHchar

tolower(char

c)將大寫字符轉(zhuǎn)換成小寫形式,如果字符參數(shù)不在A~Z之間,則該函數(shù)不起作用char

_tolower(char

c)將字符參數(shù)c與常數(shù)0x20逐位相或,從而將大寫字符轉(zhuǎn)換成小寫字符char

toupper(char

c)將小寫字符轉(zhuǎn)換成大寫形式,如果字符參數(shù)不在a~z之間,則該函數(shù)不起作用char

_toupper(char

c)將字符參數(shù)c與常數(shù)0xdf逐位相與,從而將小寫字符轉(zhuǎn)換成大寫字符char

toascii(char

c)將任何字符參數(shù)值縮小到有效的ASCII范圍內(nèi),即將c與0x7f相與,去掉第7位以上的位(續(xù)表)表5-6輸入/輸出庫函數(shù)§5.4KeilC51庫函數(shù)5.4.3輸入/輸出庫函數(shù)(表5-6)74函數(shù)名及定義功能說明char

_getkey(void)等待從8051串口讀入一個(gè)字符并返回讀入的字符,這個(gè)函數(shù)是改變整個(gè)輸入端口機(jī)制時(shí)應(yīng)做修改的唯一一個(gè)函數(shù)char

getchar(void)使用_getkey從串口讀入字符,并將讀入的字符馬上傳給putchar函數(shù)輸出,其他與_getkey函數(shù)相同char

*gets(char

*s,int

n)該函數(shù)通過getchar從串口讀入一個(gè)長度為n的字符串并存入由s指向的數(shù)組。輸入時(shí)一旦檢測到換行符就結(jié)束字符輸入。輸入成功時(shí)返回傳入的參數(shù)指針,失敗時(shí)返回NULLchar

ungetchar(char

c)將輸入字符回送到輸入緩沖區(qū),因此下次gets或getchar可用該字符。成功時(shí)返回char型值,失敗時(shí)返回EOF,不能處理多個(gè)字符char

putchar(char

c)通過8051串行口輸出字符,與函數(shù)_getkey一樣,這是改變整個(gè)輸出機(jī)制所需要修改的唯一一個(gè)函數(shù)int

printf(const

char

*fmstr[,argument]...)以第一個(gè)參數(shù)指向字符串制定的格式通過8051串行口輸出數(shù)值和字符串,返回值為實(shí)際輸出的字符數(shù)int

sprintf(char

*s,const

char

*fmstr[,argument]...)與printf功能相似,但數(shù)據(jù)是通過一個(gè)指針s送入內(nèi)存緩沖區(qū),并以ASCII碼的形式存儲(chǔ)int

puts(const

char

*s)利用putchar函數(shù)將字符串和換行符寫入串行口,錯(cuò)誤時(shí)返回EOF,否則返回0int

scanf(const

char

*fmstr[,argument]...)在格式控制串的控制下,利用getchar函數(shù)從串行口讀入數(shù)據(jù),每遇到一個(gè)符合格式控制串fmstr規(guī)定的值,就將它按順序存入由參數(shù)指針argument指向的存儲(chǔ)單元。其中每個(gè)參數(shù)都是指針,函數(shù)返回所發(fā)現(xiàn)并轉(zhuǎn)換的輸入項(xiàng)數(shù),錯(cuò)誤則返回EOFint

sscanf(char

*s,const

char

*fmstr[,argument]...)與scanf的輸入方式相似,但字符串的輸入不是通過串行口,而是通過指針s指向的數(shù)據(jù)緩沖區(qū)void

vprintf(const

char

*s,char

*fmstr,char

*argptr)將格式化字符串和數(shù)據(jù)值輸出到由指針s指向的內(nèi)存緩沖區(qū)內(nèi)。類似于sprintf,但接受一個(gè)指向變量表的指針,而不是變量表。返回值為實(shí)際寫入到輸出字符串中的字符數(shù)表5-6輸入/輸出庫函數(shù)(續(xù)表)§5.4KeilC51庫函數(shù)5.4.3輸入/輸出庫函數(shù)(表5-6)75函數(shù)名及定義功能說明int

sprintf(char

*s,const

char

*fmstr[,argument]...)與printf功能相似,但數(shù)據(jù)是通過一個(gè)指針s送入內(nèi)存緩沖區(qū),并以ASCII碼的形式存儲(chǔ)int

puts(const

char

*s)利用putchar函數(shù)將字符串和換行符寫入串行口,錯(cuò)誤時(shí)返回EOF,否則返回0int

scanf(const

char

*fmstr[,argument]...)在格式控制串的控制下,利用getchar函數(shù)從串行口讀入數(shù)據(jù),每遇到一個(gè)符合格式控制串fmstr規(guī)定的值,就將它按順序存入由參數(shù)指針argument指向的存儲(chǔ)單元。其中每個(gè)參數(shù)都是指針,函數(shù)返回所發(fā)現(xiàn)并轉(zhuǎn)換的輸入項(xiàng)數(shù),錯(cuò)誤則返回EOFint

sscanf(char

*s,const

char

*fmstr[,argument]...)與scanf的輸入方式相似,但字符串的輸入不是通過串行口,而是通過指針s指向的數(shù)據(jù)緩沖區(qū)void

vprintf(const

char

*s,char

*fmstr,char

*argptr)將格式化字符串和數(shù)據(jù)值輸出到由指針s指向的內(nèi)存緩沖區(qū)內(nèi)。類似于sprintf,但接受一個(gè)指向變量表的指針,而不是變量表。返回值為實(shí)際寫入到輸出字符串中的字符數(shù)輸入/輸出庫函數(shù)的原型聲明在頭文件STDIO.H,通過8051內(nèi)核單片機(jī)的串行口工作,若希望支持其他I/O接口,只需改動(dòng)_getkey()和putchar(),庫中所有其他I/O支持函數(shù)都依賴于這兩個(gè)函數(shù)模塊。在使用8051系列單片機(jī)的串行口之前,應(yīng)先對其進(jìn)行初始化。例,晶振頻率11.0592MHz,若串口1通信的參數(shù)為9600,n,8,1(9600波特率,8個(gè)數(shù)據(jù)位,1個(gè)停止位,沒有奇偶校驗(yàn)位),則初始化語句:voidUartInit(void)//9600bps@11.0592MHz{SCON=0x50;//8位數(shù)據(jù),可變波特率AUXR&=0xBF;//定時(shí)器1時(shí)鐘為Fosc/12,即12TAUXR&=0xFE;//串口1選擇定時(shí)器1為波特率發(fā)生器TMOD&=0x0F;//設(shè)定定時(shí)器1為16位自動(dòng)重裝方式TL1=0xE8;//設(shè)定定時(shí)初值TH1=0xFF;//設(shè)定定時(shí)器初值ET1=0;//禁止定時(shí)器1中斷TR1=1;//啟動(dòng)定時(shí)器1TI=1;//直接使用printf必須加入此句才能實(shí)現(xiàn)發(fā)送

}§5.4KeilC51庫函數(shù)5.4.3輸入/輸出庫函數(shù)(表5-6略)76例如:_getkey()函數(shù)的定義(在Keil安裝文件夾LIB的C文件中)#include<reg51.h>char_getkey(){charc;while(!RI);

c=SBUF;RI=0;return(c);}【例5-1】輸出庫函數(shù)printf()的應(yīng)用舉例:#include<stdio.h>#include<stc15.h>voidUart1Init(void);//將前面定義的串口1初始化函數(shù)進(jìn)行聲明voidmain(void){ chara; intb; longc; unsignedcharx; unsignedinty; unsignedlongz; floatf,g; charbuf[]="TestString"; char*p=buf;

Uart1Init();

//調(diào)用串口1初始化函數(shù)

a=1;b=12365;c

溫馨提示

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

最新文檔

評論

0/150

提交評論