5 第五章 C51函數(shù) 單片機(jī)_第1頁
5 第五章 C51函數(shù) 單片機(jī)_第2頁
5 第五章 C51函數(shù) 單片機(jī)_第3頁
5 第五章 C51函數(shù) 單片機(jī)_第4頁
5 第五章 C51函數(shù) 單片機(jī)_第5頁
已閱讀5頁,還剩19頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第五章

C51函數(shù)

5.1函數(shù)5.1.1函數(shù)的定義函數(shù)定義的一般格式如下:函數(shù)類型函數(shù)名(形式參數(shù)表)[reentrant][interruptm][usingn]形式參數(shù)說明{

局部變量定義 函數(shù)體}前面部件稱為函數(shù)的首部,后面稱為函數(shù)的尾部,格式說明:1.函數(shù)類型函數(shù)類型說明了函數(shù)返回值的類型。2.函數(shù)名函數(shù)名是用戶為自定義函數(shù)取的名字以便調(diào)用函數(shù)時使用。3.形式參數(shù)表形式參數(shù)表用于列錄在主調(diào)函數(shù)與被調(diào)用函數(shù)之間進(jìn)行數(shù)據(jù)傳遞的形式參數(shù)?!纠?-1】定義一個返回兩個整數(shù)的最大值的函數(shù)max()。int

max(int

x,inty){intz;z=x>y?x:y;return(z);}也可以用成這樣:int

max(x,y)int

x,y;{intz;z=x>y?x:y;return(z);}4.reentrant修飾符

這個修飾符用于把函數(shù)定義為可重入函數(shù)。所謂可重入函數(shù)就是允許被遞歸調(diào)用的函數(shù)。函數(shù)的遞歸調(diào)用是指當(dāng)一個函數(shù)正被調(diào)用尚未返回時,又直接或間接調(diào)用函數(shù)本身。一般的函數(shù)不能做到這樣,只有重入函數(shù)才允許遞歸調(diào)用。

關(guān)于重入函數(shù),注意以下幾點:(1)用reentrant修飾的重入函數(shù)被調(diào)用時,實參表內(nèi)不允許使用bit類型的參數(shù)。函數(shù)體內(nèi)也不允許存在任何關(guān)于位變量的操作,更不能返回bit類型的值。(2)編譯時,系統(tǒng)為重入函數(shù)在內(nèi)部或外部存儲器中建立一個模擬堆棧區(qū),稱為重入棧。重入函數(shù)的局部變量及參數(shù)被放在重入棧中,使重入函數(shù)可以實現(xiàn)遞歸調(diào)用。(3)在參數(shù)的傳遞上,實際參數(shù)可以傳遞給間接調(diào)用的重入函數(shù)。無重入屬性的間接調(diào)用函數(shù)不能包含調(diào)用參數(shù),但是可以使用定義的全局變量來進(jìn)行參數(shù)傳遞。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ù)器T14——串行口中斷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)生一個致命的錯誤。(4)如果在中斷函數(shù)中調(diào)用了其它函數(shù),則被調(diào)用函數(shù)所使用的寄存器必須與中斷函數(shù)相同。否則會產(chǎn)生不正確的結(jié)果。(5)C51編譯器對中斷函數(shù)編譯時會自動在程序開始和結(jié)束處加上相應(yīng)的內(nèi)容,具體如下:在程序開始處對ACC、B、DPH、DPL和PSW入棧,結(jié)束時出棧。中斷函數(shù)未加usingn修飾符的,開始時還要將R0~R1入棧,結(jié)束時出棧。如中斷函數(shù)加usingn修飾符,則在開始將PSW入棧后還要修改PSW中的工作寄存器組選擇位。(6)C51編譯器從絕對地址8m+3處產(chǎn)生一個中斷向量,其中m為中斷號,也即interrupt后面的數(shù)字。該向量包含一個到中斷函數(shù)入口地址的絕對跳轉(zhuǎn)。(7)中斷函數(shù)最好寫在文件的尾部,并且禁止使用extern存儲類型說明。防止其它程序調(diào)用。

【例5-2】編寫一個用于統(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ù)的返回值是放在寄存器中的。如寄存器組改變了,返回值就會出錯。5.1.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á)式中,以一個運(yùn)算對象的方式出現(xiàn)。這時的被調(diào)用函數(shù)要求帶有返回語句,以返回一個明確的數(shù)值參加表達(dá)式的運(yùn)算。(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ù)在另一個文件中。【例5-3】函數(shù)的使用#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫int

max(int

x,inty);//對max函數(shù)進(jìn)行聲明voidmain(void)//主函數(shù){int

a,b;SCON=0x52;//串口初始化TMOD=0x20;TH1=0xF3;TR1=1;scanf(“pleaseinputa,b:%d,%d”,&a,&b);printf(“\n”);printf(“max

is:%d\n”,max(a,b));while(1);}int

max(int

x,inty){intz;z=(x>=y?x:y);return(z);}【例5-4】外部函數(shù)的使用程序serial_initial.c#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫voidserial_initial(void)//主函數(shù){SCON=0x52;//串口初始化TMOD=0x20;TH1=0xF3;TR1=1;}程序main.c#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();voidmain(void){int

a,b;serial_initial();scanf(“pleaseinputa,b:%d,%d”,&a,&b);printf(“\n”);printf(“max

is:%d\n”,a>=b?a:b);while(1);}5.1.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不夠而出錯。

【例5-5】函數(shù)的嵌套調(diào)用#include<reg52.h>//包含特殊功能寄存器庫#include<stdio.h>//包含I/O函數(shù)庫externserial_initial();int

max(int

a,intb){intz;z=a>=b?a:b;return(z);}int

add(int

c,int

d,int

e,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)用?!纠?-6】遞歸求數(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();int

fac(intn)reentrant{intresult;if(n==0) result=1;else result=n*fac(n-1);return(result);}main(){int

fac_result;serial_initial();fac_result=fac(11);printf(“%d\n”,fac_result);}Anyquestion?

Thanks!

上機(jī)練習(xí):1、各自建立工程,輸入例5-2,5-3,5-4,5-5,5-6源程序,鏈接,編譯,調(diào)試,用keil串行口窗口觀察輸出結(jié)果。2、8051單片機(jī)的P1口接有8只發(fā)光二極管,P3.2-P3.5接有4個按鍵,如圖1所示,要求:按下K1鍵LED燈全亮,按下K2鍵LED燈全滅。上機(jī)練習(xí):8051P1.0P1.1圖1P1.2P1.3P1.4P1.5P1.6P1.7P3.2P3.4P3.3P3.5+5VK1K2K3K4程序如下:#include<reg51.h>程序?qū)崿F(xiàn):建立工程key1,輸入源程序。voidmain()在Debug選項下左下角Parameter{unsignedcharkey;文本框里面加入“-dledkey”。編譯

for(;;)鏈接、調(diào)試,選擇Peripheral下

{P3|=0x3c;//將P3.2-P3.5“鍵盤、LED實驗仿真板”仿真觀察。置高電平

key=P3|0xfb;//判斷K1是否按下

if(key!=0xff)P1=0;key=P3|0xf7;//判斷K2是否按下

if(key!=0xff)P1=0xff;}}上機(jī)練習(xí):3、如圖1所示,要求:按下K1鍵P1.7和P1.3所接LED燈亮;按下K2鍵P1.6和P1.2所接LED燈亮;按下K3鍵P1.5和P1.1所接LED燈亮;按下K4鍵P1.4和P1.0所接LED燈亮。#include<reg51.h>程序?qū)崿F(xiàn):建立工程key2,輸入源程序。voidmain()在Debug選項下左下角Parameter{unsignedcharkey;文本框里面加入“-dledkey”。編譯

for(;;)鏈接、調(diào)試,選擇Peripheral下

{P3|=0x3c;“鍵盤、LED實驗仿真板”仿真觀察。

key=P3;

switch(key){case0xfb:P1=0xee;break;case0xf7:P1=0xdd;break;case0xef:P1=0xbb;break;case0xdf:P1=0x77;break;}}}上機(jī)練習(xí):上機(jī)練習(xí):4、如圖1所示,要求:按下K1鍵LED燈依次循環(huán)點亮;松開K1燈熄滅。#include<reg51.h>#include<intrins.h> //該文件包含有_crol_(…)函數(shù)的說明voidmDelay(unsignedint

DelayTime){ unsignedintj=0;

for(;DelayTime>0;DelayTime--) {for(j=0;j<125;j++){;} }}voidmain(){ unsignedcharOutData=0xfe; while(1) { P3|=0x3c; while((P3|0xfb)!=0xff) { P1=OutData;

OutData=_crol_(OutData,1);//循環(huán)左移

mDelay(1000);/*延時1000毫秒*/}P1=0xff; }}

程序?qū)崿F(xiàn):建立工程loop1,輸入源程序。在Debug選項下左下角Parameter文本框里面加入“-dledkey”。編譯、鏈接、調(diào)試,選擇Peripheral下“鍵盤、LED實驗仿真板”仿真觀察。5、如圖1所示,要求:開機(jī)后全部LED燈不亮;按下K1鍵LED燈從LED1到LED8依次循環(huán)點亮,然后全部熄滅;再按K1鍵,重復(fù)上述過程。如果中間按下K2鍵,則所有LED燈立即全部熄滅;并返回起始狀態(tài)。(提示:break語句)

溫馨提示

  • 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

提交評論