版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
單片機(jī)C語言程序設(shè)計1.1C語言與MCS-51單片機(jī)1.1.1C語言的特點及程序結(jié)構(gòu)一.C語言的特點1.語言簡潔、緊湊,使用方便、靈活。2.運算符豐富。3.?dāng)?shù)據(jù)結(jié)構(gòu)豐富。具有現(xiàn)代化語言的各種數(shù)據(jù)結(jié)構(gòu)。4.可進(jìn)行結(jié)構(gòu)化程序設(shè)計。5.可以直接對計算機(jī)硬件進(jìn)行操作。6.生成的目標(biāo)代碼質(zhì)量高,程序執(zhí)行效率高。7.可移植性好。二.C語言的程序結(jié)構(gòu)C語言程序采用函數(shù)結(jié)構(gòu),每個C語言程序由一個或多個函數(shù)組成,在這些函數(shù)中至少應(yīng)包含一個主函數(shù)main(),也可以包含一個main()函數(shù)和若干個其它的功能函數(shù)。不管main()函數(shù)放于何處,程序總是從main()函數(shù)開始執(zhí)行,執(zhí)行到main()函數(shù)結(jié)束則結(jié)束。在main()函數(shù)中調(diào)用其它函數(shù),其它函數(shù)也可以相互調(diào)用,但main()函數(shù)只能調(diào)用其它的功能函數(shù),而不能被其它的函數(shù)所調(diào)用。功能函數(shù)可以是C語言編譯器提供的庫函數(shù),也可以是由用戶定義的自定義函數(shù)。在編制C程序時,程序的開始部分一般是預(yù)處理命令、函數(shù)說明和變量定義等。
1.1.2C語言與MCS-51單片機(jī)
用C語言編寫MCS-51單片機(jī)程序與用匯編語言編寫MCS–51單片機(jī)程序不一樣。用匯編語言編寫MCS–51單片機(jī)程序必須要考慮其存儲器結(jié)構(gòu),尤其必須考慮其片內(nèi)數(shù)據(jù)存儲器與特殊功能寄存器的使用以及按實際地址處理端口數(shù)據(jù)。用C語言編寫的MCS–51單片機(jī)應(yīng)用程序,則不用像匯編語言那樣須具體組織、分配存儲器資源和處理端口數(shù)據(jù),但在C語言編程中,對數(shù)據(jù)類型與變量的定義,必須要與單片機(jī)的存儲結(jié)構(gòu)相關(guān)聯(lián),否則編譯器不能正確地映射定位。
C語言編寫單片機(jī)應(yīng)用程序時,需根據(jù)單片機(jī)存儲結(jié)構(gòu)及內(nèi)部資源定義相應(yīng)的數(shù)據(jù)類型和變量,而標(biāo)準(zhǔn)的C語言程序不需要考慮這些問題;C51包含的數(shù)據(jù)類型、變量存儲模式、輸入輸出處理、函數(shù)等方面與標(biāo)準(zhǔn)的C語言有一定的區(qū)別。其它的語法規(guī)則、程序結(jié)構(gòu)及程序設(shè)計方法等與標(biāo)準(zhǔn)的C語言程序設(shè)計相同。
用C語言編寫單片機(jī)應(yīng)用程序與標(biāo)準(zhǔn)的C語言程序也有相應(yīng)的區(qū)別:
現(xiàn)在支持MCS-51系列單片機(jī)的C語言編譯器有很多種,如AmericanAutomation、Avocet、BSO/TASKING、DUNFIELDSHAREWARE、KEIL/Franklin等。各種編譯器的基本情況相同,但具體處理時有一定的區(qū)別,其中KEIL/Franklin以它的代碼緊湊和使用方便等特點優(yōu)于其它編譯器,現(xiàn)在使用特別廣泛。
本章主要以KEIL編譯器介紹MCS-51單片機(jī)C語言程序設(shè)計。1.1.3C51程序結(jié)構(gòu)C51的語法規(guī)定、程序結(jié)構(gòu)及程序設(shè)計方法都與標(biāo)準(zhǔn)的C語言程序設(shè)計相同,但C51程序與標(biāo)準(zhǔn)的C程序在以下幾個方面不一樣:(1)C51中定義的庫函數(shù)和標(biāo)準(zhǔn)C語言定義的庫函數(shù)不同。標(biāo)準(zhǔn)的C語言定義的庫函數(shù)是按通用微型計算機(jī)來定義的,而C51中的庫函數(shù)是按MCS-51單片機(jī)相應(yīng)情況來定義的;(2)C51中的數(shù)據(jù)類型與標(biāo)準(zhǔn)C的數(shù)據(jù)類型也有一定的區(qū)別,在C51中還增加了幾種針對MCS-51單片機(jī)特有的數(shù)據(jù)類型;(3)C51變量的存儲模式與標(biāo)準(zhǔn)C中變量的存儲模式不一樣,C51中變量的存儲模式是與MCS-51單片機(jī)的存儲器緊密相關(guān);(1)C51與標(biāo)準(zhǔn)C的輸入輸出處理不一樣,C51中的輸入輸出是通過MCS-51串行口來完成的,輸入輸出指令執(zhí)行前必須要對串行口進(jìn)行初始化;(5)C51與標(biāo)準(zhǔn)C在函數(shù)使用方面也有一定的區(qū)別,C51中有專門的中斷函數(shù)。1.2C51的數(shù)據(jù)類型C51的數(shù)據(jù)類型分為基本數(shù)據(jù)類型和組合數(shù)據(jù)類型,情況與標(biāo)準(zhǔn)C中的數(shù)據(jù)類型基本相同,但其中char型與short型相同,float型與double型相同,另外,C51中還有專門針對于MCS-51單片機(jī)的特殊功能寄存器型和位類型。一.字符型char有signedchar和unsignedchar之分,默認(rèn)為signedchar。它們的長度均為一個字節(jié),用于存放一個單字節(jié)的數(shù)據(jù)。
對于signedchar,它用于定義帶符號字節(jié)數(shù)據(jù),其字節(jié)的最高位為符號位,“0”表示正數(shù),“1”表示負(fù)數(shù),補(bǔ)碼表示,所能表示的數(shù)值范圍是-128~+127;
對于unsignedchar,它用于定義無符號字節(jié)數(shù)據(jù)或字符,可以存放一個字節(jié)的無符號數(shù),其取值范圍為0~255。unsignedchar可以用來存放無符號數(shù),也可以存放西文字符,一個西文字符占一個字節(jié),在計算機(jī)內(nèi)部用ASCII碼存放。
二.int整型分singedint和unsignedint。默認(rèn)為signedint。它們的長度均為兩個字節(jié),用于存放一個雙字節(jié)數(shù)據(jù)。對于signedint,用于存放兩字節(jié)帶符號數(shù),補(bǔ)碼表示,數(shù)的范疇為-32768~+32767。對于unsignedint,用于存放兩字節(jié)無符號數(shù),數(shù)的范圍為0~65535。三.long長整型分singedlong和unsignedlong。默認(rèn)為signedlong。它們的長度均為四個字節(jié),用于存放一個四字節(jié)數(shù)據(jù)。對于signedlong,用于存放四字節(jié)帶符號數(shù),補(bǔ)碼表示,數(shù)的范疇為-2117183618~+2117183617。對于unsignedlong,用于存放四字節(jié)無符號數(shù),數(shù)的范圍為0~1291967295。四.float浮點型float型數(shù)據(jù)的長度為四個字節(jié),格式符合IEEE-751標(biāo)準(zhǔn)的單精度浮點型數(shù)據(jù),包含指數(shù)和尾數(shù)兩部分,最高位為符號位,“1”表示負(fù)數(shù),“0”表示正數(shù),其次的8位為階碼,最后的23位為尾數(shù)的有效數(shù)位,由于尾數(shù)的整數(shù)部分隱含為“1”,所以尾數(shù)的精度為21位。五.*指針型指針型本身就是一個變量,在這個變量中存放的指向另一個數(shù)據(jù)的地址。這個指針變量要占用一定的內(nèi)存單元,對不同的處理器其長度不一樣,在C51中它的長度一般為1~3個字節(jié)。六.特殊功能寄存器型這是C51擴(kuò)充的數(shù)據(jù)類型,用于訪問MCS-51單片機(jī)中的特殊功能寄存器數(shù)據(jù),它分sfr和sfr16兩種類型。其中:sfr為字節(jié)型特殊功能寄存器類型,占一個內(nèi)存單元,利用它可以訪問MCS-51內(nèi)部的所有特殊功能寄存器;sfr16為雙字節(jié)型特殊功能寄存器類型,占用兩個字節(jié)單元,利用它可以訪問MCS-51內(nèi)部的所有兩個字節(jié)的特殊功能寄存器。
在C51中對特殊功能寄存器的訪問必須先用sfr或sfr16進(jìn)行聲明。七.位類型這也是C51中擴(kuò)充的數(shù)據(jù)類型,用于訪問MCS-51單片機(jī)中的可尋址的位單元。在C51中,支持兩種位類型:bit型和sbit型。它們在內(nèi)存中都只占一個二進(jìn)制位,其值可以是“1”或“0”。其中:用bit定義的位變量在C51編譯器編譯時,在不同的時候位地址是可以變化的,而用sbit定義的位變量必須與MCS-51單片機(jī)的一個可以尋址位單元或可位尋址的字節(jié)單元中的某一位聯(lián)系在一起,在C51編譯器編譯時,其對應(yīng)的位地址是不可變化的?;緮?shù)據(jù)類型長度取值范圍unsignedchar1字節(jié)0~255signedchar1字節(jié)-128~+127unsignedint2字節(jié)0~65535signedint2字節(jié)-32768~+32767unsignedlong1字節(jié)0~1291967295signedlong1字節(jié)-2117183618~+2117183617float1字節(jié)1.175191E-38~3.102823E+38bit1位0或1sbit1位0或1sfr1字節(jié)0~255sfr162字節(jié)0~65535KEILC51編譯器能夠識別的基本數(shù)據(jù)類型:二.變量名變量名是C51區(qū)分不同變量,為不同變量取的名稱。在C51中規(guī)定變量名可以由字母、數(shù)字和下劃線三種字符組成,且第一個字母必須為字母或下劃線。變量名有兩種:普通變量名和指針變量名。它們的區(qū)別是指針變量名前面要帶“*”號。三.存儲種類存儲種類是指變量在程序執(zhí)行過程中的作用范圍。C51變量的存儲種類有四種,分別是自動(auto)、外部(extern)、靜態(tài)(static)和寄存器(register)。1.a(chǎn)uto:
使用auto定義的變量稱為自動變量,其作用范圍在定義它的函數(shù)體或復(fù)合語句內(nèi)部,當(dāng)定義它的函數(shù)體或復(fù)合語句執(zhí)行時,C51才為該變量分配內(nèi)存空間,結(jié)束時占用的內(nèi)存空間釋放。自動變量一般分配在內(nèi)存的堆棧空間中。定義變量時,如果省略存儲種類,則該變量默認(rèn)為自動(auto)變量。2.extern:
使用extern定義的變量稱為外部變量。在一個函數(shù)體內(nèi),要使用一個已在該函數(shù)體外或別的程序中定義過的外部變量時,該變量在該函數(shù)體內(nèi)要用extern說明。外部變量被定義后分配固定的內(nèi)存空間,在程序整個執(zhí)行時間內(nèi)都有效,直到程序結(jié)束才釋放。3.static:
使用static定義的變量稱為靜態(tài)變量。它又分為內(nèi)部靜態(tài)變量和外部靜態(tài)變量。在函數(shù)體內(nèi)部定義的靜態(tài)變量為內(nèi)部靜態(tài)變量,它在對應(yīng)的函數(shù)體內(nèi)有效,一直存在,但在函數(shù)體外不可見,這樣不僅使變量在定義它的函數(shù)體外被保護(hù),還可以實現(xiàn)當(dāng)離開函數(shù)時值不被改變。外部靜態(tài)變量上在函數(shù)外部定義的靜態(tài)變量。它在程序中一直存在,但在定義的范圍之外是不可見的。如在多文件或多模塊處理中,外部靜態(tài)變量只在文件內(nèi)部或模塊內(nèi)部有效。1.register:
使用register定義的變量稱為寄存器變量。它定義的變量存放在CPU內(nèi)部的寄存器中,處理速度快,但數(shù)目少。C51編譯器編譯時能自動識別程序中使用頻率最高的變量,并自動將其作為寄存器變量,用戶可以無需專門聲明。在C51中,為了用戶處理方便,C51編譯器把MCS-51單片機(jī)的常用的特殊功能寄存器和特殊位進(jìn)行了定義,放在一個“reg51.h”或“reg52.h”的頭文件中,當(dāng)用戶要使用時,只須要在使用之前用一條預(yù)處理命令#include<reg52.h>把這個頭文件包含到程序中,然后就可使用殊功能寄存器名和特殊位名稱。1.5表達(dá)式語句及復(fù)合語句1.5.1表達(dá)式語句在表達(dá)式的后邊加一個分號“;”就構(gòu)成了表達(dá)式語句,如: a=++b*9; x=8;y=7; ++k;可以一行放一個表達(dá)式形成表達(dá)式語句,也可以一行放多個表達(dá)式形成表達(dá)式語句,這時每個表達(dá)式后面都必須帶“;”號,另外,還可以僅由—個分號“;”占一行形成一個表達(dá)式語句,這種語句稱為空語句??照Z句在程序設(shè)計中通常用于兩種情況:(1)在程序中為有關(guān)語句提供標(biāo)號,用以標(biāo)記程序執(zhí)行的位置。例如采用下面的語句可以構(gòu)成一個循環(huán)。repeat:;;gotorepeat;(2)在用while語句構(gòu)成的循環(huán)語句后面加一個分號,形成一個不執(zhí)行其它操作的空循環(huán)體。這種結(jié)構(gòu)通常用于對某位進(jìn)行判斷,當(dāng)不滿足條件則等待,滿足條件則執(zhí)行?!纠肯旅孢@段子程序用于讀取8051單片機(jī)的串行口的數(shù)據(jù),當(dāng)沒有接收到則等待,當(dāng)接收到,接收數(shù)據(jù)后返回,返回值為接收的數(shù)據(jù)。#include<reg51.h>chargetchar(){charc;while(!RI);//當(dāng)接收中斷標(biāo)志位RI為0則等待,當(dāng)接收中斷標(biāo)志位為1則;等待結(jié)束c=SBUF;RI=0;return(c);}1.7.2if語句if語句是C51中的一個基本條件選擇語句,它通常有三種格式:(1)if(表達(dá)式){語句;}(2)if(表達(dá)式){語句1;}else{語句2;}(3)if(表達(dá)式1){語句1;}elseif(表達(dá)式2)(語句2;)elseif(表達(dá)式3)(語句3;)……elseif(表達(dá)式n-1)(語句n-1;)else{語句n}1.7.3switch/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;}說明如下:(1)switch后面括號內(nèi)的表達(dá)式,可以是整型或字符型表達(dá)式。(2)當(dāng)該表達(dá)式的值與某一“case”后面的常量表達(dá)式的值相等時,就執(zhí)行該“case”后面的語句,然后遇到break語句退出switch語句。若表達(dá)式的值與所有case后的常量表達(dá)式的值都不相同,則執(zhí)行default后面的語句,然后退出switch結(jié)構(gòu)。(3)每一個case常量表達(dá)式的值必須不同否則會出現(xiàn)自相矛盾的現(xiàn)象。(1)case語句和default語句的出現(xiàn)次序?qū)?zhí)行過程沒有影響。(5)每個case語句后面可以有“break”,也可以沒有。有break語句,執(zhí)行到break則退出switch結(jié)構(gòu),若沒有,則會順次執(zhí)行后面的語句,直到遇到break或結(jié)束。(6)每一個case語句后面可以帶一個語句,也可以帶多個語句,還可以不帶。語句可以用花括號括起,也可以不括。(7)多個case可以共用一組執(zhí)行語句。【例11】switch/case語句的用法。對學(xué)生成績劃分為A~D,對應(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)}1.7.1while語句while語句在C51中用于實現(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)之外的下一條語句。它的特點是:先判斷條件,后執(zhí)行循環(huán)體。在循環(huán)體中對條件進(jìn)行改變,然后再判斷條件,如條件成立,則再執(zhí)行循環(huán)體,如條件不成立,則退出循環(huán)。如條件第一次就不成立,則循環(huán)體一次也不執(zhí)行。#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidmain(void)//主函數(shù){inti,s=0;//定義整型變量x和yi=1;SCON=0x52;//串口初始化TMOD=0x20;TH1=0XF3;TR1=1;while(i<=100)//累加1~100之和在s中{s=s+i;i++;}printf(“1+2+3……+100=%d\n”,s);while(1);}【例15】下面程序是通過while語句實現(xiàn)計算并輸出1~100的累加和。程序執(zhí)行的結(jié)果:1+2+3……+100=50501.7.5dowhile語句dowhile語句在C51中用于實現(xiàn)直到型循環(huán)結(jié)構(gòu),它的格式如下:do{語句;}/*循環(huán)體*/while(表達(dá)式);它的特點是:先執(zhí)行循環(huán)體中的語句,后判斷表達(dá)式。如表達(dá)式成立(真),則再執(zhí)行循環(huán)體,然后又判斷,直到有表達(dá)式不成立(假)時,退出循環(huán),執(zhí)行dowhile結(jié)構(gòu)的下一條語句。dowhile語句在執(zhí)行時,循環(huán)體內(nèi)的語句至少會被執(zhí)行一次。#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidmain(void)//主函數(shù){inti,s=0;//定義整型變量x和yi=1;SCON=0x52;//串口初始化TMOD=0x20;TH1=0XF3;TR1=1;do//累加1~100之和在s中{s=s+i;i++;}while(i<=100);printf(“1+2+3……+100=%d\n”,s);while(1);}【例16】通過dowhile語句實現(xiàn)計算并輸出1~100的累加和。for(表達(dá)式1;表達(dá)式2;表達(dá)式3){語句;}/*循環(huán)體*/for語句后面帶三個表達(dá)式,它的執(zhí)行過程如下:(1)先求解表達(dá)式1的值。(2)求解表達(dá)式2的值,如表達(dá)式2的值為真,則執(zhí)行循環(huán)休中的語句,然后執(zhí)行下一步(3)的操作,如表達(dá)式2的值為假,則結(jié)束for循環(huán),轉(zhuǎn)到最后一步。(3)若表達(dá)式2的值為真,則執(zhí)行完循環(huán)體中的語句后,求解表達(dá)式3,然后轉(zhuǎn)到第四步。(1)轉(zhuǎn)到(2)繼續(xù)執(zhí)行。(5)退出for循環(huán),執(zhí)行下面的一條語句。在for循環(huán)中,一般表達(dá)式1為初值表達(dá)式,用于給循環(huán)變量賦初值;表達(dá)式2為條件表達(dá)式,對循環(huán)變量進(jìn)行判斷;表達(dá)式3為循環(huán)變量更新表達(dá)式,用于對循環(huán)變量的值進(jìn)行更新,使循環(huán)變量能不滿足條件而退出循環(huán)。1.7.6for語句【例17】用for語句實現(xiàn)計算并輸出1~100的累加和。#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidmain(void)//主函數(shù){inti,s=0;//定義整型變量x和ySCON=0x52;//串口初始化TMOD=0x20;TH1=0XF3;TR1=1;for(i=1;i<=100;i++)s=s+i;//累加1~100之和在s中printf(“1+2+3……+100=%d\n”,s);while(1);}程序執(zhí)行的結(jié)果:1+2+3……+100=5050在一個循環(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中,允許三種循環(huán)結(jié)構(gòu)相互嵌套。【例18】用嵌套結(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)系。1.7.7循環(huán)的嵌套5.interruptm修飾符interruptm是C51函數(shù)中非常重要的一個修飾符,這是因為中斷函數(shù)必須通過它進(jìn)行修飾。在C51程序設(shè)計中,當(dāng)函數(shù)定義時用了interruptm修飾符,系統(tǒng)編譯時把對應(yīng)函數(shù)轉(zhuǎn)化為中斷函數(shù),自動加上程序頭段和尾段,并按MCS-51系統(tǒng)中斷的處理方式自動把它安排在程序存儲器中的相應(yīng)位置。
在該修飾符中,m的取值為0~31,對應(yīng)的中斷情況如下:0——外部中斷01——定時/計數(shù)器T02——外部中斷13——定時/計數(shù)器T11——串行口中斷5——定時/計數(shù)器T2其它值預(yù)留。編寫MCS-51中斷函數(shù)注意如下:(1)中斷函數(shù)不能進(jìn)行參數(shù)傳遞,如果中斷函數(shù)中包含任何參數(shù)聲明都將導(dǎo)致編譯出錯。(2)中斷函數(shù)沒有返回值,如果企圖定義一個返回值將得不到正確的結(jié)果,建議在定義中斷函數(shù)時將其定義為void類型,以明確說明沒有返回值。(3)在任何情況下都不能直接調(diào)用中斷函數(shù),否則會產(chǎn)生編譯錯誤。因為中斷函數(shù)的返回是由8051單片機(jī)的RETI指令完成的,RETI指令影響8051單片機(jī)的硬件中斷系統(tǒng)。如果在沒有實際中斷情況下直接調(diào)用中斷函數(shù),RETI指令的操作結(jié)果會產(chǎn)生一個致命的錯誤。(1)如果在中斷函數(shù)中調(diào)用了其它函數(shù),則被調(diào)用函數(shù)所使用的寄存器必須與中斷函數(shù)相同。否則會產(chǎn)生不正確的結(jié)果。(7)中斷函數(shù)最好寫在文件的尾部,并且禁止使用extern存儲類型說明。防止其它程序調(diào)用。
【例22】編寫一個用于統(tǒng)計外中斷0的中斷次數(shù)的中斷服務(wù)程序externintx;voidint0()interrupt0using1{x++;}
6.usingn修飾符修飾符usingn用于指定本函數(shù)內(nèi)部使用的工作寄存器組,其中n的取值為0~3,表示寄存器組號。對于usingn修飾符的使用,注意以下幾點:(1)加入usingn后,C51在編譯時自動的在函數(shù)的開始處和結(jié)束處加入以下指令。{PUSHPSW;標(biāo)志寄存器入棧MOVPSW,#與寄存器組號相關(guān)的常量……POPPSW;標(biāo)志寄存器出棧}(2)usingn修飾符不能用于有返回值的函數(shù),因為C51函數(shù)的返回值是放在寄存器中的。如寄存器組改變了,返回值就會出錯。1.8.2函數(shù)的調(diào)用與聲明一.函數(shù)的調(diào)用函數(shù)調(diào)用的一般形式如下:函數(shù)名(實參列表);對于有參數(shù)的函數(shù)調(diào)用,若實參列表包含多個實參,則各個實參之間用逗號隔開。按照函數(shù)調(diào)用在主調(diào)函數(shù)中出現(xiàn)的位置,函數(shù)調(diào)用方式有以下三種:(1)函數(shù)語句。把被調(diào)用函數(shù)作為主調(diào)用函數(shù)的一個語句。(2)函數(shù)表達(dá)式。函數(shù)被放在一個表達(dá)式中,以一個運算對象的方式出現(xiàn)。這時的被調(diào)用函數(shù)要求帶有返回語句,以返回一個明確的數(shù)值參加表達(dá)式的運算。(3)函數(shù)參數(shù)。被調(diào)用函數(shù)作為另一個函數(shù)的參數(shù)。二.自定義函數(shù)的聲明在C51中,函數(shù)原型一般形式如下:[extern]函數(shù)類型函數(shù)名(形式參數(shù)表);函數(shù)的聲明是把函數(shù)的名字、函數(shù)類型以及形參的類型、個數(shù)和順序通知編譯系統(tǒng),以便調(diào)用函數(shù)時系統(tǒng)進(jìn)行對照檢查。函數(shù)的聲明后面要加分號。如果聲明的函數(shù)在文件內(nèi)部,則聲明時不用extern,如果聲明的函數(shù)不在文件內(nèi)部,而在另一個文件中,聲明時須帶extern,指明使用的函數(shù)在另一個文件中。1.8.3函數(shù)的嵌套與遞歸一.函數(shù)的嵌套在一個函數(shù)的調(diào)用過程中調(diào)用另一個函數(shù)。C51編譯器通常依靠堆棧來進(jìn)行參數(shù)傳遞,堆棧設(shè)在片內(nèi)RAM中,而片內(nèi)RAM的空間有限,因而嵌套的深度比較有限,一般在幾層以內(nèi)。如果層數(shù)過多,就會導(dǎo)致堆??臻g不夠而出錯。
【例25】函數(shù)的嵌套調(diào)用#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();intmax(inta,intb){intz;z=a>=b?a:b;return(z);}intadd(intc,intd,inte,intf){intresult;result=max(c,d)+max(e,f);//調(diào)用函數(shù)maxreturn(result);}main(){intfinal;serial_initial();final=add(7,5,2,8);printf(“%d”,final);while(1);}二.函數(shù)的遞歸遞歸調(diào)用是嵌套調(diào)用的一個特殊情況。如果在調(diào)用一個函數(shù)過程中又出現(xiàn)了直接或間接調(diào)用該函數(shù)本身,則稱為函數(shù)的遞歸調(diào)用?!纠?-26】遞歸求數(shù)的階乘n!。在數(shù)學(xué)計算中,一個數(shù)n的階乘等于該數(shù)本身乘以數(shù)n-1的階乘,即n!=n(n-1)!,用n-1的階乘來表示n的階乘就是一種遞歸表示方法。在程序設(shè)計中通過函數(shù)遞歸調(diào)用來實現(xiàn)。程序如下:在函數(shù)的遞歸調(diào)用中要避免出現(xiàn)無終止的自身調(diào)用,應(yīng)通過條件控制結(jié)束遞歸調(diào)用,使得遞歸的次數(shù)有限。下面是一個利用遞歸調(diào)用求n!的例子。#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();intfac(intn)reentrant{intresult;if(n==0) result=1;else result=n*fac(n-1);return(result);}main(){intfac_result;serial_initial();fac_result=fac(11);printf(“%d\n”,fac_result);}1.9C51構(gòu)造數(shù)據(jù)類型1.9.1數(shù)組一.一維數(shù)組一維數(shù)組只有一個下標(biāo),定義的形式如下:數(shù)據(jù)類型說明符數(shù)組名[常量表達(dá)式][={初值,初值……}]各部分說明如下:(1)“數(shù)據(jù)類型說明符”說明了數(shù)組中各個元素存儲的數(shù)據(jù)的類型。(2)“數(shù)組名”是整個數(shù)組的標(biāo)識符,它的取名方法與變量的取名方法相同。(3)“常量表達(dá)式”,常量表達(dá)式要求取值要為整型常量,必須用方括號“[]”括起來。用于說明該數(shù)組的長度,即該數(shù)組元素的個數(shù)。(1)“初值部分”用于給數(shù)組元素賦初值,這部分在數(shù)組定義時屬于可選項。對數(shù)組元素賦值,可以在定義時賦值,也可以定義之后賦值。在定義時賦值,后面須帶等號,初值須用花括號括起來,括號內(nèi)的初值兩兩之間用逗號間隔,可以對數(shù)組的全部元素賦值,也可以只對部分元素賦值。初值為0的元素可以只用逗號占位而不寫初值0。例如:下面是定義數(shù)組的兩個例子。unsignedcharx[5];unsignedinty[3]={1,2,3};第一句定義了一個無符號字符數(shù)組,數(shù)組名為x,數(shù)組中的元素個數(shù)為5。第二句定義了一個無符號整型數(shù)組,數(shù)組名為y,數(shù)組中元素個數(shù)為3,定義的同時給數(shù)組中的三個元素賦初值,賦初值分別為1、2、3。需要注意的是,C51語言中數(shù)組的下標(biāo)是從0開始的,因此上面第一句定義的5個元素分別是:x[0]、x[1]、x[2]、x[3]、x[1]。第二句定義的3個元素分別是:y[0]、y[1]、y[2]。賦值情況為:y[0]=1;y[1]=2;y[2]=3。C51規(guī)定在引用數(shù)組時,只能逐個引用數(shù)組中的各個元素,而不能一次引用整個數(shù)組。但如果是字符數(shù)組則可以一次引用整個數(shù)組?!纠?-27】用數(shù)組計算并輸出Fibonacci數(shù)列的前20項。Fibonacci數(shù)列在數(shù)學(xué)和計算機(jī)算法中十分有用。Fibonacci數(shù)列是這樣的一組數(shù):第一個數(shù)字為0,第二個數(shù)字為1,之后每一個數(shù)字都是前兩個數(shù)字之和。設(shè)計時通過數(shù)組存放Fibonacci數(shù)列,從第三項開始可通過累加的方法計算得到。程序如下:#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();main(){intfib[20],i;fib[0]=0;fib[1]=1;serial_initial();for(i=2;i<20;i++)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é)果:0 1 1 2 35 8 13 21 3155 89 111 233 377610 987 1597 2581 1118二.字符數(shù)組用來存放字符數(shù)據(jù)的數(shù)組稱為字符數(shù)組,它是C語言中常用的一種數(shù)組。字符數(shù)組中的每一個元素都用來存放一個字符,也可用字符數(shù)組來存放字符串。字符數(shù)組的定義下一般數(shù)組相同,只是在定義時把數(shù)據(jù)類型定義為char型。例如:charstring1[10];charstring2[20];上面定義了兩個字符數(shù)組,分別定義了10個元素和20個元素。在C51語言中,字符數(shù)組用于存放一組字符或字符串,字符串以“\0”作為結(jié)束符,只存放一般字符的字符數(shù)組的賦值與使用和一般的數(shù)組完全相同。對于存放字符串的字符數(shù)組。既可以對字符數(shù)組的元素逐個進(jìn)行訪問,也可以對整個數(shù)組按字符串的方式進(jìn)行處理?!纠?-28】對字符數(shù)組進(jìn)行輸入和輸出。#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();main(){charstring[20];serial_initial();printf(“pleasetypeanycharacter:”);scanf(“%s”,string);printf(“%s\n”,string);while(1);}1.9.2指針指針是C語言中的一個重要概念。指針類型數(shù)據(jù)在C語言程序中使用十分普遍,正確地使用指針類型數(shù)據(jù),可以有效地表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu);可以動態(tài)地分配存儲器,直接處理內(nèi)存地址。一.指針的概念了解指針的基本概念,先要了解數(shù)據(jù)在內(nèi)存中的存儲和讀取方法。在匯編語言中,對內(nèi)存單元數(shù)據(jù)的訪問是通過指明內(nèi)存單元的地址。訪問時有兩種方式:直接尋址方式和間接尋址方式。直接尋址是通過在指令中直接給出數(shù)據(jù)所在單元的地址而訪問該單元的數(shù)據(jù)。例如:MOVA,20H。在指令中直接給出所訪問的內(nèi)存單元地址20H,訪問的是地址為20H的單元的數(shù)據(jù),該指令把地址為20H的片內(nèi)RAM單元的內(nèi)容送累加器A;間接尋址是指所操作的數(shù)據(jù)所在的內(nèi)存單元地址不是通過指令中直接提供,該地址是存放在寄存器中或其它的內(nèi)存單元中,指令中指明存放地址的寄存器或內(nèi)存單元來訪問相應(yīng)的數(shù)據(jù)。在C語言中,可以通過地址方式來訪問內(nèi)存單元的數(shù)據(jù),但C語言作為一種高級程序設(shè)計語言,數(shù)據(jù)通常是以變量的形式進(jìn)行存放和訪問的。對于變量,在一個程序中定義了一個變量,編譯器在編譯時就在內(nèi)存中給這個變量分配一定的字節(jié)單元進(jìn)行存儲。如對整型變量(int)分配2個字節(jié)單元,對于浮點型變量(float)分配1個字節(jié)單元,對于字符型變量分配1個字節(jié)單元等。變量在使用時分清兩個概念:變量名和變量的值。前一個是數(shù)據(jù)的標(biāo)識,后一個是數(shù)據(jù)的內(nèi)容。變量名相當(dāng)于內(nèi)存單元的地址,變量的值相當(dāng)于內(nèi)存單元的內(nèi)容。對于內(nèi)存單元的數(shù)據(jù)訪問方式有兩種,對于變量也有兩種訪問方式:直接訪問方式和間接訪問方式。直接訪問方式。對于變量的訪問,我們大多數(shù)時候是直接給出變量名。例如:printf(“%d”,a),直接給出變量a的變量名來輸出變量a的內(nèi)容。在執(zhí)行時,根據(jù)變量名得到內(nèi)存單元的地址,然后從內(nèi)存單元中取出數(shù)據(jù)按指定的格式輸出。這就是直接訪問方式。
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年高職(工業(yè)分析技術(shù))食品成分檢驗綜合測試試題及答案
- 2025年大學(xué)通識選修(藝術(shù)鑒賞)試題及答案
- 2025年高職建筑工程技術(shù)(模板支護(hù)工藝)試題及答案
- 2025年高職航空裝備類(航空裝備基礎(chǔ))試題及答案
- 2025年高職水路運輸與海事管理(海事管理實務(wù))試題及答案
- 2025 小學(xué)四年級思想品德下冊公共場合優(yōu)化禮儀學(xué)習(xí)效果反饋課件
- 養(yǎng)老院老人心理健康制度
- 養(yǎng)老院康復(fù)設(shè)備管理制度
- 2026年學(xué)生檔案管理崗位面試指南含答案
- 2026年鄉(xiāng)村醫(yī)生信息化小測含答案
- 減速機(jī)知識培訓(xùn)資料課件
- 冷庫消防安全培訓(xùn)課件
- 普陀區(qū)一模高三數(shù)學(xué)試卷
- 光熱儲能電站發(fā)電項目項目管理各階段主要任務(wù)
- 2026年中考語文復(fù)習(xí):非連續(xù)性文本閱讀 中考真題練習(xí)題匯編(含答案解析)
- 醫(yī)療工作者榜樣學(xué)習(xí)心得體會
- 部隊安全駕駛課件
- 裝修裝飾工程成品保護(hù)方案
- 鄉(xiāng)土地理教學(xué)
- 房產(chǎn)代持委托協(xié)議書
評論
0/150
提交評論