第3章-C51語(yǔ)言編程基礎(chǔ)_第1頁(yè)
第3章-C51語(yǔ)言編程基礎(chǔ)_第2頁(yè)
第3章-C51語(yǔ)言編程基礎(chǔ)_第3頁(yè)
第3章-C51語(yǔ)言編程基礎(chǔ)_第4頁(yè)
第3章-C51語(yǔ)言編程基礎(chǔ)_第5頁(yè)
已閱讀5頁(yè),還剩173頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第3章

C51語(yǔ)言編程基礎(chǔ)

1單片機(jī)應(yīng)用系統(tǒng)日趨復(fù)雜,對(duì)程序的可讀性、升級(jí)與維護(hù)以及模塊化要求越來(lái)越高,對(duì)軟件編程要求也越來(lái)越高,要求編程人員在短時(shí)間內(nèi)編寫(xiě)出執(zhí)行效率高、運(yùn)行可靠的程序代碼。同時(shí),也要方便多個(gè)編程人員來(lái)進(jìn)行協(xié)同開(kāi)發(fā)。C51語(yǔ)言是近年來(lái)在8051單片機(jī)開(kāi)發(fā)中,普遍使用的程序設(shè)計(jì)語(yǔ)言,能直接對(duì)8051單片機(jī)硬件進(jìn)行操作,既有高級(jí)語(yǔ)言特點(diǎn),又有匯編語(yǔ)言特點(diǎn),因此在8051單片機(jī)程序設(shè)計(jì)中,得到廣泛使用。下面介紹8051單片機(jī)的C51語(yǔ)言,以及如何使用C51語(yǔ)言集成化開(kāi)發(fā)平臺(tái)KeilμVision3,進(jìn)行C51程序設(shè)計(jì)與開(kāi)發(fā)。23.1C51編程語(yǔ)言簡(jiǎn)介用于8051單片機(jī)編程的C語(yǔ)言,在標(biāo)準(zhǔn)C基礎(chǔ)上針對(duì)8051硬件特點(diǎn)進(jìn)行擴(kuò)展,并向8051上移植,經(jīng)多年努力,C51已成為公認(rèn)的高效、簡(jiǎn)潔的8051單片機(jī)的實(shí)用高級(jí)編程語(yǔ)言。與8051匯編語(yǔ)言相比,C51語(yǔ)言在功能上、結(jié)構(gòu)性、可讀性、可維護(hù)性上有明顯優(yōu)勢(shì),易學(xué)易用。3.1.1C51語(yǔ)言與8051匯編語(yǔ)言比較與8051匯編語(yǔ)言相比,C51有如下優(yōu)點(diǎn)。(1)可讀性好。C51語(yǔ)言程序比匯編語(yǔ)言程序的可讀性好,編程效率高,程序便于修改、維護(hù)以及升級(jí)。3(2)模塊化開(kāi)發(fā)與資源共享。用C51開(kāi)發(fā)的程序模塊可不經(jīng)修改,直接被其他工程所用,使得開(kāi)發(fā)者能夠很好地利用已有的大量標(biāo)準(zhǔn)C程序資源與豐富的庫(kù)函數(shù),減少重復(fù)勞動(dòng),同時(shí)也有利于多個(gè)工程師進(jìn)行協(xié)同開(kāi)發(fā)。(3)可移植性好。為某種型號(hào)單片機(jī)開(kāi)發(fā)的C語(yǔ)言程序,只需把與硬件相關(guān)的頭文件和編譯鏈接的參數(shù)進(jìn)行適當(dāng)修改,就可方便地移植到其他型號(hào)的單片機(jī)上。例如,為8051單片機(jī)編寫(xiě)的程序通過(guò)改寫(xiě)頭文件以及少量的程序行,就可方便地移植到PIC單片機(jī)上。(4)生成的代碼效率高。當(dāng)前較好的C51語(yǔ)言編譯系統(tǒng)編譯出來(lái)的代碼效率只比直接使用匯編語(yǔ)言低20%左右,如果使用優(yōu)化編譯選項(xiàng),最高可達(dá)到90%左右。43.1.2C51語(yǔ)言與標(biāo)準(zhǔn)C語(yǔ)言的比較C51語(yǔ)言與標(biāo)準(zhǔn)C語(yǔ)言間有許多相同地方,但也有自身特點(diǎn)。不同的嵌入式C語(yǔ)言編譯系統(tǒng)之所以與標(biāo)準(zhǔn)C語(yǔ)言有不同的地方,主要是由于它們所針對(duì)的硬件系統(tǒng)不同。對(duì)于8051單片機(jī),目前廣泛使用的是C51語(yǔ)言。C51語(yǔ)言基本語(yǔ)法與標(biāo)準(zhǔn)C相同,是在標(biāo)準(zhǔn)C的基礎(chǔ)上進(jìn)行適合8051內(nèi)核單片機(jī)硬件的擴(kuò)展。深入理解C51語(yǔ)言對(duì)標(biāo)準(zhǔn)C語(yǔ)言的擴(kuò)展部分以及它們的不同之處,是掌握C51語(yǔ)言的關(guān)鍵之一。5C51語(yǔ)言與標(biāo)準(zhǔn)C語(yǔ)言一些差別如下。(1)庫(kù)函數(shù)不同。標(biāo)準(zhǔn)C中不適合于嵌入式控制器系統(tǒng)的庫(kù)函數(shù),被排除在C51語(yǔ)言之外,如字符屏幕和圖形函數(shù)。有些庫(kù)函數(shù)必須針對(duì)8051的硬件特點(diǎn)來(lái)做出相應(yīng)的開(kāi)發(fā)。

例如,在標(biāo)準(zhǔn)C中,庫(kù)函數(shù)printf和scanf,常用于屏幕打印和接收字符,而在C51語(yǔ)言中,主要用于串行口數(shù)據(jù)的收發(fā)。(2)數(shù)據(jù)類(lèi)型有一定區(qū)別。在C51中增加幾種8051單片機(jī)的數(shù)據(jù)類(lèi)型,在標(biāo)準(zhǔn)C的基礎(chǔ)上又?jǐn)U展了4種類(lèi)型。例如,8051單片機(jī)包含位操作空間和豐富的位操作指令,因此,C51語(yǔ)言與標(biāo)準(zhǔn)C語(yǔ)言相比增加了位類(lèi)型。6(3)C51語(yǔ)言變量存儲(chǔ)模式與標(biāo)準(zhǔn)C語(yǔ)言中變量存儲(chǔ)模式數(shù)據(jù)不一樣。標(biāo)準(zhǔn)C最初是為通用計(jì)算機(jī)設(shè)計(jì)的,在通用計(jì)算機(jī)中只有一個(gè)程序和數(shù)據(jù)統(tǒng)一尋址的內(nèi)存空間,而C51語(yǔ)言中變量的存儲(chǔ)模式與8051單片機(jī)的各種存儲(chǔ)器區(qū)緊密相關(guān)。(4)數(shù)據(jù)存儲(chǔ)類(lèi)型不同。8051存儲(chǔ)區(qū)可分為內(nèi)部數(shù)據(jù)存儲(chǔ)區(qū)、外部數(shù)據(jù)存儲(chǔ)區(qū)以及程序存儲(chǔ)區(qū)。

內(nèi)部數(shù)據(jù)存儲(chǔ)區(qū)可分為3個(gè)不同的C51存儲(chǔ)類(lèi)型:data、idata和bdata。

外部數(shù)據(jù)存儲(chǔ)區(qū)分為2個(gè)不同的C51存儲(chǔ)類(lèi)型:xdata和pdata。

程序存儲(chǔ)區(qū)只能讀不能寫(xiě),可能在8051內(nèi)部或者在外部,C51語(yǔ)言提供的code存儲(chǔ)類(lèi)型用來(lái)訪問(wèn)程序存儲(chǔ)區(qū)。7(5)標(biāo)準(zhǔn)C語(yǔ)言沒(méi)有處理單片機(jī)中斷的定義,而C51語(yǔ)言中有專(zhuān)門(mén)的中斷函數(shù)。 (6)頭文件不同。C51語(yǔ)言頭文件必須把8051單片機(jī)內(nèi)部的外設(shè)硬件資源(如定時(shí)器、中斷、I/O等)相應(yīng)的特殊功能寄存器寫(xiě)入到頭文件內(nèi),而標(biāo)準(zhǔn)C不用。(7)程序結(jié)構(gòu)的差異。由于8051單片機(jī)的硬件資源有限,它的編譯系統(tǒng)不允許太多的程序嵌套。其次,標(biāo)準(zhǔn)C語(yǔ)言所具備的遞歸特性不被C51語(yǔ)言支持。8但從數(shù)據(jù)運(yùn)算操作、程序控制語(yǔ)句以及函數(shù)的使用上來(lái)說(shuō),C51與標(biāo)準(zhǔn)C幾乎沒(méi)有什么明顯差別。如果程序設(shè)計(jì)者具備了有關(guān)標(biāo)準(zhǔn)C語(yǔ)言的編程基礎(chǔ),只要注意C51與標(biāo)準(zhǔn)C不同之處,并熟悉8051單片機(jī)的硬件結(jié)構(gòu),就能較快掌握C51編程。9103.2C51語(yǔ)言程序設(shè)計(jì)基礎(chǔ)本節(jié)在標(biāo)準(zhǔn)C基礎(chǔ)上,了解掌握C51的數(shù)據(jù)類(lèi)型和存儲(chǔ)類(lèi)型、C51的基本運(yùn)算與流程控制語(yǔ)句、C51語(yǔ)言構(gòu)造數(shù)據(jù)類(lèi)型、C51函數(shù)以及C51程序設(shè)計(jì)的其他一些問(wèn)題,為C51的程序開(kāi)發(fā)打下基礎(chǔ)。113.2.1C51語(yǔ)言中的數(shù)據(jù)類(lèi)型與存儲(chǔ)類(lèi)型1.?dāng)?shù)據(jù)類(lèi)型數(shù)據(jù)是單片機(jī)操作的對(duì)象,具有一定格式的數(shù)字或數(shù)值,數(shù)據(jù)的不同格式就稱(chēng)為數(shù)據(jù)類(lèi)型。

KeilC51支持的基本數(shù)據(jù)類(lèi)型見(jiàn)表3-1。針對(duì)8051的硬件特點(diǎn),C51在標(biāo)準(zhǔn)C基礎(chǔ)上,擴(kuò)展了4種數(shù)據(jù)類(lèi)型(見(jiàn)表3-1中最后4行)。注意,擴(kuò)展的4種數(shù)據(jù)類(lèi)型,不能使用指針來(lái)對(duì)它們存取。12132.C51的擴(kuò)展數(shù)據(jù)類(lèi)型下面對(duì)擴(kuò)展的4種數(shù)據(jù)類(lèi)型說(shuō)明。(1)位變量bit的值可以是1(true),也可是0(false)。(2)特殊功能寄存器sfr。8051單片機(jī)的特殊功能寄存器分布在片內(nèi)數(shù)據(jù)存儲(chǔ)區(qū)的地址單元80H~FFH之間,“sfr”數(shù)據(jù)類(lèi)型占用一個(gè)內(nèi)存單元。利用它可訪問(wèn)8051單片機(jī)內(nèi)部的所有特殊功能寄存器。

例如:sfrP1=0x90這一語(yǔ)句定義了P1端口在片內(nèi)的寄存器,在程序后續(xù)的語(yǔ)句中可以用“P1=0xff”,使P1的所有引腳輸出為高電平的語(yǔ)句來(lái)操作特殊功能寄存器。14(3)特殊功能寄存器sfr16。

“sfr16”數(shù)據(jù)類(lèi)型占用兩個(gè)內(nèi)存單元,用于操作占兩個(gè)字節(jié)的特殊功能寄存器。例如:“sfr16DPTR=0x82”語(yǔ)句定義了片內(nèi)16位數(shù)據(jù)指針寄存器DPTR,其低8位字節(jié)地址為82H,高8位字節(jié)地址為83H。在程序的后續(xù)語(yǔ)句中就可對(duì)DPTR進(jìn)行操作。(4)特殊功能位sbit。

sbit是指AT89S51片內(nèi)特殊功能寄存器的可尋址位。例如:

sfr PSW=0xd0; //定義PSW寄存器地址為0xd0

sbit OV=PSW^2; //定義OV位為PSW.2符號(hào)“^”前是特殊功能寄存器名字,“^”后的數(shù)字定義特殊功能寄存器可尋址位在寄存器中的位置,取值必須是0~7。15注意,不要把bit與sbit相混淆。bit定義普通的位變量,只能是二進(jìn)制的0或1。sbit是定義特殊功能寄存器的可尋址位,值是可以進(jìn)行位尋址的特殊功能寄存器的某位的絕對(duì)地址,例如,PSW寄存器OV位的絕對(duì)地址0xd2。上面的例子還涉及到C51注釋的寫(xiě)法問(wèn)題,C51的注釋寫(xiě)法有2種:(1)//……,兩個(gè)斜杠后面跟著的為注釋語(yǔ)句,本寫(xiě)法只能注釋一行,當(dāng)換行時(shí),必須在新行上重新寫(xiě)兩個(gè)斜杠。(2)/*……*/,一個(gè)斜杠與星號(hào)結(jié)合使用,本寫(xiě)法可注釋任一行,即斜杠星號(hào)與星號(hào)斜杠之間的所有文字都作為注釋?zhuān)醋⑨層卸嘈袝r(shí),只需在注釋的開(kāi)始處,加斜杠星號(hào),在注釋的結(jié)尾處,加上星號(hào)斜杠即可。加注釋的目的是為了便于讀懂程序,所有注釋都不參與程序編譯,編譯器在編譯過(guò)程中會(huì)自動(dòng)刪去注釋。16173.?dāng)?shù)據(jù)存儲(chǔ)類(lèi)型在討論C51數(shù)據(jù)類(lèi)型時(shí),須同時(shí)提及它的存儲(chǔ)類(lèi)型,以及它與8051單片機(jī)存儲(chǔ)器結(jié)構(gòu)的關(guān)系,因?yàn)镃51定義的任何數(shù)據(jù)類(lèi)型必須以一定的方式,定位在8051單片機(jī)的某一存儲(chǔ)區(qū)中,否則沒(méi)有任何實(shí)際意義。8051有片內(nèi)、片外數(shù)據(jù)存儲(chǔ)區(qū),還有程序存儲(chǔ)區(qū)。片內(nèi)的數(shù)據(jù)存儲(chǔ)區(qū)是可讀寫(xiě)的,8051的衍生系列最多可有256字節(jié)的內(nèi)部數(shù)據(jù)存儲(chǔ)區(qū)(例如AT89S52單片機(jī)),其中低128字節(jié)可直接尋址,高128字節(jié)(80H~FFH)只能間接尋址,從地址20H開(kāi)始的16字節(jié)可位尋址。18

內(nèi)部數(shù)據(jù)存儲(chǔ)區(qū)可分為3個(gè)不同的數(shù)據(jù)存儲(chǔ)類(lèi)型:data、idata和bdata。

訪問(wèn)片外數(shù)據(jù)存儲(chǔ)區(qū)比訪問(wèn)片內(nèi)數(shù)據(jù)存儲(chǔ)區(qū)慢,因?yàn)樵L問(wèn)片外數(shù)據(jù)存儲(chǔ)區(qū)要通過(guò)對(duì)數(shù)據(jù)指針加載地址來(lái)間接尋址訪問(wèn)。

C51提供兩種不同的數(shù)據(jù)存儲(chǔ)類(lèi)型xdata和pdata來(lái)訪問(wèn)片外數(shù)據(jù)存儲(chǔ)區(qū)。程序存儲(chǔ)區(qū)只能讀不能寫(xiě),可能在8051單片機(jī)內(nèi)部或者外部,或外部和內(nèi)部都有,由8051單片機(jī)硬件決定,C51提供了code存儲(chǔ)類(lèi)型來(lái)訪問(wèn)程序存儲(chǔ)區(qū)。19C51存儲(chǔ)類(lèi)型與8051實(shí)際的存儲(chǔ)空間的對(duì)應(yīng)關(guān)系見(jiàn)表3-2。下面對(duì)表3-2各種存儲(chǔ)區(qū)作以說(shuō)明。(1)DATA區(qū)尋址最快,應(yīng)把常使用的變量放在該區(qū),但該區(qū)存儲(chǔ)空間有限,DATA區(qū)除了包含程序變量外,還包含了堆棧和寄存器組。DATA區(qū)聲明中的存儲(chǔ)類(lèi)型標(biāo)識(shí)符為data,通常指片內(nèi)RAM128字節(jié)的內(nèi)部數(shù)據(jù)存儲(chǔ)的變量,可直接尋址。聲明舉例: unsignedchardatasystem_status=0; unsignedint

dataunit_id[8]; chardatainp_string[20];2021標(biāo)準(zhǔn)變量和用戶自聲明變量都可存儲(chǔ)在DATA區(qū)中,只要不超過(guò)DATA區(qū)的范圍即可,由于C51用默認(rèn)的寄存器組來(lái)傳遞參數(shù),這樣DATA區(qū)至少失去8字節(jié)空間。另外,當(dāng)內(nèi)部堆棧溢出的時(shí)候,程序會(huì)莫名其妙地復(fù)位。這是因?yàn)?051沒(méi)有報(bào)錯(cuò)機(jī)制,堆棧溢出只能以這種方式表示,因此要留有較大的堆??臻g來(lái)防止堆棧溢出。(2)BDATA區(qū)DATA中的位尋址區(qū),在該區(qū)中聲明變量就可進(jìn)行位尋址。BDATA區(qū)聲明中的存儲(chǔ)類(lèi)型標(biāo)識(shí)符為bdata,指的是片內(nèi)RAM可位尋址的16字節(jié)存儲(chǔ)區(qū)(字節(jié)地址為20H~2FH)中的128個(gè)位。下面是在BDATA區(qū)中聲明的位變量和使用位變量的例子:unsignedcharbdata

status_byte;22unsignedint

bdata

status_word;sbit

stat_flag=status_byte^4;if(status_word^15){……}stat_flag=1;C51編譯器不允許在BDATA區(qū)中聲明float和double型變量。

(3)IDATA區(qū)該區(qū)使用寄存器作為指針來(lái)對(duì)片內(nèi)RAM進(jìn)行間接尋址,常用來(lái)存放使用比較頻繁的變量。與外部存儲(chǔ)器尋址相比,它的指令執(zhí)行周期和代碼長(zhǎng)度相對(duì)較短。

IDATA區(qū)聲明中的存儲(chǔ)類(lèi)型標(biāo)識(shí)符為idata,指的是片內(nèi)RAM的256字節(jié)的存儲(chǔ)區(qū),只能間接尋址,速度比直接尋址慢。23聲明舉例如下:unsignedcharidata

system_status=0;unsignedint

idataunit_id[8];charidatainp_string[16];floatidata

out_value;(4)PDATA區(qū)和XDATA區(qū)位于片外存儲(chǔ)區(qū),PDATA區(qū)和XDATA區(qū)聲明中的存儲(chǔ)類(lèi)型標(biāo)識(shí)符分別為pdata和xdata。

PDATA區(qū)只有256字節(jié),僅指定256字節(jié)的外部數(shù)據(jù)存儲(chǔ)區(qū)。但XDATA區(qū)最多可達(dá)64KB,對(duì)應(yīng)的xdata存儲(chǔ)類(lèi)型標(biāo)識(shí)符可指定外部數(shù)據(jù)區(qū)64KB內(nèi)的任何地址。24

對(duì)PDATA區(qū)的尋址要比對(duì)XDATA區(qū)尋址快,因?yàn)閷?duì)PDATA區(qū)尋址,只需裝入8位地址,而對(duì)XDATA區(qū)尋址要裝入16位地址,所以盡量把外部數(shù)據(jù)存儲(chǔ)在PDATA區(qū)中。對(duì)PDATA區(qū)和XDATA區(qū)的聲明舉例如下:unsignedcharxdata

system_status=0;unsignedint

pdataunit_id[8];charxdatainp_string[16];floatpdata

out_value;由于外部數(shù)據(jù)存儲(chǔ)器與外部I/O口是統(tǒng)一編址的,外部數(shù)據(jù)存儲(chǔ)器地址段中除了包含數(shù)據(jù)存儲(chǔ)器地址外,還包含外部I/O口的地址。對(duì)外部數(shù)據(jù)存儲(chǔ)器及外部I/O口的尋址將在本章的絕對(duì)地址尋址中介紹。25(5)程序存儲(chǔ)區(qū)CODE程序存儲(chǔ)區(qū)CODE聲明的標(biāo)識(shí)符為code,儲(chǔ)存的數(shù)據(jù)是不可改變的。在C51編譯器中可以用存儲(chǔ)區(qū)類(lèi)型標(biāo)識(shí)符code來(lái)訪問(wèn)程序存儲(chǔ)區(qū)。聲明舉例如下:unsignedcharcodea[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};

上面介紹了C51的數(shù)據(jù)存儲(chǔ)類(lèi)型,其大小和值域見(jiàn)表3-3。單片機(jī)訪問(wèn)片內(nèi)RAM比訪問(wèn)片外RAM相對(duì)快一些,所以應(yīng)盡量把頻繁使用的變量置于片內(nèi)RAM。即采用data、bdata或idata存儲(chǔ)類(lèi)型,而將容量較大或使用不太頻繁的那些變量置于片外RAM,即采用pdata或xdata存儲(chǔ)類(lèi)型。常量只能采用code存儲(chǔ)類(lèi)型。2627變量存儲(chǔ)類(lèi)型定義舉例:(1)chardataa1; /*字符變量a1被定義為data型,分配在 片內(nèi)RAM低128字節(jié)中*/(2)floatidata

x,y; /*浮點(diǎn)變量x和y被定義為idata型,定位在

片內(nèi)RAM中,只能用間接尋址方式尋址*/

(3)bitbdatap; /*位變量p被定義為bdata型,定位在片內(nèi)

RAM中的位尋址區(qū)*/

(4)unsignedint

pdatavar1; /*無(wú)符號(hào)整型變量var1定義為pdata型,定位在片外RAM中,相當(dāng)于@Ri間接尋址*/

(5)unsignedcharxdataa[2][4];/*無(wú)符號(hào)字符型二維數(shù)組變量a[2][4]被定義為xdata存儲(chǔ)類(lèi)型,定位在片外RAM中,占據(jù)2×4=8字節(jié),相當(dāng)于@DPTR間接尋址*/

28294.?dāng)?shù)據(jù)存儲(chǔ)模式如果在變量定義時(shí)略去存儲(chǔ)類(lèi)型標(biāo)識(shí)符,編譯器會(huì)自動(dòng)默認(rèn)存儲(chǔ)類(lèi)型。進(jìn)一步由SMALL、COMPACT和LARGE存儲(chǔ)模式指令限制。例如,若聲明charvar1,則在使用SMALL存儲(chǔ)模式下,var1被定位在data存儲(chǔ)區(qū),在使用COMPACT模式下,var1被定位在idata存儲(chǔ)區(qū);在LARGE模式下,var1被定位在xdata存儲(chǔ)區(qū)中。30下面對(duì)存儲(chǔ)模式作進(jìn)一步說(shuō)明。(1)SMALL模式本模式下所有變量都默認(rèn)位于8051單片機(jī)內(nèi)部的數(shù)據(jù)存儲(chǔ)器,與使用data指定存儲(chǔ)器類(lèi)型的方式一樣。在此模式下,變量訪問(wèn)的效率高,但是所有數(shù)據(jù)對(duì)象和堆棧必須使用內(nèi)部RAM。(2)COMPACT模式本模式下所有變量都默認(rèn)在外部數(shù)據(jù)存儲(chǔ)器的1頁(yè)(256字節(jié))內(nèi),這與使用pdata指定存儲(chǔ)器類(lèi)型是一樣的。該類(lèi)型適用于變量不超過(guò)256字節(jié)的情況,此限制是由尋址方式?jīng)Q定的,相當(dāng)于使用數(shù)據(jù)指針@Ri尋址。與SMALL模式相比,該存儲(chǔ)模式的效率比較低,對(duì)變量訪問(wèn)的速度也慢一些,但比LARGE模式快。

3132(3)LARGE模式

本模式下所有變量都默認(rèn)位于外部數(shù)據(jù)存儲(chǔ)器,相當(dāng)于用@DPTR尋址。通過(guò)數(shù)據(jù)指針訪問(wèn)外部數(shù)據(jù)存儲(chǔ)器的效率較低,特別是當(dāng)變量為2字節(jié)或更多字節(jié)時(shí),該模式要比SMALL和COMPACT產(chǎn)生更多的代碼。在固定的存儲(chǔ)器地址上進(jìn)行變量傳遞,是C51的標(biāo)準(zhǔn)特征之一。在SMALL模式下,參數(shù)傳遞是在片內(nèi)數(shù)據(jù)存儲(chǔ)區(qū)中完成的。LARGE和COMPACT模式允許參數(shù)在外部存儲(chǔ)器中傳遞。C51也支持混合模式。例如,在LARGE模式下,生成的程序可將一些函數(shù)放入SMALL模式中,從而加快執(zhí)行速度。333.2.2C51語(yǔ)言的特殊功能寄存器及位變量定義介紹C51如何對(duì)特殊功能寄存器及位變量進(jìn)行定義并訪問(wèn)。1.特殊功能寄存器的C51定義C51語(yǔ)言允許通過(guò)使用關(guān)鍵字sfr、sbit或直接引用編譯器提供的頭文件來(lái)對(duì)特殊功能寄存器(SFR)進(jìn)行訪問(wèn),特殊功能寄存器分布在片內(nèi)RAM高128字節(jié)中,只能采用直接尋址方式。

34(1)使用關(guān)鍵字定義sfr為能直接訪問(wèn)特殊功能寄存器SFR,C51提供了一種定義方法,即引入關(guān)鍵字sfr,語(yǔ)法如下:

sfr

特殊功能寄存器名字=特殊功能寄存器地址;例如:

sfrIE=0xA8; //中斷允許寄存器IE地址A8H

sfrTCON=0x88; //定時(shí)器/計(jì)數(shù)器控制寄存器地址88H

sfrSCON=0x98; //串行口控制寄存器地址98H在8051中,要訪問(wèn)16位SFR,要用關(guān)鍵字sfr16。16位SFR的低字節(jié)地址須作為“sfr16”的定義地址,例如:

sfr16DPTR=0x82 //DPTR的低8位地址為82H,高8位地址為83H

35(2)通過(guò)頭文件訪問(wèn)SFR各種衍生型的8051單片機(jī)的特殊功能寄存器的數(shù)量與類(lèi)型有時(shí)是不相同的,對(duì)其訪問(wèn)可通過(guò)頭文件訪問(wèn)來(lái)進(jìn)行。為用戶處理方便,C51把8051(或8052單片機(jī))常用的特殊功能寄存器和其中的可尋址位進(jìn)行了定義,放在一個(gè)reg51.h(或reg52.h)的頭文件中。當(dāng)用戶要使用時(shí),只需在使用之前用一條預(yù)處理命令#include<reg51.h>把這個(gè)頭文件包含到程序中,就可使用特殊功能寄存器名和其中的可尋址位名稱(chēng)了。用戶可對(duì)頭文件進(jìn)行增減。36頭文件引用舉例如下:#include<reg51.h> //包含8051單片機(jī)的頭文件voidmain(void){ TL0=0xf0; //給T0低字節(jié)TL0設(shè)置時(shí)間常數(shù)

TH0=0x3f; //給T0高字節(jié)TH0設(shè)置時(shí)間常數(shù)

TR0=1; //啟動(dòng)定時(shí)器T0 ……}(3)特殊功能寄存器中的位定義對(duì)SFR中的可尋址位的訪問(wèn),要使用關(guān)鍵字來(lái)定義可尋址位,共3種方法。37①sbit

位名=特殊功能寄存器^位置;例如:sfrPSW=0xd0; //定義PSW寄存器的字節(jié)地址0xd0sbitCY=PSW^7; //定義CY位為PSW.7,地址為0xd0sbitOV=PSW^2; //定義OV位為PSW.2,地址為0xd2②sbit

位名=字節(jié)地址^位置;

例如:sbitCY=0xd0^7; //CY位地址為0xd7sbitOV=0xd0^2; //OV位地址為0xd2③sbit

位名=位地址;將位的絕對(duì)地址賦給變量,位地址必須在0x80~0xff。38例如: sbitCY=0xd7; //CY位地址為0xd7sbitOV=0xd2; //OV位地址為0xd2【例】AT89S51單片機(jī)片內(nèi)P1口的各尋址位的定義如下:sfrP1=0x90;sbitP1_7=P1^7;sbitP1_6=P1^6;sbitP1_5=P1^5;sbitP1_4=P1^4;sbitP1_3=P1^3;sbitP1_2=P1^2;sbitP1_1=P1^1;sbitP1_0=P1^0;

39402.位變量的C51定義(1)由于8051可位操作,C51擴(kuò)展的“bit”數(shù)據(jù)類(lèi)型用來(lái)定義位變量,這是與標(biāo)準(zhǔn)C的不同之處。C51采用關(guān)鍵字“bit”來(lái)定義位變量,一般格式為:

bitbit_name;例如:

bitov_flag; //將ov_flag定義為位變量bitlock_pointer; //將lock_pointer定義為位變量41(2)函數(shù)可以包含類(lèi)型為bit的參數(shù),也可將其作為返回值。C51程序函數(shù)可以包含類(lèi)型為“bit”的參數(shù),也可將其作為返回值。例如:bitfunc(bitb0,bitb1); //位變量b0與b1作為函數(shù)func的參數(shù){

……

return(b1); //位變量b1作為return函數(shù)的返回值}42(3)位變量定義的限制。位變量不能用來(lái)定義指針和數(shù)組。例如:

bit*ptr; //錯(cuò)誤,不能用位變量來(lái)定義指針

bitarray[]; //錯(cuò)誤,不能用位變量來(lái)定義數(shù)組array[]定義位變量時(shí),允許定義存儲(chǔ)類(lèi)型,位變量都被放入一個(gè)位段,此段總是位于8051的片內(nèi)RAM中,因此其存儲(chǔ)類(lèi)型限制為DATA或IDATA,如果將位變量定義成其他類(lèi)型,將會(huì)導(dǎo)致編譯時(shí)出錯(cuò)。43443.2.3C51語(yǔ)言的絕對(duì)地址訪問(wèn)如何對(duì)8051片內(nèi)RAM、片外RAM及I/O空間進(jìn)行訪問(wèn),C51提供兩種常用的訪問(wèn)絕對(duì)地址的方法。1.絕對(duì)宏編譯器提供了一組宏定義對(duì)code、data、pdata和xdata空間進(jìn)行絕對(duì)尋址。程序中用“#include<absacc.h>”來(lái)對(duì)absacc.h中聲明的宏來(lái)訪問(wèn)絕對(duì)地址,包括CBYTE、CWORD、DBYTE、DWORD、XBYTE、XWORD、PBYTE、PWORD,具體使用參見(jiàn)absacc.h頭文件。其中:45CBYTE以字節(jié)形式對(duì)code區(qū)尋址;CWORD以字形式對(duì)code區(qū)尋址;DBYTE以字節(jié)形式對(duì)data區(qū)尋址;DWORD以字形式對(duì)data區(qū)尋址;XBYTE以字節(jié)形式對(duì)xdata區(qū)尋址;XWORD以字形式對(duì)xdata區(qū)尋址;PBYTE以字節(jié)形式對(duì)pdata區(qū)尋址;PWORD以字形式對(duì)pdata區(qū)尋址。46【例】片內(nèi)RAM、片外RAM及I/O定義的程序如下:

#include<absacc.h>#definePORTAXBYTE[0xFFC0]//將PORTA定義為外部I/O口,地址為0xFFC0,長(zhǎng)度8位#defineNRAMDBYTE[0x50] //將NRAM定義為片內(nèi)RAM,地址為0x50,長(zhǎng)度8位main(){ PORTA=0x3d;//將數(shù)據(jù)3DH寫(xiě)入地址為0xffc0的外部I/O端口PORTA中

NRAM=0x01;//將數(shù)據(jù)01H寫(xiě)入片內(nèi)RAM的0x40單元}472._at_關(guān)鍵字關(guān)鍵字_at_可對(duì)指定的存儲(chǔ)器空間的絕對(duì)地址訪問(wèn),格式如下:[存儲(chǔ)器類(lèi)型]數(shù)據(jù)類(lèi)型說(shuō)明符變量名_at_地址常數(shù)其中,存儲(chǔ)器類(lèi)型為C51能識(shí)別的數(shù)據(jù)類(lèi)型;數(shù)據(jù)類(lèi)型為C51支持的數(shù)據(jù)類(lèi)型;地址常數(shù)用于指定變量的絕對(duì)地址,必須位于有效的存儲(chǔ)器空間之內(nèi);使用_at_定義的變量必須為全局變量。48【例】使用關(guān)鍵字

_at_

實(shí)現(xiàn)絕對(duì)地址的訪問(wèn),程序如下:voidmain(void){ dataunsignedchary1

_at_0x50;//在data區(qū)定義字節(jié)變量y1,地址為50H

xdataunsignedint

y2

_at_0x4000;//在xdata區(qū)定義字變量y2,地址為//4000H

y1=0xff;

y2=0x1234;

……

while(1);}【例】將片外RAM2000H開(kāi)始的連續(xù)20字節(jié)清0,程序如下:49xdataunsignedcharbuffer[20]_at_0x2000;voidmain(void){ unsignedchari;

for(i=0;i<20;i++)

{

buffer[i]=0

}}如把片內(nèi)RAM40H單元開(kāi)始的8個(gè)單元內(nèi)容清0,程序如下:xdataunsignedcharbuffer[8]_at_0x40;voidmain(void){50unsignedcharj;

for(j=0;j<8;j++) {

buffer[j]=0

}}51523.2.4C51的基本運(yùn)算與標(biāo)準(zhǔn)C類(lèi)似,主要包括算術(shù)運(yùn)算、關(guān)系運(yùn)算、邏輯運(yùn)算、位運(yùn)算和賦值運(yùn)算及其表達(dá)式等。1.算術(shù)運(yùn)算符算術(shù)運(yùn)算符及說(shuō)明見(jiàn)表3-4。53C51中表示加1和減1時(shí)可以采用自增運(yùn)算符和自減運(yùn)算符,自增和自減運(yùn)算符是使變量自動(dòng)加1或減1,自增和自減運(yùn)算符放在變量前和變量之后是不同的,見(jiàn)表3-5。542.邏輯運(yùn)算符邏輯運(yùn)算的結(jié)果只有“真”和“假”兩種,“1”表示真,“0”表示假。表3-6列出了邏輯運(yùn)算符及其說(shuō)明。

例如:

條件“10>20”為假,“2<6”為真,則邏輯與運(yùn)算為:

(10>20)&&(2<6)=0&&1=0。55563.關(guān)系運(yùn)算符關(guān)系運(yùn)算符是判斷兩個(gè)數(shù)之間的關(guān)系。說(shuō)明如表3-7所示。4.位運(yùn)算位運(yùn)算符及其說(shuō)明見(jiàn)表3-8。

57在實(shí)際應(yīng)用中,常想改變I/O口中某一位的值,而不影響其他位,如果I/O口可位尋址的,這個(gè)問(wèn)題就很簡(jiǎn)單。但有時(shí)外擴(kuò)的I/O口只能進(jìn)行字節(jié)操作,要想實(shí)現(xiàn)單獨(dú)位控,就要采用位操作?!纠?/p>

編程將擴(kuò)展的某I/O

PORTA(只能字節(jié)操作)的PORTA.5清

0,PORTA.1置1,程序如下:#define<absacc.h> //定義片外

I/O

口變量PORTA要用該頭文件#definePORTAXBYTE[0xffc0]//定義一個(gè)片外

I/O

口變量PORTAvoidmain(){ ……

PORTA=(PORTA&0xdf)│0x02;

……}58程序中,第2行定義一個(gè)片外

I/O

口變量PORTA,地址為片外數(shù)據(jù)存儲(chǔ)區(qū)的0xffc0。在main()函數(shù)中,“PORTA=(PORTA&0xdf)│0x02”的作用是先用運(yùn)算符“&”將PORTA.5置成0,然后再用“│0x02”運(yùn)算將PORTA.1置為1。5.指針和取地址運(yùn)算符指針是C51語(yǔ)言中一個(gè)十分重要的概念,指針變量用于存儲(chǔ)某個(gè)變量的地址,C51用“*”和“&”運(yùn)算符來(lái)提取變量?jī)?nèi)容和變量地址,見(jiàn)表3-9。59提取變量的內(nèi)容和變量的地址的一般形式分別為:目標(biāo)變量=*指針變量//將指針變量所指的存儲(chǔ)單元內(nèi)容賦值給目標(biāo)變量指針變量=&目標(biāo)變量 //將目標(biāo)變量的地址賦值給指針變量例如:a=&b; //取b變量的地址送至變量ac=*b; //把以指針變量b為地址的單元內(nèi)容送至變量c指針變量中只能存放地址(即指針型數(shù)據(jù)),不能將非指針類(lèi)型的數(shù)據(jù)賦值給指針變量。例如:inti; //定義整型變量iint*b; //定義指向整數(shù)的指針變量bb=&i; //將變量i的地址賦給指針變量bb=i;//錯(cuò),指針變量b只能存放變量指針(變量地址),不能存放變量i的值60613.2.5C51的分支與循環(huán)程序結(jié)構(gòu)C51程序按結(jié)構(gòu)可分為3類(lèi),即順序、分支和循環(huán)結(jié)構(gòu)。順序結(jié)構(gòu)是基本結(jié)構(gòu),程序自上而下,從main(

)的函數(shù)開(kāi)始一直到程序結(jié)束,只有一條路可走,無(wú)其他路徑可選,結(jié)構(gòu)較簡(jiǎn)單和便于理解,這里僅介紹分支結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。1.分支控制語(yǔ)句

分支控制語(yǔ)句有:if語(yǔ)句和switch語(yǔ)句。62(1)if語(yǔ)句

用來(lái)判定所給定的條件是否滿足,根據(jù)判定結(jié)果決定執(zhí)行兩種操作之一。

if語(yǔ)句的基本結(jié)構(gòu)如下:

if(表達(dá)式){語(yǔ)句}括號(hào)中的表達(dá)式成立時(shí),程序執(zhí)行大括號(hào)內(nèi)的語(yǔ)句,否則程序跳過(guò)大括號(hào)中的語(yǔ)句部分,而直接執(zhí)行下面的其他語(yǔ)句。63C51提供3種形式的if語(yǔ)句:形式1

if(表達(dá)式){語(yǔ)句}例如:

if(x>y){max=x;min=y;}即如果x>y,則x賦給max,y賦給min。如果x>y不成立,則不執(zhí)行大括號(hào)中的賦值運(yùn)算。形式2if(表達(dá)式){語(yǔ)句1;}else{語(yǔ)句2;}64例如:if(x>y){max=x;}else{max=y;}

本形式相當(dāng)于雙分支選擇結(jié)構(gòu)。形式3if(表達(dá)式1){語(yǔ)句1;}elseif(表達(dá)式2){語(yǔ)句2;}elseif(表達(dá)式3){語(yǔ)句3;}……else{語(yǔ)句n;}65例如:if(x>100){y=1;}elseif(x>50){y=2;}elseif(x>30){y=3;}elseif(x>20){y=4;}else{y=5;}本形式相當(dāng)于串行多分支選擇結(jié)構(gòu)。在if語(yǔ)句中又含有一個(gè)或多個(gè)if語(yǔ)句,這稱(chēng)為if語(yǔ)句的嵌套。應(yīng)當(dāng)注意if與else的對(duì)應(yīng)關(guān)系,else總是與它前面最近的一個(gè)if語(yǔ)句相對(duì)應(yīng)。66(2)switch語(yǔ)句if語(yǔ)句只有兩個(gè)分支可選擇,而switch語(yǔ)句是多分支選擇語(yǔ)句。switch語(yǔ)句的一般形式如下:switch(表達(dá)式1){ case常量表達(dá)式1:{語(yǔ)句1;}break;

case常量表達(dá)式2:{語(yǔ)句2;}break; …… case常量表達(dá)式n:{語(yǔ)句n;}break; default:{語(yǔ)句n+1;}}上述switch語(yǔ)句說(shuō)明如下。67(1)每一case常量表達(dá)式須互不相同,否則將混亂。(2)各個(gè)case和default出現(xiàn)次序,不影響程序執(zhí)行的結(jié)果。(3)switch括號(hào)內(nèi)表達(dá)式的值與某case后面的常量表達(dá)式的值相同時(shí),就執(zhí)行它后面的語(yǔ)句,遇到break語(yǔ)句則退出switch語(yǔ)句。若所有的case中的常量表達(dá)式的值都沒(méi)有與switch語(yǔ)句表達(dá)式的值相匹配時(shí),就執(zhí)行default后面的語(yǔ)句。(4)如果在case語(yǔ)句中遺忘了break語(yǔ)句,則程序執(zhí)行了本行之后,不會(huì)按規(guī)定退出switch語(yǔ)句,而是將執(zhí)行后續(xù)的case語(yǔ)句。在執(zhí)行1個(gè)case分支后,使流程跳出switch結(jié)構(gòu),即中止switch語(yǔ)句的執(zhí)行,可以用1條break語(yǔ)句完成。68switch語(yǔ)句的最后一個(gè)分支可以不加break語(yǔ)句,結(jié)束后直接退出switch結(jié)構(gòu)?!纠吭趩纹瑱C(jī)程序設(shè)計(jì)中,常用switch語(yǔ)句作為鍵盤(pán)中按鍵按下的判別,并根據(jù)按下鍵的鍵號(hào)跳向各自的分支處理程序。69input:keynum=keyscan()switch(keynum){ case1: key1();break; //如果按下鍵為1鍵,則執(zhí)行函數(shù)key1() case2: key2();break; //如果按下鍵為2鍵,則執(zhí)行函數(shù)key2() case3: key3();break; //如果按下鍵為3鍵,則執(zhí)行函數(shù)key3() case4: key4();break; //如果按下鍵為4鍵,則執(zhí)行函數(shù)key4() ……

default:gotoinput}例子中的keyscan()是另行編寫(xiě)的一個(gè)鍵盤(pán)掃描函數(shù),如有鍵按下,該函數(shù)就會(huì)得到按下鍵的鍵值,將鍵值賦予變量keynum。如果鍵值為2,則執(zhí)行鍵值處理函數(shù)key2()后返回;如果鍵值為4,則執(zhí)行key4()函數(shù)后返回。70執(zhí)行完1個(gè)鍵值處理函數(shù)后,則跳出switch語(yǔ)句,從而達(dá)到按下不同的按鍵來(lái)進(jìn)行不同的鍵值處理的目的。71722.循環(huán)控制語(yǔ)句許多實(shí)用程序都包含循環(huán)結(jié)構(gòu),熟練掌握和運(yùn)用循環(huán)結(jié)構(gòu)的程序設(shè)計(jì)是C51語(yǔ)言程序設(shè)計(jì)的基本要求。實(shí)現(xiàn)循環(huán)結(jié)構(gòu)的語(yǔ)句有以下3種:while語(yǔ)句、do-while語(yǔ)句和for語(yǔ)句。(1)while語(yǔ)句。

語(yǔ)法形式為:while(表達(dá)式)

{

循環(huán)體語(yǔ)句;

}73表達(dá)式是while循環(huán)能否繼續(xù)的條件,如果表達(dá)式為真,就重復(fù)執(zhí)行循環(huán)體語(yǔ)句;反之,則終止循環(huán)體內(nèi)的語(yǔ)句。while循環(huán)結(jié)構(gòu)特點(diǎn):循環(huán)條件測(cè)試在循環(huán)體開(kāi)頭,要想執(zhí)行重復(fù)操作,首先必須進(jìn)行循環(huán)條件的測(cè)試,如條件不成立,則循環(huán)體內(nèi)的重復(fù)操作一次也不能執(zhí)行。例如:

while((P1&0x80)==0){}while中的條件語(yǔ)句對(duì)AT89S8051單片機(jī)的P1口的P1.7位進(jìn)行測(cè)試,如果P1.7為低(0),則由于循環(huán)體無(wú)實(shí)際操作語(yǔ)句,故繼續(xù)測(cè)試下去(等待),一旦P1.7的電平變高(1),則循環(huán)終止。74

(2)do-while語(yǔ)句。語(yǔ)法形式為:do{ 循環(huán)體語(yǔ)句;}while(表達(dá)式);do-while語(yǔ)句特點(diǎn)是先執(zhí)行內(nèi)嵌的循環(huán)體語(yǔ)句,再計(jì)算表達(dá)式,如表達(dá)式的值為非0,則繼續(xù)執(zhí)行循環(huán)體語(yǔ)句,直到表達(dá)式的值為0時(shí)結(jié)束循環(huán)。由do-while構(gòu)成的循環(huán)與while循環(huán)的重要區(qū)別是:while循環(huán)的控制出現(xiàn)在循環(huán)體之前,只有當(dāng)while后面表達(dá)式的值非0時(shí),才可能執(zhí)行循環(huán)體;在do-while構(gòu)成的循環(huán)中,總是先執(zhí)行一次循環(huán)體,然后再求表達(dá)式的值,因此無(wú)論表達(dá)式的值是0還是非0,循環(huán)體至少要被執(zhí)行一次。75

在do-while循環(huán)體中,要有能使while后表達(dá)式的值變?yōu)?的操作,否則,循環(huán)會(huì)無(wú)限制地進(jìn)行下去?!纠繉?shí)型數(shù)組sample存有10個(gè)采樣值,編寫(xiě)程序段,要求返回其平均值(平均值濾波)。程序如下:floatavg(float*sample){ floatsum=0; charn=0;

do { sum+=sample[n];

n++;

}while(n<10);return(sum/10);}76(3)基于for語(yǔ)句的循環(huán)。3種循環(huán)常用的是for循環(huán)。不僅可用于循環(huán)次數(shù)已知的情況,也可用于循環(huán)次數(shù)不確定而只給出循環(huán)條件情況,完全可替77代while語(yǔ)句。for循環(huán)的一般格式為:for(表達(dá)式1;表達(dá)式2;表達(dá)式3){

循環(huán)體語(yǔ)句;}for是關(guān)鍵字,括號(hào)中常含有3個(gè)表達(dá)式,各表達(dá)式間用“;”隔開(kāi)。這3個(gè)表達(dá)式可以是任意形式的表達(dá)式,通常主要用于for循環(huán)控制。緊跟在for()之后的循環(huán)體,在語(yǔ)法上要求是

1

條語(yǔ)句;若在循環(huán)體內(nèi)需要多條語(yǔ)句,應(yīng)用大括號(hào)括起來(lái)組成復(fù)合語(yǔ)句。78for執(zhí)行過(guò)程如下:①計(jì)算“表達(dá)式1”,表達(dá)式1通常稱(chēng)為“初值設(shè)定表達(dá)式”。②計(jì)算“表達(dá)式2”,表達(dá)式2通常稱(chēng)為“終值條件表達(dá)式”,若滿足條件,轉(zhuǎn)下一步,若不滿足條件,則轉(zhuǎn)步驟⑤。③執(zhí)行1次for循環(huán)體。④計(jì)算“表達(dá)式3”,“表達(dá)式3”通常稱(chēng)為“更新表達(dá)式”轉(zhuǎn)向步驟②。⑤結(jié)束循環(huán),執(zhí)行for循環(huán)之后的語(yǔ)句。79下面對(duì)for語(yǔ)句的幾個(gè)特例進(jìn)行說(shuō)明。①for語(yǔ)句中的小括號(hào)內(nèi)的3個(gè)表達(dá)式全部為空。 例如:for(;;){

循環(huán)體語(yǔ)句;}在小括號(hào)內(nèi)只有兩分號(hào),無(wú)表達(dá)式,這意味著沒(méi)有設(shè)初值,無(wú)判斷條件,循環(huán)變量為增值,它的作用相當(dāng)于while(1),這將導(dǎo)致一個(gè)無(wú)限循環(huán)。一般在編程時(shí),需要無(wú)限循環(huán)時(shí),可采用這種形式的for循環(huán)語(yǔ)句。②

for語(yǔ)句的3個(gè)表達(dá)式中,表達(dá)式1缺省。80例如:for(;i<=100;i++)sum=sum+i;

即不對(duì)i設(shè)初值。③for語(yǔ)句的3個(gè)表達(dá)式中,表達(dá)式2缺省。 例如:for(i=1;;i++)sum=sum+i;即不判斷循環(huán)條件,認(rèn)為表達(dá)式始終為真,循環(huán)將無(wú)休止地進(jìn)行下去。④for語(yǔ)句的3個(gè)表達(dá)式中,表達(dá)式1、表達(dá)式3省略。例如:81for(;i<=100;){ sum=sum+i; i++;}⑤沒(méi)有循環(huán)體的for語(yǔ)句。 例如:inta=1000;for(t=0;t<a;t++){;}本例典型應(yīng)用就是軟件延時(shí)??捎醚h(huán)結(jié)構(gòu)來(lái)實(shí)現(xiàn),即循環(huán)執(zhí)行指令,消磨一段已知的時(shí)間。指令的執(zhí)行時(shí)間是靠一定數(shù)量的時(shí)鐘周期來(lái)計(jì)時(shí)的,如果使用12MHz晶振,則12個(gè)時(shí)鐘周期花費(fèi)的時(shí)間為1μs。82【例】編寫(xiě)一個(gè)延時(shí)1ms程序。voiddelayms(unsignedcharint

j){ unsignedchari;

while(j--)

{

for(i=0;i<125;i++)

{;}

}}如把上述程序段編譯成匯編代碼分析,用for的內(nèi)部循環(huán)大約延時(shí)8μs,但不是特別精確。不同編譯器會(huì)產(chǎn)生不同延時(shí),因此i的上限值125應(yīng)根據(jù)實(shí)際情況進(jìn)行補(bǔ)償調(diào)整。83【例】求1+2+3…+100的累加和。 用for語(yǔ)句編寫(xiě)的程序如下:#include<reg51.h>#include<stdio.h>main(){

intnvar1,nsum;

for(nvar1=0,nsum=1;nsum<=100;nsum++)

nVar1+=ncount; //累加求和

while(1);}【例】無(wú)限循環(huán)的結(jié)構(gòu)實(shí)現(xiàn)。 編寫(xiě)無(wú)限循環(huán)程序段,可用以下3種結(jié)構(gòu)。84①使用while(1)的結(jié)構(gòu):while(1){

代碼段;}②使用for(;;)的結(jié)構(gòu):for(;;){

代碼段;}

③使用do-while(1)的結(jié)構(gòu):do{

代碼段;}while(1);

85863.break語(yǔ)句、continue語(yǔ)句和goto語(yǔ)句在循環(huán)體執(zhí)行中,如滿足循環(huán)判定條件的情況下跳出代碼段,可使用

break語(yǔ)句或continue語(yǔ)句;如要從任意地方跳轉(zhuǎn)到代碼某地方,可使用goto語(yǔ)句。(1)break語(yǔ)句循環(huán)結(jié)構(gòu)中,可使用break語(yǔ)句跳出本層循環(huán)體,馬上結(jié)束本層循環(huán)?!纠繄?zhí)行如下程序段。87【例】執(zhí)行如下程序段。voidmain(void) { int

i,sum; sum=0;

for(i=1;i<=10;i++) { sum=sum+i;

if(sum>5)break;print(“sum=%d\n”,sum);/*通過(guò)串口向計(jì)算機(jī)屏幕輸出顯示sum值*/}}本例如沒(méi)有break語(yǔ)句,程序?qū)⑦M(jìn)行10次循環(huán);當(dāng)i=3時(shí),sum的值為6,此時(shí),if語(yǔ)句的表達(dá)式“sum>5”的值為1,于是執(zhí)行break語(yǔ)句,跳出for循環(huán),從而提前終止循環(huán)。88因此在一個(gè)循環(huán)程序中,既可通過(guò)循環(huán)語(yǔ)句中的表達(dá)式來(lái)控制循環(huán)是否結(jié)束,還可直接通過(guò)break語(yǔ)句強(qiáng)行退出循環(huán)結(jié)構(gòu)。(2)continue語(yǔ)句作用及用法與break語(yǔ)句類(lèi)似,區(qū)別:當(dāng)前循環(huán)遇到break,是直接結(jié)束循環(huán),若遇上continue,則是停止當(dāng)前這一層循環(huán),然后直接嘗試下一層循環(huán)??梢?jiàn),continue并不結(jié)束整個(gè)循環(huán),而僅僅是中斷這一層循環(huán),然后跳到循環(huán)條件處,繼續(xù)下一層的循環(huán)。當(dāng)然,如果跳到循環(huán)條件處,發(fā)現(xiàn)條件已不成立,那么循環(huán)也會(huì)結(jié)束。89【例】輸出整數(shù)1~100的累加值,但要求跳過(guò)所有個(gè)位為3的數(shù)。為完成題目要求,在循環(huán)中加一個(gè)判斷,如果該數(shù)各位是3,就跳過(guò)該數(shù)不加。如何來(lái)判斷1~100的數(shù)中那些數(shù)個(gè)位是3呢?用求余數(shù)的運(yùn)算符“%”,將一個(gè)兩位以內(nèi)的正整數(shù),除以10后,余數(shù)是3,就說(shuō)明這個(gè)數(shù)的個(gè)位為3。例如對(duì)于數(shù)73,除以10后,余數(shù)是3。參考程序如下:

voidmain(void) {

inti,sum=0; sum=0;

for(i=1;i<=100;i++)

90{ if(i%10==3)

continue; sum=sum+i;}print(“sum=%d\n”,sum);/*在計(jì)算機(jī)屏幕顯示sum值,了解本語(yǔ)句的功能即可*/}(3)goto語(yǔ)句無(wú)條件轉(zhuǎn)移語(yǔ)句,當(dāng)執(zhí)行g(shù)oto語(yǔ)句時(shí),將程序指針跳轉(zhuǎn)到goto給出的下一條代碼?;靖袷饺缦拢?/p>

goto

標(biāo)號(hào)91【例】計(jì)算整數(shù)1~100的累加值,存放到sum中。voidmain(void) { unsignedchariintsum;

sumadd:sum=sum+i;i++;if(i<101) {

goto

sumadd; }}goto語(yǔ)句在C51中經(jīng)常用于無(wú)條件跳轉(zhuǎn)某條必須執(zhí)行的語(yǔ)句以及在死循環(huán)程序中退出循環(huán)。92933.2.6C51的數(shù)組在C51程序設(shè)計(jì)中,數(shù)組使用的較為廣泛。1.?dāng)?shù)組簡(jiǎn)介數(shù)組是同類(lèi)數(shù)據(jù)的一個(gè)有序結(jié)合,用數(shù)組名來(lái)標(biāo)識(shí)。整型變量的有序結(jié)合稱(chēng)為整型數(shù)組,字符型變量的有序結(jié)合稱(chēng)為字符型數(shù)組。數(shù)組中的數(shù)據(jù),稱(chēng)為數(shù)組元素。數(shù)組中各元素的順序用下標(biāo)表示,下標(biāo)為n的元素可以表示為數(shù)組名[n]。改變[]中的下標(biāo)就可以訪問(wèn)數(shù)組中的所有的元素。數(shù)組有一維、二維、三維和多維數(shù)組之分。C51語(yǔ)言中常用的一維、二維數(shù)組和字符數(shù)組。

94(1)一維數(shù)組具有一個(gè)下標(biāo)的數(shù)組元素組成的數(shù)組成為一維數(shù)組,一維數(shù)組形式如下: 類(lèi)型說(shuō)明符數(shù)組名[元素個(gè)數(shù)];其中,數(shù)組名是一個(gè)標(biāo)識(shí)符,元素個(gè)數(shù)是一個(gè)常量表達(dá)式,不能是含有變量的表達(dá)式:例如:

intarray1[8]

定義名為array1的數(shù)組,包含8個(gè)整型元素,在定義數(shù)組時(shí),可對(duì)數(shù)組進(jìn)行整體初始化,若定義后對(duì)數(shù)組賦值,則只能對(duì)每個(gè)元素分別賦值。例如:

95inta[3]={2,4,6};/*給全部元素賦值,a[0]=2,a[1]=4,a[2]=6*/intb[4]={5,4,3,2};/*給全部元素賦值,b[0]=5,b[1]=4,b[2]=3,b[3]=2*/(2)二維數(shù)組或多維數(shù)組具有兩個(gè)或兩個(gè)以上下標(biāo)的數(shù)組,稱(chēng)為二維數(shù)組或多維數(shù)組。定義二維數(shù)組的一般形式如下:類(lèi)型說(shuō)明符數(shù)組名[行數(shù)][列數(shù)];其中,數(shù)組名是一個(gè)標(biāo)識(shí)符,行數(shù)和列數(shù)都是常量表達(dá)式。例如:floatarray2[4][3]/*array2數(shù)組,4行3列共12個(gè)浮點(diǎn)型元素*/二維數(shù)組可以在定義時(shí)進(jìn)行整體初始化,也可在定義后單個(gè)地進(jìn)行賦值。例如:96inta[3][4]={1,2,3,4},{5,6,7,8},{9,10,11,12};/*a數(shù)組全部初始化*/intb[3][4]={1,3,5,7},{2,4,6,8},{};/*b數(shù)組部分初始化,未初始化的元素為0*/(3)字符數(shù)組 若一個(gè)數(shù)組的元素是字符型的,則該數(shù)組就是一個(gè)字符數(shù)組。例如:chara[10]={‘B’,‘E’,‘I’,‘’,‘J’,‘I’,‘N’,‘G’,‘\0’};/*字符串?dāng)?shù)組*/定義了一個(gè)字符型數(shù)組a[],有10個(gè)數(shù)組元素,并且將9個(gè)字符(其中包括一個(gè)字符串結(jié)束標(biāo)志‘\0’

)分別賦給了a[0]~a[8],剩余的a[9]被系統(tǒng)自動(dòng)賦予空格字符。97C51還允許用字符串直接給字符數(shù)組置初值,例如:chara[10]={“BEIJING”};用雙引號(hào)括起來(lái)的一串字符,成為字符串常量,C51編譯器會(huì)自動(dòng)地在字符串末尾加上結(jié)束符‘\0’。用單引號(hào)括起來(lái)的字符為字符的ASCII碼值,而不是字符串。例如‘a(chǎn)’表示a的ASCII碼值61H,而“a”表示一個(gè)字符串,由兩個(gè)字符a和\0組成。98一個(gè)字符串可以用一維數(shù)組來(lái)裝入,但數(shù)組的元素?cái)?shù)目一定要比字符多一個(gè),以便C51編譯器自動(dòng)在其后面加入結(jié)束符‘\0’。2.?dāng)?shù)組的應(yīng)用在C51的編程中,數(shù)組一個(gè)非常有用的功能是查表。例如數(shù)學(xué)運(yùn)算,編程者更愿意采用查表計(jì)算而不是公式計(jì)算。例如,對(duì)于傳感器的非線性轉(zhuǎn)換需要進(jìn)行補(bǔ)償,使用查表法就要有效的多。再如,LED顯示程序中根據(jù)要顯示的數(shù)值,找到對(duì)應(yīng)的顯示段碼送到LED顯示器顯示。表可以事先計(jì)算好后裝入程序存儲(chǔ)器中。

99【例】使用查表法,計(jì)算數(shù)0~9的平方。#defineucharunsignedcharuchar

codesquare[0,1,4,9,16,25,36,49,64,81];/*0~9的平方表*/uchar

fuction(ucharnumber){ returnsquare[number]};/*返回要求得其平方的數(shù)*/main() { result=fuction(7);/*函數(shù)fuction()的返回值為7,其平方49存入result單元*/}程序開(kāi)始,“ucharcodesquare[0,1,4,9,16,25,36,49,64,81];”定義了一個(gè)無(wú)符號(hào)字符型的數(shù)組square[],并對(duì)其進(jìn)行了初始化,將數(shù)0~9的平方值賦予了數(shù)組square[],數(shù)據(jù)類(lèi)型代碼code指定編譯器將平方表定位在程序存儲(chǔ)器中。

100主函數(shù)調(diào)用函數(shù)fuction(),假設(shè)得到返回值number=7;從square數(shù)組中查表獲得相應(yīng)的求得其平方的數(shù)為49。執(zhí)行result=fuction(7)后,result的結(jié)果為相應(yīng)的平方數(shù)493.?dāng)?shù)組與存儲(chǔ)空間當(dāng)程序中設(shè)定了一個(gè)數(shù)組時(shí),C51編譯器就會(huì)在系統(tǒng)的存儲(chǔ)空間中開(kāi)辟一個(gè)區(qū)域,用于存放數(shù)組的內(nèi)容。數(shù)組就包含在這個(gè)由連續(xù)存儲(chǔ)單元組成的模塊的存儲(chǔ)體內(nèi)。對(duì)字符數(shù)組而言,占據(jù)了內(nèi)存中一連串的字節(jié)位置。對(duì)整型(int)數(shù)組而言,將在存儲(chǔ)區(qū)中占據(jù)一連串連續(xù)的字節(jié)對(duì)的位置。對(duì)長(zhǎng)整型(long)數(shù)組或浮點(diǎn)型(float)數(shù)組,一個(gè)數(shù)組成員將占有4字節(jié)的存儲(chǔ)空間。

101當(dāng)一維數(shù)組被創(chuàng)建時(shí),C51編譯器就會(huì)根據(jù)數(shù)組的類(lèi)型在內(nèi)存中開(kāi)辟一塊大小等于數(shù)組長(zhǎng)度乘以數(shù)據(jù)類(lèi)型長(zhǎng)度(即類(lèi)型占有的字節(jié)數(shù))的區(qū)域。對(duì)于二維數(shù)組a[m][n]而言,其存儲(chǔ)順序是按行存儲(chǔ),先存第0行元素的第0列、第1列、第2列,直至第n-1列,然后返回到存第1行元素的第0列、第1列、第2列,直至第n-1列,……,如此順序存儲(chǔ),直到第m-1行的第n-1列。當(dāng)數(shù)組特別是多維數(shù)組中大多數(shù)元素沒(méi)有被有效利用地利用時(shí),就會(huì)浪費(fèi)大量的存儲(chǔ)空間。對(duì)于51單片機(jī),不擁有大量的存儲(chǔ)區(qū),其存儲(chǔ)資源極為有限,因此在進(jìn)行C51語(yǔ)言編程開(kāi)發(fā)時(shí),要仔細(xì)地根據(jù)需要來(lái)選擇數(shù)組的大小。1021033.2.7C51的指針C51支持基于存儲(chǔ)器的指針和一般指針兩種指針類(lèi)型。當(dāng)定義一個(gè)指針變量時(shí),若未給出它所指向的對(duì)象的存儲(chǔ)類(lèi)型,則被認(rèn)為是一般指針,反之若給出了它所指向?qū)ο蟮拇鎯?chǔ)類(lèi)型,則被認(rèn)為是基于存儲(chǔ)器的指針?;诖鎯?chǔ)器的指針類(lèi)型由C51語(yǔ)言源代碼中存儲(chǔ)類(lèi)型決定,用這種指針可以高效訪問(wèn)對(duì)象,且只需1~2字節(jié)。

一般指針占用3字節(jié):1個(gè)字節(jié)為存儲(chǔ)器類(lèi)型,2個(gè)字節(jié)為偏移量。存儲(chǔ)器類(lèi)型決定了對(duì)象所用的8051的存儲(chǔ)空間,偏移量指向?qū)嶋H地址。一個(gè)一般指針可以訪問(wèn)任何變量而不管它在8051存儲(chǔ)器的位置。1041.通用指針C51提供一個(gè)3字節(jié)的通用指針,通用指針聲明和使用與標(biāo)準(zhǔn)C語(yǔ)言完全一樣。通用指針的形式如下:數(shù)據(jù)類(lèi)型*指針變量;例如:

uchar*pz例中pz就是通用指針,用3字節(jié)來(lái)存儲(chǔ)指針,第一字節(jié)表示存儲(chǔ)器類(lèi)型,第二、三字節(jié)分別是指針?biāo)赶驍?shù)據(jù)地址的高字節(jié)和低字節(jié),這種定義很方便但速度較慢,在所指向的目標(biāo)存儲(chǔ)器空間不明確時(shí)普遍使用。1052.基于存儲(chǔ)器的指針存儲(chǔ)器指針在定義時(shí)指明了存儲(chǔ)器類(lèi)型,并且指針總是指向特定的存儲(chǔ)器空間(片內(nèi)數(shù)據(jù)RAM、片外數(shù)據(jù)RAM或程序ROM)。例如:charxdata*str;//str指向xdata區(qū)中的char型數(shù)據(jù)int

xdata*pd; //pd指向外部RAM區(qū)中的int型整數(shù)由于定義中已經(jīng)指明了存儲(chǔ)器類(lèi)型,因此,相對(duì)于通用指針而言,指針第一個(gè)字節(jié)省略,對(duì)于data、bdata、idata與pdata存儲(chǔ)器類(lèi)型,指針僅需要1B,因?yàn)樗鼈兊膶ぶ房臻g都在256B以內(nèi),而code和xdata存儲(chǔ)器類(lèi)型則需要2B指針,因?yàn)樗鼈兊膶ぶ房臻g最大為64KB。

106使用存儲(chǔ)器指針好處是節(jié)省了存儲(chǔ)空間,編譯器不用為存儲(chǔ)器選擇和決定正確的存儲(chǔ)器操作指令來(lái)產(chǎn)生代碼,使代碼更加簡(jiǎn)短,但必須保證指針不指向所聲明的存儲(chǔ)區(qū)以外的地方,否則會(huì)產(chǎn)生錯(cuò)誤。通用指針產(chǎn)生的代碼執(zhí)行速度比指定存儲(chǔ)區(qū)的指針要慢,因?yàn)榇鎯?chǔ)區(qū)在運(yùn)行前是未知的,編譯器不能優(yōu)化存儲(chǔ)區(qū)訪問(wèn),必須產(chǎn)生可以訪問(wèn)任何存儲(chǔ)區(qū)的通用代碼。由上所述,使用存儲(chǔ)器指針比使用通用指針效率高,存儲(chǔ)器指針?biāo)伎臻g小,速度更快,在存儲(chǔ)器空間明確時(shí),建議使用存儲(chǔ)器指針,如果存儲(chǔ)器空間不明確則使用通用指針。1071083.3C51語(yǔ)言的函數(shù)函數(shù)是一個(gè)完成一定相關(guān)功能的執(zhí)行代碼段。在高級(jí)語(yǔ)言中,函數(shù)與另外兩個(gè)名詞“子程序”和“過(guò)程”用來(lái)描述同樣的事情。在C51語(yǔ)言中使用的是函數(shù)這個(gè)術(shù)語(yǔ)。一個(gè)C51程序必須至少有一個(gè)函數(shù),以main為名,稱(chēng)為主函數(shù),主函數(shù)是唯一的,整個(gè)程序從這個(gè)主函數(shù)開(kāi)始執(zhí)行。C51語(yǔ)言還可建立和使用庫(kù)函數(shù),可由用戶根據(jù)需求調(diào)用。1093.3.1函數(shù)的分類(lèi)從結(jié)構(gòu)上分,C51語(yǔ)言函數(shù)可分為主函數(shù)main()和普通函數(shù)兩種。而普通函數(shù)又劃分為兩種:標(biāo)準(zhǔn)庫(kù)函數(shù)和用戶自定義函數(shù)。1.標(biāo)準(zhǔn)庫(kù)函數(shù)由C51編譯器提供的。編程者在進(jìn)行程序設(shè)計(jì)時(shí),應(yīng)該善于充分利用這些功能強(qiáng)大、資源豐富的標(biāo)準(zhǔn)庫(kù)函數(shù)資源,以提高編程效率。用戶可直接調(diào)用C51庫(kù)函數(shù)而不需為這個(gè)函數(shù)寫(xiě)任何代碼,只需要包含具有該函數(shù)說(shuō)明的頭文件即可。例如調(diào)用輸出函數(shù)printf時(shí),要求程序在調(diào)用輸出庫(kù)函數(shù)前包含以下的include命令:

#include<stdio.h>1102.用戶自定義函數(shù)用戶自定義函數(shù)是用戶根據(jù)需要所編寫(xiě)的函數(shù)。從函數(shù)定義的形式分為:無(wú)參函數(shù)、有參函數(shù)和空函數(shù)。(1)無(wú)參函數(shù)此種函數(shù)在被調(diào)用時(shí),既無(wú)參數(shù)輸入,也不返回結(jié)果給調(diào)用函數(shù),只是為完成某種操作而編寫(xiě)的函數(shù)。無(wú)參函數(shù)的定義形式為:返回值類(lèi)型標(biāo)識(shí)符函數(shù)名(){ 函數(shù)體;}111無(wú)參函數(shù)一般不帶返回值,因此函數(shù)的返回值類(lèi)型的標(biāo)識(shí)符可省略。例如函數(shù):main(),為無(wú)參函數(shù),返回值類(lèi)型的標(biāo)識(shí)符可省略,默認(rèn)值是int類(lèi)型。(2)有參函數(shù)調(diào)用此種函數(shù)時(shí),必須提供實(shí)際的輸入函數(shù)。有參函數(shù)的定義形式為:返回值類(lèi)型標(biāo)識(shí)符函數(shù)名(形式參數(shù)列表)形式參數(shù)說(shuō)明{ 函數(shù)體;}112【例】定義一個(gè)函數(shù)max(),用于求兩個(gè)數(shù)中的大數(shù)。inta,bintmax(a,b){ if(a>b)return(a); elsereturn(b);}程序段中,a、b為形式參數(shù)。return()為返回語(yǔ)句。(3)空函數(shù)此種函數(shù)體內(nèi)是空白的。調(diào)用空函數(shù)時(shí),什么工作也不做,不起任何作用。定義空函數(shù)的目的,并不是為了執(zhí)行某種操作,而是為了以后程序功能的擴(kuò)充。先將一些基本模塊的功能函數(shù)定義成空函數(shù),占好位113置,并寫(xiě)好注釋?zhuān)院笤儆靡粋€(gè)編好的函數(shù)代替它。這樣整個(gè)程序的結(jié)構(gòu)清晰,可讀性好,以后擴(kuò)充新功能方便??蘸瘮?shù)的定義形式為:返回值類(lèi)型標(biāo)識(shí)符函數(shù)名(){}例如:floatmin(){} /*空函數(shù),占好位置*/1143.3.2函數(shù)的參數(shù)與返回值1.函數(shù)的參數(shù)C語(yǔ)言采用函數(shù)之間的參數(shù)傳遞方式,使一個(gè)函數(shù)能對(duì)不同的變量進(jìn)行功能相同的處理,從而大大提高了函數(shù)的通用性與靈活性。函數(shù)之間的參數(shù)傳遞,由主函數(shù)調(diào)用時(shí)主調(diào)函數(shù)的實(shí)際參數(shù)與被調(diào)函數(shù)的形式參數(shù)之間進(jìn)行數(shù)據(jù)傳遞來(lái)實(shí)現(xiàn)。被調(diào)用函數(shù)的最后結(jié)果由被調(diào)用函數(shù)的return語(yǔ)句返回給調(diào)用函數(shù)。函數(shù)的參數(shù)包括形式參數(shù)和實(shí)際參數(shù)。115(1)形式參數(shù):函數(shù)的函數(shù)名后面括號(hào)中的變量名稱(chēng)為形式參數(shù),簡(jiǎn)稱(chēng)形參。(2)實(shí)際參數(shù):在函數(shù)調(diào)用時(shí),主調(diào)函數(shù)名后面括號(hào)中的表達(dá)式稱(chēng)實(shí)際參數(shù),簡(jiǎn)稱(chēng)實(shí)參。在C語(yǔ)言的函數(shù)調(diào)用中,實(shí)際參數(shù)與形式參數(shù)之間的數(shù)據(jù)傳遞是單向進(jìn)行的,只能由實(shí)際參數(shù)傳遞給形式參數(shù),而不能由形式參數(shù)傳遞給實(shí)際參數(shù)。實(shí)際參數(shù)與形式參數(shù)的類(lèi)型必須一致,否則會(huì)發(fā)生類(lèi)型不匹配的錯(cuò)誤。被調(diào)用函數(shù)的形式參數(shù)在函數(shù)未調(diào)用之前,并不占用實(shí)際內(nèi)存單元。只有當(dāng)函數(shù)調(diào)用發(fā)生時(shí),被調(diào)用函數(shù)的形式參數(shù)才分配給內(nèi)存單元,此時(shí)內(nèi)存中調(diào)用函數(shù)的實(shí)際參數(shù)和被調(diào)用函數(shù)的形式參數(shù)位于不同的單元。116在調(diào)用結(jié)束后,形式參數(shù)所占有的內(nèi)存被系統(tǒng)釋放,而實(shí)際參數(shù)所占有的內(nèi)存單元仍保留并維持原值。2.函數(shù)的返回值函數(shù)返回值是通過(guò)return語(yǔ)句獲得的。一個(gè)函數(shù)可有一個(gè)以上的return語(yǔ)句,但是多于一個(gè)的return語(yǔ)句必須在選擇結(jié)構(gòu)(if或do/case)中使用(例如前面求兩個(gè)數(shù)中的大數(shù)函數(shù)max()的例子),因?yàn)楸徽{(diào)用函數(shù)一定只能返回一個(gè)變量。

117函數(shù)返回值的類(lèi)型由返回值的標(biāo)識(shí)符來(lái)指定。例如在函數(shù)名之前的int指定函數(shù)的返回值的類(lèi)型為整型數(shù)(int)。若沒(méi)有指定函數(shù)的返回值類(lèi)型,默認(rèn)返回值為整型類(lèi)型。當(dāng)函數(shù)沒(méi)有返回值時(shí),則使用標(biāo)識(shí)符void進(jìn)行說(shuō)明。1181193.3.3函數(shù)的調(diào)用在一個(gè)函數(shù)中需要用到某個(gè)函數(shù)的功能時(shí),就調(diào)用該函數(shù)。調(diào)用者稱(chēng)為主調(diào)函數(shù),被調(diào)用者稱(chēng)為被調(diào)函數(shù)。1.函數(shù)調(diào)用的一般形式函數(shù)調(diào)用的一般形式: 函數(shù)名 {實(shí)際參數(shù)列表};

120若被調(diào)函數(shù)是有參函數(shù),則主調(diào)函數(shù)必須把被調(diào)函數(shù)所需的參數(shù)傳遞給被調(diào)函數(shù)。傳遞給被調(diào)函數(shù)的數(shù)據(jù)稱(chēng)為實(shí)際參數(shù)(簡(jiǎn)稱(chēng)實(shí)參),必須與形參的數(shù)據(jù)在數(shù)量、類(lèi)型和順序上都一致。實(shí)參可以是常量、變量和表達(dá)式。實(shí)參對(duì)形參的數(shù)據(jù)是單向的,即只能將實(shí)參傳遞給形參.2.函數(shù)調(diào)用的方式主調(diào)用函數(shù)對(duì)被調(diào)用函數(shù)的調(diào)用有以下3種方式。(1)函數(shù)調(diào)用語(yǔ)句函數(shù)調(diào)用語(yǔ)句把被調(diào)用函數(shù)的函數(shù)名作為主調(diào)函數(shù)的一個(gè)語(yǔ)句。例如:

print_message();此時(shí),并不要求函數(shù)返回結(jié)果數(shù)值,只要求函數(shù)完成某種操作。121(2)函數(shù)結(jié)果作為表達(dá)式的一個(gè)運(yùn)算對(duì)象函數(shù)結(jié)果作為表達(dá)式的一個(gè)運(yùn)算對(duì)象,例如:result=2*gcd(a,b);被調(diào)用函數(shù)以一個(gè)運(yùn)算對(duì)象出現(xiàn)在表達(dá)式中。這要求被調(diào)用函數(shù)帶有return語(yǔ)句,以便返回一個(gè)明確的數(shù)值參加表達(dá)式的運(yùn)算。被調(diào)用函數(shù)gcd為表達(dá)式的一部分,它的返回值乘2再賦給變量result。

(3)函數(shù)參數(shù)函數(shù)參數(shù)即被調(diào)用函數(shù)作為另一個(gè)函數(shù)的實(shí)際參數(shù)。例如:m=max(a,gcd(u,v));其中,gcd(u,v)是一次函數(shù)調(diào)用,它的值作為另一個(gè)函數(shù)的max()的實(shí)際參數(shù)之一。

1223.對(duì)調(diào)用函數(shù)的說(shuō)明在一個(gè)函數(shù)調(diào)另一個(gè)函數(shù)調(diào)用另一個(gè)函數(shù)時(shí),須具備以下條件:(1)被調(diào)用函數(shù)必須是已經(jīng)存在的函數(shù)(庫(kù)函數(shù)或用戶自定義的函數(shù))。(2)如果程序中使用了庫(kù)函數(shù),或使用了不在同一文件中的另外自定義函數(shù),則應(yīng)該在程序的開(kāi)頭處使用#include包含語(yǔ)句,將所有的函數(shù)信息包含到程序中來(lái)。

例如,#include<stdio.h>,將標(biāo)準(zhǔn)的輸入、輸出頭文件stdio.h(在函數(shù)庫(kù)中)包含到程序中來(lái)。在程序編譯時(shí),系統(tǒng)會(huì)自動(dòng)將函數(shù)庫(kù)中的有關(guān)函數(shù)調(diào)入到程序中去,編譯出完整的程序代碼。123(3)如果程序中使用了自定義函數(shù),且該函數(shù)與調(diào)用它的函數(shù)同在一個(gè)文件中,則應(yīng)根據(jù)主調(diào)用函數(shù)與被調(diào)用函數(shù)在文件中的位置,決定是否對(duì)被調(diào)用函數(shù)作出說(shuō)明。a.

如果被調(diào)用函數(shù)在主調(diào)用函數(shù)之后,一般應(yīng)在主調(diào)用函數(shù)中,在被調(diào)用函數(shù)調(diào)用之前,對(duì)被調(diào)用函數(shù)的返回值類(lèi)型作出說(shuō)明。b.

如果被調(diào)用函數(shù)出現(xiàn)在主調(diào)用函數(shù)之前,不用對(duì)被調(diào)用函數(shù)進(jìn)行說(shuō)明。c.

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(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)論