單片機(jī)與嵌入式系統(tǒng)原理及應(yīng)用 課件 第3、4章 C51語言程序設(shè)計、mcs-51單片機(jī)內(nèi)部資源及應(yīng)用_第1頁
單片機(jī)與嵌入式系統(tǒng)原理及應(yīng)用 課件 第3、4章 C51語言程序設(shè)計、mcs-51單片機(jī)內(nèi)部資源及應(yīng)用_第2頁
單片機(jī)與嵌入式系統(tǒng)原理及應(yīng)用 課件 第3、4章 C51語言程序設(shè)計、mcs-51單片機(jī)內(nèi)部資源及應(yīng)用_第3頁
單片機(jī)與嵌入式系統(tǒng)原理及應(yīng)用 課件 第3、4章 C51語言程序設(shè)計、mcs-51單片機(jī)內(nèi)部資源及應(yīng)用_第4頁
單片機(jī)與嵌入式系統(tǒng)原理及應(yīng)用 課件 第3、4章 C51語言程序設(shè)計、mcs-51單片機(jī)內(nèi)部資源及應(yīng)用_第5頁
已閱讀5頁,還剩128頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第3章C51語言程序設(shè)計3.1C51程序結(jié)構(gòu)3.2C51數(shù)據(jù)結(jié)構(gòu)3.3C51絕對地址訪問3.4C51的運(yùn)算符及表達(dá)式3.5C51的輸入輸出3.6C51程序基本結(jié)構(gòu)與相關(guān)語句3.7函數(shù)C51是為51系列單片機(jī)設(shè)計的一種C語言,其特點(diǎn):

C51語言已成為51系列單片機(jī)程序開發(fā)的主流軟件方法。結(jié)構(gòu)化語言,代碼緊湊——效率可與匯編語言媲美接近真實語言,程序可讀性強(qiáng)——易于調(diào)試、維護(hù)庫函數(shù)豐富,編程工作量小——產(chǎn)品開發(fā)周期短機(jī)器級控制能力,可直接對硬件操作——適合于嵌入式系統(tǒng)開發(fā)目標(biāo)代碼質(zhì)量高,執(zhí)行性效率高——效率僅比匯編語言低10~20%與匯編指令無關(guān),易于掌握——在單片機(jī)基礎(chǔ)上上手快3.1C51程序結(jié)構(gòu)C51與標(biāo)準(zhǔn)C語言對比相同之處:語法規(guī)則、程序結(jié)構(gòu)、編程方法舉例:LED閃爍控制功能預(yù)處理命令---------函數(shù)說明----------全局變量定義------

主函數(shù)----------自定義函數(shù)---------局部變量定義--------

函數(shù)體

函數(shù)體------C51程序結(jié)構(gòu)C51與標(biāo)準(zhǔn)C語言對比不同之處:

(1)庫函數(shù):標(biāo)準(zhǔn)的C語言定義的庫函數(shù)是按通用微型計算機(jī)來定義的,而C51中的庫函數(shù)是按MCS-51單片機(jī)相應(yīng)情況來定義的。(2)數(shù)據(jù)類型:在C51中還增加了幾種針對MCS-51單片機(jī)特有的數(shù)據(jù)類型。(3)存儲模式:C51中變量的存儲模式是與MCS-51單片機(jī)的存儲器緊密相關(guān)的。(4)輸入/輸出處理:C51中的輸入/輸出是通過MCS-51串行口來完成的,輸入/輸出指令執(zhí)行前必須要對串行口進(jìn)行初始化。(5)函數(shù)使用方面:

C51中有專門的中斷函數(shù)

。3.2C51數(shù)據(jù)結(jié)構(gòu)

任何程序設(shè)計都離不開對數(shù)據(jù)的處理,數(shù)據(jù)在計算機(jī)內(nèi)存中的存放情況由數(shù)據(jù)結(jié)構(gòu)決定,C語言的數(shù)據(jù)結(jié)構(gòu)是以數(shù)據(jù)類型出現(xiàn)的。

標(biāo)準(zhǔn)C語言的數(shù)據(jù)類型可分為基本數(shù)據(jù)類型和組合數(shù)據(jù)類型。標(biāo)準(zhǔn)C語言的基本數(shù)據(jù)類型有字符型char、短整型short、整型int、長整型long、浮點(diǎn)型float和雙精度型double。C51的數(shù)據(jù)類型與標(biāo)準(zhǔn)C語言中的數(shù)據(jù)類型基本相同,但其中char型與short型相同,float型與double型相同。另外,C51中還有專門針對MCS-51單片機(jī)的特殊功能寄存器型和位類型。組合數(shù)據(jù)類型有數(shù)組類型、結(jié)構(gòu)體類型、共同體類型和枚舉類型,另外還有指針類型和空類型。

在程序執(zhí)行過程中,數(shù)值不變的量為常量,數(shù)值不斷變化的量為變量。使用一個變量之前,必須進(jìn)行定義,以便編譯系統(tǒng)為它分配相應(yīng)的存儲單元。變量名與存儲單元地址相對應(yīng),變量值與存儲單元的內(nèi)容相對應(yīng)。例如在51單片機(jī)多存儲空間中如何確定變量與地址的關(guān)系?3.2.1C51的變量及其定義的格式【存儲種類】數(shù)據(jù)類型【存儲類型】

變量名(標(biāo)準(zhǔn)C)(標(biāo)準(zhǔn)C)*括號項【】——可以缺?。ǖ栌腥笔≈担〤51變量定義的四要素:(C51特有)(標(biāo)準(zhǔn)C+C51)【存儲種類】

數(shù)據(jù)類型【存儲類型】變量名存儲種類用于說明變量的作用范圍:1、auto(自動型)——作用范圍在定義它的函數(shù)體或復(fù)合語句內(nèi)部,當(dāng)定義它的函數(shù)體或復(fù)合語句執(zhí)行時,C51才為該變量分配內(nèi)存空間,結(jié)束時占用的內(nèi)存空間釋放。(缺?。?、extern(外部型)——在一個函數(shù)體內(nèi),當(dāng)要使用一個已在該函數(shù)體外或別的程序中定義過的外部變量時,該變量在該函數(shù)體內(nèi)要用extern說明。外部變量被定義后分配固定的內(nèi)存空間,在程序整個執(zhí)行時間內(nèi)都有效,直到程序結(jié)束才釋放。3、static(靜態(tài)型)——在函數(shù)體內(nèi)部定義的靜態(tài)變量為內(nèi)部靜態(tài)變量,它在對應(yīng)的函數(shù)體內(nèi)有效,一直存在,但在函數(shù)體外不可見。在多文件或多模塊處理中,外部靜態(tài)變量只在文件內(nèi)部或模塊內(nèi)部有效。4、register(寄存器型)——它定義的變量存放在CPU內(nèi)部的寄存器中,處理速度快,但數(shù)量少。C51的基本數(shù)據(jù)類型【存儲種類】數(shù)據(jù)類型

【存儲類型】變量名基本數(shù)據(jù)類型長度取值范圍unsignedchar1字節(jié)0~+255signedchar1字節(jié)–128~+127unsignedint2字節(jié)0~+65535signedint2字節(jié)–32768~+32767unsignedlong4字節(jié)0~+4294967295signedlong4字節(jié)–2147483648~+2147483647float4字節(jié)–3.402823E+38~+3.402823E+38bit1位0或1sbit1位0或1sfr1位0~+255sfr162字節(jié)0~+65535*有符號數(shù)類型可以忽略signed標(biāo)識符(1)C51擴(kuò)充的3種基本數(shù)據(jù)類型:bit、sfr或sfr16、sbit

bit型存儲格式sfr型存儲格式sfrbit型存儲格式關(guān)鍵詞sfr或sfr16用于定義SFR字節(jié)地址變量,語法規(guī)則:

sfr

sfr_name=字節(jié)地址常數(shù);

sfr16sfr_name=字節(jié)地址常數(shù);例如,sfrP0=0x80;//定義P0口地址80H

sfrPCON=0x87;//定義PCON地址87H

sfr16DPTR=0x82;//定義DPTR的低地址82H

注意:C51語言中十六進(jìn)制整數(shù)是數(shù)值前加0x或0X前綴。sfr或sfr16型

bit型關(guān)鍵詞bit用于定義一般的可位處理的位變量,語法規(guī)則:注意:bit型變量的位地址是由編譯器為其隨機(jī)分配的(定義時不能用戶指定);位地址范圍是在片內(nèi)RAM可位尋址區(qū)。bitbit_name

[=0或1];例如:bitdoor=0;//定義一個叫door的位變量且初值為0CYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PD0^7

D7HD6HD5HD4HD3HD2HD1HD0HD0HPSWD0^6

D0^5

D0^4

D0^3

D0^2

D0^1

D0^0

絕對位地址相對位地址字節(jié)地址位地址表達(dá)形式:絕對位地址、相對位地址關(guān)鍵詞sbit用于定義SFR位地址變量注意:與bit型變量不同,sbit型變量的位地址是由用戶指定的,位地址范圍在可位尋址的SFR中。sbit型

1)將SFR的絕對位地址定義為位變量名

sbit

bit_name=位地址常數(shù);例如,sbit

CY=0xD7;3)將SFR的相對位位置定義位變量名(SFR名稱+位位置)

sbit

bit_name=sfr_name^位位置;例如,sbit

CY=PSW^7;2)將SFR的相對位地址定義為位變量名(SFR字節(jié)地址+位位置)

sbit

bit_name=sfr字節(jié)地址

^位位置;

例如,sbit

CY=0xD0^7;sbit型可用三種定義形式:CYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PCYACF0RS1RS0OVF1PD0^7

D7HD6HD5HD4HD3HD2HD1HD0HD0HPSWD0^6

D0^5

D0^4

D0^3

D0^2

D0^1

D0^0

絕對位地址相對位地址字節(jié)地址

C51編譯器在頭文件“REG51.H”中定義了全部sfr/sfr16和sbit變量。

用一條預(yù)處理命令#include<REG51.H>把這個頭文件包含到C51程序中,無需重新定義即可直接使用它們的名稱。編程中變量的定義及使用:(2)C51常用的組合數(shù)據(jù)類型:指針、數(shù)組

C51的指針

C語言指針的一般定義形式為:

數(shù)據(jù)類型*指針變量名[=&被指向變量名];其中,指針變量指向一個由“數(shù)據(jù)類型”說明的變量。被指向變量和指針變量都位于C編譯器默認(rèn)的內(nèi)存區(qū)中。例如:inta=’A’;int*p1=&a;這表示p1是一個指向int型變量的指針變量,此時p1的值為int型變量a的地址,而a和p1兩個變量都位于C編譯器默認(rèn)的內(nèi)存區(qū)中。對于C51,除了數(shù)據(jù)類型外,指針定義中還應(yīng)能說明:1)指針變量自身位于哪個存儲區(qū)中?

2)被指向變量位于哪個存儲區(qū)中?

C51指針的一般定義形式:

數(shù)據(jù)類型[存儲類型1]*[存儲類型2]變量名[=&被指向變量名];數(shù)據(jù)類型——被指向變量的類型,如int型或char型存儲類型1——被指向變量所在的存儲區(qū),缺省時由地址賦值關(guān)系決定存儲類型2——指針變量所在的存儲區(qū),缺省時為編譯器默認(rèn)的存儲區(qū)例1若采用SMALL編譯模式,試解釋下述定義的含義。

charxdataa=‘A’;

char*ptr=&a;解:ptr是一個指向char型變量的指針,它本身位于SMALL編譯模式默認(rèn)的data存儲區(qū)里,此時它指向位于xdata存儲區(qū)里的char型變量a的地址。數(shù)據(jù)類型[存儲類型1]*[存儲類型2]變量名[=&被指向變量名];例2試解釋下述定義的含義 charxdataa=‘A’; char*ptr=&a; charidatab=‘B’; ptr=&b;解:以char*ptr形式定義的指針變量,既可指向位于xdata存儲區(qū)的char型變量a的地址,也可指向位于idata存儲區(qū)的char型變量b的地址(由賦值操作關(guān)系決定)。前兩句與例1相同charxdataa=‘A’;char*ptr=&a;例3試解釋以下指針定義的含義 charxdataa=‘A’; charxdata*ptr=&a;

解:ptr是位于data存儲區(qū)且固定指向xdata存儲區(qū)的char型變量的指針變量,此時ptr的值為變量a的地址(不能像例2那樣再將idata存儲區(qū)的char型變量b的地址賦予ptr)。例4試解釋以下指針定義的含義 charxdataa=‘A’; charxdata*idataptr=&a;解:ptr是固定指向xdata存儲區(qū)的char型變量的指針變量,它自身存放在idata存儲區(qū)中,此時ptr指向位于xdata存儲區(qū)中的char型變量a的地址。例5輸入兩個整數(shù)x與y,經(jīng)比較后按從大到小的順序輸出。

解:ptr是固定指向xdata存儲區(qū)的char型變量的指針變量,它自身存放在idata存儲區(qū)中,此時ptr指向位于xdata存儲區(qū)中的char型變量a的地址。例5輸入兩個整數(shù)x與y,經(jīng)比較后按從大到小的順序輸出。

解:#include<reg51.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();main(){

intx,y;

int*p,*p1,*p2;

serial_initial();

printf("inputxandy:\n");

scanf("%d%d",&x,&y);

p1=&x;p2=&y;

if(x<y){p=p1;p1=p2;p2=p;}

printf("max=%d,min=%d\n",*p1,*p2);

while(1);}程序執(zhí)行結(jié)果:inputxandy;48max=8,min=4在這個程序中定義了3個指針變量:*p、*p1和*p2,它們都指向整型變量。經(jīng)過賦值后,p1指向x,p2指向y。然后比較變量x和y的大小。C51構(gòu)造數(shù)據(jù)類型—數(shù)組數(shù)組是一組有序數(shù)據(jù)的集合,數(shù)組中的每一個數(shù)據(jù)都屬于同一數(shù)據(jù)類型。數(shù)組中的各個元素可以用數(shù)組名和下標(biāo)來唯一確定。1)一維數(shù)組一維數(shù)組只有一個下標(biāo),定義的形式如下:數(shù)據(jù)類型

數(shù)組名[常量表達(dá)式]={初值1,初值2,...}例6

試解釋下述定義的含義:

unsignedcharx[5]。解:定義了一個無符號字符數(shù)組,數(shù)組名為x,數(shù)組中的元素個數(shù)為5,分別為x[0]~x[4]。例7

試解釋下述定義的含義:

inty[3]={1,2,3}。解:定義了一個有符號整型數(shù)組,數(shù)組名為y,數(shù)組中元素個數(shù)為3,定義的同時給數(shù)組中的三個元素賦初值,賦初值分別為1、2、3

,即y[0]=1,y[1]=2,y[2]=3。*注意:1、C51語言中數(shù)組的下標(biāo)是從0開始;2、C51規(guī)定在引用數(shù)組時,只能逐個引用數(shù)組中的各個元素,而不能一次引用整個數(shù)組。但如果是字符數(shù)組則可以一次引用整個數(shù)組。比如:

#include<stdio.h> main(){charc[10]; scanf(“%s”,c); printf(“%s\n”,c);}

2)字符數(shù)組用來存放字符數(shù)據(jù)的數(shù)組稱為字符數(shù)組,字符數(shù)組中的每一個元素都用來存放一個字符,也可用字符數(shù)組來存放字符串。字符數(shù)組的定義同一般數(shù)組相同,只是在定義時把數(shù)據(jù)類型定義為char型。例如:charstring1[10]和charstring2[20];定義了包含了10元素和20個元素的兩個字符數(shù)組。*注意:存放字符時,一個字符占一個數(shù)組元素;而存放字符串時,結(jié)束符“\0”自動存放于字符串的后面,也要占一個元素位置,因而定義數(shù)組長度時應(yīng)比字符串長度大1。例8用數(shù)組計算并輸出Fibonacci數(shù)列的前20項。解:Fibonacci數(shù)列在數(shù)學(xué)和計算機(jī)算法中十分有用。Fibonacci數(shù)列是這樣的一組數(shù):第一個數(shù)字為0,第二個數(shù)字為1,之后每個數(shù)字都是前兩個數(shù)字之和。設(shè)計時通過數(shù)組存放Fibonacci數(shù)列,從第3項開始可通過累加的方法計算得到。程序如下:#include<reg51.h>//包含特殊功能寄存器庫

#include<stdio.h>//包含I/O函數(shù)庫

voidserial_initial(void){//printf函數(shù)串口參數(shù)設(shè)置

{

SCON=0x52;//串口初始化

TMOD=0x20;

TH1=0XF3;

TR1=1;}main(){intfib[20],i;fib[0]=0;fib[1]=1;serial_initial();for(i=2;1<20;1++)fib[i]=fib[i-2]+fib[i-1];for(i=0;i<20;i++){if(i%5==0)printf("\n");printf("%6d",fib[i]);}while(1);

}程序執(zhí)行結(jié)果:01123581321345589144233377610987159725844148注意:在C51的一般I/O函數(shù)庫中定義的I/O函數(shù)都是通過串行接口實現(xiàn)的,在使用I/O函數(shù)之前,應(yīng)先對MCS-51單片機(jī)的串行接口進(jìn)行初始化??梢园汛诔跏蓟^程定義成一個函數(shù),然后在程序中調(diào)用即可。

存儲類型體現(xiàn)了變量的存放區(qū)域。51系列單片機(jī)共有6個存儲類型(分布在3個邏輯存儲空間中)。data區(qū)code區(qū)xdata區(qū)bdata區(qū)pdata區(qū)idata區(qū)【存儲種類】

數(shù)據(jù)類型【存儲類型】變量名不同存儲類型的特點(diǎn)SMALL系統(tǒng)COMPACT系統(tǒng)LARGE系統(tǒng)編譯模式三種編譯模式分別對應(yīng)于三種缺省存儲類型;若無特殊聲明,均為“SMALL編譯模式”。存儲器類型描

述data直接尋址的片內(nèi)RAM低128B,訪問速度快bdata片內(nèi)RAM的可位尋址區(qū)(20H~2FH),允許字節(jié)和位混合訪問idata間接尋址訪問的片內(nèi)高128BRAM(適用于52子系列)pdata用Ri間接訪問的片外RAM的低256Bxdata用DPTR間接訪問的片外RAM,允許訪問全部64KB片外RAMcode程序存儲器ROM64KB空間例9變量的存儲模式。1)#pragmasmall /*變量的存儲模式為SMALL*/chark1; /*k1變量存儲器類型為data*/intxdatam1; /*ml變量存儲器類型為xdata*/2)#pragmacompact /*變量的存儲模式為compact*/chark2; /*k2變量存儲器類型為pdata*/intxdatam2; /*m2變量存儲器類型為xdata*/3)intfuncl(intx1,inty1)large/*函數(shù)的存儲模式為LARGE,*/{

/*函數(shù)func1的形參xl和y1的存儲器類型為xdata*/return(x1+y1);}4)intfunc2(intx2,inty2)/*函數(shù)的存儲模式隱含為SMALL*/{/*函數(shù)func2的形參x2和y2的存儲器類型為data*/return(x2-y2);}

變量名是C51為區(qū)分不同變量而為不同變量取的名稱。C51中規(guī)定變量名可以由字母、數(shù)字和下畫線3種字符組成,且第一個字母必須為字母或下畫線,變量名長度隨編譯系統(tǒng)而定。變量名有兩種:普通變量名和指針變量名,它們的區(qū)別是指針變量名的前面要帶“*”號。

變量名具有字母大小寫的敏感性,如SUM和sum代表不同的變量。

注意:頭文件中定義的變量都是大寫的,若程序采取小寫變量則需要重新定義。【存儲種類】

數(shù)據(jù)類型【存儲類型】

變量名C51擴(kuò)展的若干關(guān)鍵字一覽表

變量名不得使用標(biāo)準(zhǔn)C語言和C51語言的關(guān)鍵字。unsignedchardatasystem_status=0;//定義system_status為無符號字符型自動變量,該變量位于data區(qū)中且初值為0。變量定義舉例變量名為system_status位于片內(nèi)RAM區(qū)無符號字符型自動型初值為零unsignedcharbdatastatus_byte;//定義status_byte為無符號字符型自動變量,該變量位于bdata區(qū)例10編程將8051的內(nèi)部數(shù)據(jù)存儲器25H單元和30H單元的數(shù)據(jù)相乘,結(jié)果存到外部數(shù)據(jù)存儲器中(任意位置)。解:#include<math.h>voidmain(){unsignedchar*ptr,a,b;unsignedintxdatax;ptr=0x25;a=*ptr;ptr=0x30;b=*ptr;x=a*b;}

在C51中,可以通過變量的形式訪問MCS-51單片機(jī)的存儲器,也可以通過絕對地址來訪問存儲器。對于絕對地址,訪問形式有三種。(1)使用C51運(yùn)行庫中預(yù)定義宏C51編譯器提供了一組宏定義來對51系列單片機(jī)的code、data、pdata和xdata空間進(jìn)行絕對尋址。

定義了8個宏定義,這些函數(shù)原型放在absacc.h文件中。使用時需用預(yù)處理命令把該頭文件包含到文件中,形式為:#include<absacc.h>。3.3C51絕對地址訪問

其中:CBYTE以字節(jié)形式對code區(qū)尋址,DBYTE以字節(jié)形式對data區(qū)尋址,PBYTE以字節(jié)形式對pdata區(qū)尋址,XBYTE以字節(jié)形式對xdata區(qū)尋址,CWORD以字形式對code區(qū)尋址,DWORD以字形式對data區(qū)尋址,PWORD以字形式對pdata區(qū)尋址,XWORD以字形式對xdata區(qū)尋址。

訪問形式如下:

宏名[地址]宏名為CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD或XWORD。地址為存儲單元的絕對地址,一般用十六進(jìn)制形式表示。例11通過絕對地址對存儲單元的訪問。解:#include<absacc.h>/*將絕對地址頭文件包含到文件中*/#include<reg51.h>/*將寄存器頭文件包含到文件中*/#defineucharunsignedchar /*定義符號uchar為數(shù)據(jù)類型符unsignedchar*/#defineuintunsignedint /*定義符號uint為數(shù)據(jù)類型符unsignedint*/voidmain(void){

ucharvar1;

uintvar2;

var1=XBYTE[0x0005];/*XBYTE[0x0005]訪問片外RAM的0005字節(jié)單元*/

var2=XWORD[0x0002];/*XWORD[0x0002]訪問片外RAM的0002字單元*/

while(1);}

上述程序中,XBYTE[0x0005]就是以絕對地址方式訪問的片外RAM0005字節(jié)單元,XWORD[0x0002]就是以絕對地址方式訪問的片外RAM0002字單元。

(2)通過指針訪問采用指針的方法實現(xiàn)在C51程序中對任意指定的存儲器單元進(jìn)行訪問。例12

通過指針實現(xiàn)絕對地址的訪問。解:#defineucharunsignedchar/*定義符號uchar為數(shù)據(jù)類型符unsignedchar*/#defineuintunsignedint/*定義符號uint為數(shù)據(jù)類型符unsignedint*/voidfunc(void){uchardatavar1;ucharpdata*dp1; /*定義一個指向pdata區(qū)的指針dp1*/uintxdata*dp2; /*定義一個指向xdata區(qū)的指針dp2*/uchardata*dp3; /*定義一個指向data區(qū)的指針dp3*/dp1=0x30; /*dp1指針賦值,指向pdata區(qū)的30H單元*/dp2=0x1000; /*dp2指針賦值,指向xdata區(qū)的1000H単元*/*dp1=0xff; /*將數(shù)據(jù)0xff送到片外RAM30H單元*/*dp2=0x1234; /*將數(shù)據(jù)0x1234送到片外RAM1000H單元*/dp3=&var1; /*dp3指針指向data區(qū)的var1變量*/*dp3=0x20; /*給變量var1賦值0x20*/}

(3)通過_at_關(guān)鍵字訪問使用_at_對指定的存儲器空間的絕對地址進(jìn)行訪問,一般格式如下:[存儲器類型]數(shù)據(jù)類型變量名_at_地址常數(shù);

其中,存儲器類型為data、bdata、xdata、pdata等C51能識別的存儲類型,如省略則按默認(rèn)存儲器類型確定變量的存儲區(qū)域;數(shù)據(jù)類型為C51支持的數(shù)據(jù)類型;地址常數(shù)用于指定變量的絕對地址,必須位于有效的存儲器空間之內(nèi);使用_at_定義的變量必須為全局變量。例13

通過_at_實現(xiàn)絕對地址的訪問。解:#defineucharunsignedchar/*定義符號uchar為數(shù)據(jù)類型符unsignedchar*/#defineuintunsignedint /*定義符號uint為數(shù)據(jù)類型符unsignedint*/

dataucharx1_at_0x40; /*在data區(qū)中定義字節(jié)變量x1,*/

/*

它的地址為40H*/

xdatauintx2_at_0x2000; /*在xdata區(qū)中定義字變量x2,/*

/*

它的地址為2000H*/voidmain(void){

x1=0xff;

x2=0x1234;

while(1);}C51具有十分豐富的運(yùn)算符,利用這些運(yùn)算符可以組成各種表達(dá)式及語句。在C51中,運(yùn)算符按其在表達(dá)式中所起的作用,可分為賦值運(yùn)算符、算術(shù)運(yùn)算符、自增與自減運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、條件運(yùn)算符和指針和地址運(yùn)算符等。

表達(dá)式則是由運(yùn)算符及運(yùn)算對象所組成的具有特定含義的式子。3.4C51的運(yùn)算符及表達(dá)式(1)

賦值運(yùn)算符:“=”功能:將一個數(shù)據(jù)的值賦給一個變量;賦值語句格式:變量=表達(dá)式;執(zhí)行時先計算出右邊表達(dá)式的值,然后賦給左邊的變量。例如:x=8+9;/*將8+9的值賦給變量x*/x=y=5;/*將常數(shù)5同時賦給變量x和y*/在C51中,允許在一個語句中同時給多個變量賦值,賦值順序自右向左。(2)

算術(shù)運(yùn)算符C51中支持的算術(shù)運(yùn)算符有:

+

加或取正值運(yùn)算符

-

減或取負(fù)值運(yùn)算符乘運(yùn)算符

*

乘運(yùn)算符;

/

除運(yùn)算符;

%

取余運(yùn)算符。

加、減、乘運(yùn)算相對比較簡單;對于除運(yùn)算,如相除的兩個數(shù)為浮點(diǎn)數(shù),則運(yùn)算的結(jié)果也為浮點(diǎn)數(shù),如相除的兩個數(shù)為整數(shù),則運(yùn)算的結(jié)果也為整數(shù),即為整除。如25.0/20.0結(jié)果為1.25,而25/20結(jié)果為1。對于取余運(yùn)算,則要求參加運(yùn)算的兩個數(shù)必須為整數(shù),運(yùn)算結(jié)果為它們的余數(shù)。例如:x=5%3,結(jié)果x的值為2。(3)

自增與自減運(yùn)算符

++:變量加1

--:變量減1

執(zhí)行時先使用變量,再使變量加/減1。

例如:

i++;/*先使用變量i,再使i增1*/

j--;/*先使用變量j,再使減1*/(4)

關(guān)系運(yùn)算符C51中有6種關(guān)系運(yùn)算符:

>

大于;<

小于;>=

大于等于;

<=

小于等于;==

等于;!=

不等于

關(guān)系運(yùn)算符用于比較兩個數(shù)的大小,用關(guān)系運(yùn)算符將兩個表達(dá)式連接起來形成的式子稱為關(guān)系表達(dá)式。關(guān)系表達(dá)式通常用來作為判別條件構(gòu)造分支或循環(huán)程序。

關(guān)系運(yùn)算的結(jié)果為邏輯量,成立為真(1),不成立為假(0)。其結(jié)果可以作為一個邏輯量參與邏輯運(yùn)算。例如:5>3,結(jié)果為真(1),而10==100,結(jié)果為假(0)。注意:關(guān)系運(yùn)算符等于“==”與賦值運(yùn)算符“=”的區(qū)別。(5)

邏輯運(yùn)算符C51有3種邏輯運(yùn)算符:

邏輯或||:當(dāng)兩個條件式均為假時結(jié)果為假(0值),否則為真(非0值);

邏輯與&&:當(dāng)兩個條件式均為真時結(jié)果為真(非0值),否則為假(0值);

邏輯非!

:當(dāng)條件式原來為真(非0值)結(jié)果為假(0值),當(dāng)條件式原來為假(0值),邏輯非后結(jié)果為真(非0值)。

例如:若a=8,b=3,c=0,d=0,則!a為假,!c為真,a||c為真,c||d為假,a&&b為真,b&&c為假。(6)

位運(yùn)算符C51語言能對運(yùn)算對象按位進(jìn)行操作,位運(yùn)算是按位對變量進(jìn)行運(yùn)算,但并不改變參與運(yùn)算的變量的值。如果要求按位改變變量的值,則要利用相應(yīng)的賦值運(yùn)算。C51中位運(yùn)算符只能對整數(shù)進(jìn)行操作,不能對浮點(diǎn)數(shù)進(jìn)行操作。C51中的位運(yùn)算符有:

&

按位與(與邏輯與“&&”對比記憶)

|

按位或(與邏輯或“||”對比記憶)

^

按位異或

~

按位取反(與邏輯非“!”對比記憶)

<<

左移(最低位補(bǔ)0,與關(guān)系運(yùn)算符“>”對比記憶)

>>

右移(最高位補(bǔ)0,與關(guān)系運(yùn)算符“<”對比記憶)解:

a&b=00010000B=0x10a|b=01111111B=0x7fa^b=01101111B=0x6f~a=101010llB=0xaba<<2=01010000B=0x50b>>2=00001110B=0x0e例14a=0x54=01010100B,b=0x3b=00111011B,求:a&b、a|b、a^b、~a、a<<2、b>>2的值。(7)條件運(yùn)算符條件運(yùn)算符“?:”要求有三個運(yùn)算對象,一般格式為:

邏輯表達(dá)式?

表達(dá)式1:表達(dá)式2

其功能是先計算邏輯表達(dá)式的值,當(dāng)邏輯表達(dá)式的值為真(非0值)時,將計算的表達(dá)式1的值作為整個條件表達(dá)式的值;當(dāng)邏輯表達(dá)式的值為假(0值)時,將計算的表達(dá)式2的值作為整個條件表達(dá)式的值。

例如:條件表達(dá)式max=(a>b)?a:b

執(zhí)行結(jié)果是將a和b中較大的數(shù)賦值給變量max。(8)指針和地址運(yùn)算符指針為變量的訪問提供了另一種方式,變量的指針就是該變量的地址,還可以定義一個專門指向某個變量的地址的指針變量。為了表示指針變量和它所指向的變量地址之間的關(guān)系,C51中提供了兩個專門的運(yùn)算符:

*指針運(yùn)算符(取內(nèi)容)

&

取地址運(yùn)算符(取地址)

指針運(yùn)算符“*”放在指針變量前面,實現(xiàn)訪問以指針變量的內(nèi)容為地址的存儲單元。例如:指針變量p中的地址為2000H,則*p所訪問的是地址為2000H的存儲單元,執(zhí)行語句x=*p,把地址為2000H的存儲單元的內(nèi)容送給變量x。

取地址運(yùn)算符“&”放在變量的前面,通過它取得變量的地址,變量的地址通常送給指針變量。例如:設(shè)變量x的內(nèi)容為12H,地址為2000H,則&x的值為2000H。如有一指針變量P,則通常用p=&x,實現(xiàn)將x變量的地址送給指針變量p,指針變量p指向變量x,以后可以通過*p訪問變量x。(9)語句表達(dá)式在表達(dá)式的后邊加一個分號“;”就構(gòu)成了表達(dá)式語句,比如:a=++b*9;x=8;y=7;++k;在編寫程序時,可以一行放一個表達(dá)式形成表達(dá)式語句,也可以一行放多個表達(dá)式形成表達(dá)式語句,這時每個表達(dá)式后面都必須帶“;”號。另外,還可以僅由一個分號“;”占一行形成一個表達(dá)式語句,這種語句稱為空語句??照Z句是表達(dá)式語句的一個特例,空語句在語法上是一個語句,但在語義上它并不做具體的操作??照Z句在程序設(shè)計中通常用于兩種情況。①在程序中為有關(guān)語句提供標(biāo)號,用以標(biāo)記程序執(zhí)行的位置。例如,采用下面的語句可以構(gòu)成一個循環(huán):repeat:;;gotorepeat;②在while語句構(gòu)成的循環(huán)語句后面加一個分號,形成一個不執(zhí)行其他操作的空循環(huán)體。這種結(jié)構(gòu)通常用于對某位進(jìn)行判斷,當(dāng)不滿足條件時則等待,滿足條件時則執(zhí)行。例15下面這段子程序用于讀取8051單片機(jī)的串行接口的數(shù)據(jù),若沒有接收到,則等待,接收數(shù)據(jù)后返回,返回值為接收的數(shù)據(jù)。#include<reg51.h>{charc;while(!RI);//當(dāng)接收中斷標(biāo)志位RI為0時等待,為1時結(jié)束等待c=SBUF;RI=0;return(c);}(10)復(fù)合語句復(fù)合語句是由若干語句組合而成的一種語句。在C51中,用一個花括號“{}”將若干語句括在一起就形成了一個復(fù)合語句。復(fù)合語句的最后不需要以分號“;”結(jié)束,但內(nèi)部的各條語句仍需以分號“;”結(jié)束。復(fù)合語句的一般形式為{

局部變量定義;

語句1;

語句2;}函數(shù)的執(zhí)行部分(即函數(shù)體)就是一個復(fù)合語句。3.5C51的輸入輸出C51語言本身不提供輸入和輸出語句,輸入和輸出操作是由函數(shù)來實現(xiàn)的。C51的標(biāo)準(zhǔn)函數(shù)庫提供了一個名為“stdio.h”的一般I/O函數(shù)庫,其中定義了C51中的輸入和輸出函數(shù)。當(dāng)使用輸入和輸出函數(shù)時,需先用預(yù)處理命令“#include<stdio.h>”將該函數(shù)庫包含到文件中。C51定義的I/O函數(shù)都是通過串行接口實現(xiàn)的,在使用I/O函數(shù)之前,應(yīng)先對單片機(jī)的串行接口進(jìn)行初始化。選擇串口工作方式1,波特率由定時/計數(shù)器1的溢出率決定。例如,設(shè)系統(tǒng)時鐘為12MHz,波特率為2400bps,則初始化程序如下:SCON=0x52;TMOD=0x20;TL1=TH1=0xf3;TR1=1;(1)格式輸出函數(shù)printf()printf()函數(shù)的格式如下:printf(格式控制,輸出參數(shù)表)格式控制是用雙引號括起來的字符串,也稱轉(zhuǎn)換控制字符串,它包括3種信息:格式說明符、普通字符和轉(zhuǎn)義字符。(1)格式說明符,由“%”和格式字符組成,它的作用是指明輸出數(shù)據(jù)的格式,如%d、%f等。(2)普通字符,這些字符按原樣輸出,用來輸出某些提示信息。(3)轉(zhuǎn)義字符,就是前面介紹的轉(zhuǎn)義字符,用來輸出特定的控制符,如輸出轉(zhuǎn)義字符\n就是使輸出換一行。輸出參數(shù)表是需要輸出的一組數(shù)據(jù),可以是表達(dá)式。格式字符數(shù)據(jù)類型輸出格式dint有符號十進(jìn)制數(shù)uint無符號十進(jìn)制數(shù)oint無符號八進(jìn)制數(shù)xint無符號十六進(jìn)制數(shù),用“a~f”表示Xint無符號十六進(jìn)制數(shù),用“A~F”表示ffloat有符號十進(jìn)制數(shù)浮點(diǎn)數(shù),形式為[-]dddd.dddde,Efloat有符號十進(jìn)制數(shù)浮點(diǎn)數(shù),形式為[-]d.ddddE

ddg,Gfloat自動選擇e或f格式中更緊湊的一種輸出格式cchar單個字符s指針指向一個帶結(jié)束符的字符串p指針帶存儲器指示符和偏移量的指針,形式為M:aaaa。其中,M可分別為C(code)、D(data)、I(idata)、P(pdata),如M為a,則表示的是指針偏移量C51中的printf()函數(shù)的格式字符及功能(2)格式輸入函數(shù)scanf()

scanf()函數(shù)的格式如下scanf(格式控制,地址列表)

格式控制與printf()函數(shù)的情況類似,也是用雙引號括起來的一些字符,可以包括以下3種信息:空白字符、普通字符和格式說明。

(1)空白字符,包含空格、制表符和換行符等,此字符在輸出時被忽略。

(2)普通字符,除以百分號“%”開頭的格式說明符外的所有非空白字符,在輸入時要求原樣輸入。

(3)格式說明,由百分號“%”和格式字符組成,用于指明輸入數(shù)據(jù)的格式,它的基本情況與printf()相同。

地址列表是由若干地址組成的,它可以是指針變量、取地址運(yùn)算符“&”加變量(變量的地址)或字符串名(表示字符串的首地址)。格式字符數(shù)據(jù)類型輸入格式dint指針有符號十進(jìn)制數(shù)uint指針無符號十進(jìn)制數(shù)oint指針無符號八進(jìn)制數(shù)xint指針無符號十六進(jìn)制數(shù)f,e,Efloat指針浮點(diǎn)數(shù)cchar指針字符sstring指針字符串C51中的scantf()函數(shù)的格式字符及功能例16使用格式輸入/輸出函數(shù)的例子。#include<stdio.h> //包含I/O函數(shù)庫voidmain(void) //主函數(shù){

intx,y; //定義整型變量x和y

SCON=0x52; //串口初始化

TMOD=0x20;

TH1=0xF3;

TR1=1;

printf("inputx,y:\n"); //輸出提示信息

scanf("%d%d",&x,&y); //輸入x和y的值

printf("\n"); //輸出換行

printf("%d+%d=%d",x,y,x+y); //按十進(jìn)制數(shù)的形式輸出

printf("\n"); //輸出換行

printf("%xH+%xH=%XH",x,y,x+y);//按十六進(jìn)制數(shù)的形式輸出

while(1); //結(jié)束}C51語言是一種結(jié)構(gòu)化程序設(shè)計語言,程序由若干模塊組成,每個模塊包含若干基本結(jié)構(gòu),每個基本結(jié)構(gòu)中可以有若干語句。C51語言有3種基本結(jié)構(gòu):順序結(jié)構(gòu)、選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。順序結(jié)構(gòu)選擇結(jié)構(gòu)在C51中,實現(xiàn)選擇結(jié)構(gòu)的語句:單分支

if/else多分支if/elseifswitch/case3.6C51程序基本結(jié)構(gòu)與相關(guān)語句(a)當(dāng)型循環(huán)結(jié)構(gòu)(b)直到型循環(huán)結(jié)構(gòu)循環(huán)結(jié)構(gòu)

構(gòu)成循壞結(jié)構(gòu)的語句主要有:while、do…while、for和goto等。(1)if語句

if語句是C51中的一個基本條件選擇語句,它通常有3種格式:

(1)if(表達(dá)式){語句;}

(2)if(表達(dá)式){語句1;}

else{語句2;}

(3)if(表達(dá)式1){語句1;}

elseif(表達(dá)式2){語句2;}

……

elseif(表達(dá)式n-l){語句n-l:}

else{語句n}例17if語句的用法。①if(x!=y)P2=0xff;

執(zhí)行上面語句時,如果x不等于y,則向P2口輸出全1。

②if(x>y)max=x;elsemax=y;

執(zhí)行上面語句時,如x大于y成立,則把x送給最大值變量max;如x大于y不成立,則把y送給最大值變量max。使max變量得到x、y中的大數(shù)。

③if(score>=90)AA++;elseif(score>=80)BB++;elseif(score>=70)CC++;elseif(score>=60)DD++;elseEE++;

執(zhí)行上面語句后,根據(jù)分?jǐn)?shù)score使對應(yīng)分?jǐn)?shù)段計數(shù)器加1。(2)switch/case語句

if語句通過嵌套可以實現(xiàn)多分支結(jié)構(gòu),但結(jié)構(gòu)復(fù)雜。switch是C51中提供的專門處理多分支結(jié)構(gòu)的多分支選擇語句。它的格式如下:switch(表達(dá)式){case常量表達(dá)式1:{語句1;}break;

case常量表達(dá)式2:{語句2;}break;

.......

case常量表達(dá)式n:{語句n;}break;

default:{語句n+1;}}說明如下:①switch后面括號內(nèi)的表達(dá)式可以是整型或字符型表達(dá)式。②當(dāng)該表達(dá)式的值與某一“case”后面的常量表達(dá)式的值相等時,就執(zhí)行該“case”后面的語句,然后遇到break語句退出switch語句。若表達(dá)式的值與所有case后的常量表達(dá)式的值都不相同,則執(zhí)行default后面的語句,然后退出switch結(jié)構(gòu)。③每一個case常量表達(dá)式的值必須不同。④每個case語句后面可以有“break",也可以沒有。有break語句,執(zhí)行到break則退出switch結(jié)構(gòu),若沒有,則會順次執(zhí)行后面的語句,直到遇到break或結(jié)束。⑤每一個case語句后面可以帶一個語句,也可以帶多個語句,還可以不帶。例18switch…case語句的用法。將學(xué)生成績劃分為A~E,對應(yīng)不同的百分制分?jǐn)?shù),要求根據(jù)不同的等級打印出它的對應(yīng)百分?jǐn)?shù)??梢酝ㄟ^下面的switch…case語句實現(xiàn)?!璼witch(grade){case'A':printf("90~100\n");break;case'B':printf("80~90\n");break;case'C':printf("70~80\n");break;case'D':printf("60~70\n");break;case'E':printf("<60\n");break;default:printf("error"\n))}(3)while語句

while語句用于實現(xiàn)當(dāng)型循環(huán)結(jié)構(gòu),它的格式如下:

while(表達(dá)式)

{語句;}/*循環(huán)體*/

while語句后面的表達(dá)式是能否循環(huán)的條件,后面的語句是循環(huán)體。當(dāng)表達(dá)式為非0(“真”)時,重復(fù)執(zhí)行循環(huán)體內(nèi)的語句;當(dāng)表達(dá)式為0(“假”)時,則終止while循環(huán),程序?qū)?zhí)行循環(huán)結(jié)構(gòu)之外的下一條語句。

特點(diǎn):先判斷條件,后執(zhí)行循環(huán)體;如條件第一次就不成立,則循環(huán)體一次也不執(zhí)行;在循環(huán)體中對條件進(jìn)行改變,然后再判斷條件。例19下面程序通過while語句實現(xiàn)計算并輸出1~100的累加和。#include<reg51.h> //包含特殊功能寄存器庫#include<stdio.h> //包含I/O函數(shù)庫voidmain(void) //主函數(shù){inti,s=0; //定義整型變量i和si=1;SCON=0x52; //串口初始化

TMOD=0x20;TH1=0xF3;TR1=1;while(i<=100) //累加和在s中

{s=s+i;i++;}printf("1t2+3+…+100=%d\n",s);while(1);}程序執(zhí)行的結(jié)果:1+2+3+…+100=5050。(4)do…while語句

do...while語句用于實現(xiàn)直到型循環(huán)結(jié)構(gòu),它的格式如下:

do

{語句;}/*循環(huán)體*/

while(表達(dá)式);

特點(diǎn):先執(zhí)行循環(huán)體中的語句,后判斷表達(dá)式,如表達(dá)式成立(“真”),則再執(zhí)行循環(huán)體,然后又判斷,直到有表達(dá)式不成立(“假”)時,退出循環(huán),執(zhí)行do…while結(jié)構(gòu)的下一條語句;do...while語句在執(zhí)行時,循環(huán)體內(nèi)的語句至少會被執(zhí)行一次。例20通過do…while語句實現(xiàn)計算并輸出1~100的累加和。#include<reg51.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidmain(void)//主函數(shù){inti,s=0;//定義整型變量i和si=1;SCON=0x52;//串口初始化

TMOD=0x20;TH1=0xF3;TR1=1;do//累加和在s中

{s=s+i;i++;}while(i<=100);printf("1+2+3+…+100=%d\n",s);while(1);}程序執(zhí)行的結(jié)果:1+2+3+…+100=5050。(5)for語句在C51語言中,for語句是使用最靈活、用得最多的循環(huán)控制語句,它完全可以代替while語句。格式如下:for(表達(dá)式1;表達(dá)式2;表達(dá)式3){語句;}/*循環(huán)體*/表達(dá)式1一般為初值表達(dá)式,用于給循環(huán)變量賦初值;表達(dá)式2為條件表達(dá)式,對循環(huán)變量進(jìn)行判斷;表達(dá)式3為循環(huán)變量更新表達(dá)式,用于對循環(huán)變量的值進(jìn)行更新。執(zhí)行過程如下:(1)先求解表達(dá)式1的值。(2)通過表達(dá)式2進(jìn)行是否滿足循環(huán)條件判斷,如表達(dá)式2的值為真,則執(zhí)行循環(huán)體中的語句;執(zhí)行完循環(huán)體中的語句后,求解表達(dá)式3更新變量,并重新進(jìn)行循環(huán)條件判斷;如表達(dá)式2的值為假,則結(jié)束for循環(huán),執(zhí)行下面的一條語句。例21用for語句實現(xiàn)計算,并輸出1~100的累加和。#include<reg51.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidmain(void)//主函數(shù){

inti,s=0;//定義整型變量i和s

SCON=0x52;//串口初始化

TMOD=0x20;

TH1=0xF3;

TR1=1;

for(i=1;i<=100;1++)s=s+i;//累加和在s中

printf("1+2+3+…+100=%d\n",s);

while(1);}程序執(zhí)行的結(jié)果:1+2+3+…+100=5050。(6)循環(huán)的嵌套在一個循環(huán)的循環(huán)體中允許包含一個完整的循環(huán)結(jié)構(gòu),這種結(jié)構(gòu)稱為循環(huán)的嵌套。外面的循環(huán)稱為外循環(huán),里面的循環(huán)稱為內(nèi)循環(huán),如果在內(nèi)循環(huán)的循環(huán)體內(nèi)又包含循環(huán)結(jié)構(gòu),就構(gòu)成了多重循環(huán)。在C51中,允許3種循環(huán)結(jié)構(gòu)相互嵌套。例22用嵌套結(jié)構(gòu)構(gòu)造一個延時程序。voiddelay(unsignedintx){

unsignedcharj;

while(x--)

{for(j=0;j<125;j++);}}這里,用內(nèi)循環(huán)構(gòu)造一個基準(zhǔn)的延時,調(diào)用時通過參數(shù)設(shè)置外循環(huán)的次數(shù),這樣就可以形成各種延時關(guān)系。3.7函數(shù)

C51的程序是由一個主函數(shù)和若干子函數(shù)組成的,每個子函數(shù)都完成一定的功能。在一個程序中只能有一個主函數(shù),主函數(shù)不能被調(diào)用。程序執(zhí)行時,從主函數(shù)開始,到主函數(shù)的最后一條語句結(jié)束。子函數(shù)可以被主函數(shù)調(diào)用,也可以被其他子函數(shù)或其本身調(diào)用形成子程序嵌套。在C51中,系統(tǒng)提供了豐富的功能函數(shù),其被放于標(biāo)準(zhǔn)函數(shù)庫中,以供用戶調(diào)用。如果用戶需要的函數(shù)沒有被包含在函數(shù)庫中,用戶也可以根據(jù)需要自己定義函數(shù)以便使用。(1)函數(shù)的定義在用C51進(jìn)行程序設(shè)計的過程中,既可以用系統(tǒng)提供的標(biāo)準(zhǔn)庫函數(shù),也可以使用自己定義的函數(shù)。對于系統(tǒng)提供的標(biāo)準(zhǔn)庫函數(shù),用戶使用時需在之前通過預(yù)處理命令include將對應(yīng)的標(biāo)準(zhǔn)函數(shù)庫包含到程序開始。而對于用戶自定義的函數(shù),在使用之前必須對它進(jìn)行定義,定義之后才能調(diào)用。函數(shù)定義的一般格式如下:

函數(shù)類型函數(shù)名(形式參數(shù))[reentrant][interruptm][usingn]形式參數(shù)說明{

局部變量定義

函數(shù)體}函數(shù)格式說明如下:①函數(shù)類型,用于說明函數(shù)最后的return語句送回給被調(diào)用處的返回值的類型。如果一個函數(shù)沒有返回值,函數(shù)類型可以不寫,實際處理中,這時一般把它的類型定義為void。②函數(shù)名,取名規(guī)則與變量的命名規(guī)則一樣。

③形式參數(shù)表,用于列舉在主調(diào)函數(shù)與被調(diào)用函數(shù)之間進(jìn)行數(shù)據(jù)傳遞的形式參數(shù)。在函數(shù)定義時,形式參數(shù)的類型必須說明,可以在形式參數(shù)表的位置說明,也可以在函數(shù)名后面、函數(shù)體前面進(jìn)行說明。如果函數(shù)沒有參數(shù)傳遞,在定義時,形式參數(shù)可以沒有或用void,但括號不能省略。例23定義一個返回兩個整數(shù)中的最大值的函數(shù)max()。intmax(intx,inty){intz;z=x>y?x:y;return(z);}也可以寫成這樣:intmax(x,y)intx,y;{

intz;

z=x>y?x:y;

return(z);}④interruptm修飾符interruptm是C51中斷函數(shù)的修飾符。在C51程序設(shè)計中,當(dāng)函數(shù)定義時用了interruptm修飾符,系統(tǒng)編譯時把對應(yīng)函數(shù)轉(zhuǎn)化為中斷函數(shù)。

m的取值為0~31,對應(yīng)的中斷情況如下:

0—外部中斷01—定時/計數(shù)器T02—外部中斷13—定時/計數(shù)器T14—串行口中斷其他值預(yù)留。

在編寫MCS-51中斷函數(shù)時應(yīng)注意如下幾點(diǎn):中斷函數(shù)不能進(jìn)行參數(shù)傳遞,如果中斷函數(shù)中包含任何參數(shù)聲明都將導(dǎo)致編譯出錯。中斷函數(shù)不能有返回值,在定義中斷函數(shù)時將其定義為void類型,以明確說明沒有返回值。在任何情況下都不能直接調(diào)用中斷函數(shù),否則會產(chǎn)生編譯錯誤。因為中斷函數(shù)的返回影響8051單片機(jī)的硬件中斷系統(tǒng)。如果在中斷函數(shù)中調(diào)用了其他函數(shù),則被調(diào)用函數(shù)所使用的寄存器必須與中斷函數(shù)相同。否則會產(chǎn)生不正確的結(jié)果。C51編譯器對中斷函數(shù)編譯時會自動在程序開始和結(jié)束處加上相應(yīng)的內(nèi)容,具體如下:在程序開始處對ACC、B、DPH、DPL和PSW入棧,結(jié)束時出棧。中斷函數(shù)未加usingn修飾符的,開始時還要將R0~R1入棧,結(jié)束時出棧。如中斷函數(shù)加usingn修飾符,則在開始將PSW入棧后還要修改PSW中的工作寄存器組選擇位。C51編譯器從絕對地址8m+3處產(chǎn)生一個中斷向量,其中m為中斷號,也即interrupt后面的數(shù)字。該向量包含一個到中斷函數(shù)入口地址的絕對跳轉(zhuǎn)。中斷函數(shù)最好寫在文件的尾部,并且禁止使用extern存儲類型說明。防止其他程序調(diào)用。例24編寫一個用于統(tǒng)計外中斷0的中斷次數(shù)的中斷服務(wù)程序。externintx;voidint0()interrupt0using1{

x++;}⑤usingn修飾符

MCS-51單片機(jī)有四組工作寄存器:0組、1組、2組和3組。每組8個寄存器,分別用R0~R7表示。修飾符usingn用于指定本函數(shù)內(nèi)部使用的工作寄存器組,其中n的取值為0~3,表示寄存器組號。對于usingn修飾符的使用,注意以下幾點(diǎn):加入usingn后,C51在編譯時自動在函數(shù)的開始處和結(jié)束處加入以下指令:{

PUSHPSW;//標(biāo)志寄存器入棧

MOVPSW,#與寄存器組號n相關(guān)的常量;

POPPSW;//標(biāo)志寄存器出棧}usingn修飾符不能用于有返回值的函數(shù),因為C51函數(shù)的返回值是放在寄存器中的,如寄存器組改變了,返回值就會出錯。(2)函數(shù)的調(diào)用函數(shù)調(diào)用的一般形式如下:

函數(shù)名

(實參列表);主調(diào)函數(shù)的實參與形參的個數(shù)應(yīng)該相等,類型一一對應(yīng),實參與形參的位置一致;各個實參之間用逗號隔開;如果調(diào)用的是無參數(shù)函數(shù),則實參也不需要,但是括號不能省略。按照函數(shù)調(diào)用在主調(diào)函數(shù)中出現(xiàn)的位置,函數(shù)調(diào)用方式有以下3種:函數(shù)語句。把被調(diào)用函數(shù)作為主調(diào)用函數(shù)的一個語句。函數(shù)表達(dá)式。函數(shù)被放在一個表達(dá)式中,以一個運(yùn)算對象的方式出現(xiàn)。這時的被調(diào)用函數(shù)要求帶有返回語句,以返回一個明確的數(shù)值參加表達(dá)式的運(yùn)算。函數(shù)參數(shù)。被調(diào)用函數(shù)作為另一個函數(shù)的參數(shù)。(3)自定義函數(shù)的聲明在C51程序設(shè)計中,如果一個自定義函數(shù)的調(diào)用在函數(shù)的定義之后,在使用函數(shù)時可以不對函數(shù)進(jìn)行說明;如果一個函數(shù)的調(diào)用在定義之前,或調(diào)用的函數(shù)不在本文件內(nèi)部,而是在另一個文件中,則在調(diào)用之前需對函數(shù)進(jìn)行聲明,將函數(shù)的有關(guān)信息通知編譯系統(tǒng)。在C51中,函數(shù)聲明的格式如下:

[extern]函數(shù)類型函數(shù)名(形式參數(shù)表);

溫馨提示

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

評論

0/150

提交評論