函 數
1. 函式的定義
函式定義的一般格式如下:
函式型別 函式名(形式參數列) [reentrant][interrupt m][using n]
形式引數說明
前面部件稱為函式的首部,後面稱為函式的尾部,格式說明:
1).函式型別
函式型別說明了函式返回值的型別。
2).函式名
函式名是使用者為自定義函式取的名字以便呼叫函式時使用。
3).形式參數列
形式參數列用於列錄在主調函式與被呼叫函式之間進行資料傳遞的形式引數。
【例】定義乙個返回兩個整數的最大值的函式max()。
int max(int x,int y)
也可以用成這樣:
int max(x,y)
int x,y;
4).reentrant修飾符
這個修飾符用於把函式定義為可重入函式。所謂可重入函式就是允許被遞迴呼叫的函式。函式的遞迴呼叫是指當乙個函式正被呼叫尚未返回時,又直接或間接呼叫函式本身。一般的函式不能做到這樣,只有重入函式才允許遞迴呼叫。
關於重入函式,注意以下幾點:
(1)用reentrant修飾的重入函式被呼叫時,實參表內不允許使用bit型別的引數。函式體內也不允許存在任何關於位變數的操作,更不能返回bit型別的值。
(2)編譯時,系統為重入函式在內部或外部儲存器中建立乙個模擬堆疊區,稱為重入棧。重入函式的區域性變數及引數被放在重入棧中,使重入函式可以實現遞迴呼叫。
(3)在引數的傳遞上,實際引數可以傳遞給間接呼叫的重入函式。無重入屬性的間接呼叫函式不能包含呼叫引數,但是可以使用定義的全域性變數來進行引數傳遞。
5).interrupt m修飾符
interrupt m是c51函式中非常重要的乙個修飾符,這是因為中斷函式必須通過它進行修飾。在c51程式設計中,當函式定義時用了interrupt m修飾符,系統編譯時把對應函式轉化為中斷函式,自動加上程式頭段和尾段,並按51系統中斷的處理方式自動把它安排在程式儲存器中的相應位置。
在該修飾符中,m的取值為0~31,對應的中斷情況如下:
0——外部中斷0
1——定時/計數器t0
2——外部中斷1
3——定時/計數器t1
4——序列口中斷
5——定時/計數器t2
其它值預留。
編寫51中斷函式注意如下:
(1)中斷函式不能進行引數傳遞,如果中斷函式中包含任何引數宣告都將導致編譯出錯。
(2)中斷函式沒有返回值,如果企圖定義乙個返回值將得不到正確的結果,建議在定義中斷函式時將其定義為void型別,以明確說明沒有返回值。
(3)在任何情況下都不能直接呼叫中斷函式,否則會產生編譯錯誤。因為中斷函式的返回是由8051微控制器的reti指令完成的,reti指令影響8051微控制器的硬體中斷系統。如果在沒有實際中斷情況下直接呼叫中斷函式,reti指令的操作結果會產生乙個致命的錯誤。
(4)如果在中斷函式中呼叫了其它函式,則被呼叫函式所使用的暫存器必須與中斷函式相同。否則會產生不正確的結果。
(5)c51編譯器對中斷函式編譯時會自動在程式開始和結束處加上相應的內容,具體如下:在程式開始處對acc、b、dph、dpl和psw入棧,結束時出棧。中斷函式未加using n修飾符的,開始時還要將r0~r1入棧,結束時出棧。如中斷函式加using n修飾符,則在開始將psw入棧後還要修改psw中的工作暫存器組選擇位。
(6)c51編譯器從絕對位址8m+3處產生乙個中斷向量,其中m為中斷號,也即interrupt後面的數字。該向量包含乙個到中斷函式入口位址的絕對跳轉。
(7)中斷函式最好寫在檔案的尾部,並且禁止使用extern儲存型別說明。防止其它程式呼叫。
【例】編寫乙個用於統計外中斷0的中斷次數的中斷服務程式
extern int x;
void int0() interrupt 0 using 1
6).using n修飾符
修飾符using n用於指定本函式內部使用的工作暫存器組,其中n的取值為0~3,表示暫存器組號。
對於using n修飾符的使用,注意以下幾點:
(1)加入using n後,c51在編譯時自動的在函式的開始處和結束處加入以下指令。
(2)using n修飾符不能用於有返回值的函式,因為c51函式的返回值是放在暫存器中的。如暫存器組改變了,返回值就會出錯。
2. 函式的呼叫與宣告
一.函式的呼叫
函式呼叫的一般形式如下:
函式名(實參列表);
對於有引數的函式呼叫,若實參列表包含多個實參,則各個實參之間用逗號隔開。
按照函式呼叫在主調函式**現的位置,函式呼叫方式有以下三種:
(1)函式語句。把被呼叫函式作為主呼叫函式的乙個語句。
(2)函式表示式。函式被放在乙個表示式中,以乙個運算物件的方式出現。這時的被呼叫函式要求帶有返回語句,以返回乙個明確的數值參加表示式的運算。
(3)函式引數。被呼叫函式作為另乙個函式的引數。
二.自定義函式的宣告
在c51中,函式原型一般形式如下:
[extern] 函式型別 函式名(形式參數列);
函式的宣告是把函式的名字、函式型別以及形參的型別、個數和順序通知編譯系統,以便呼叫函式時系統進行對照檢查。函式的宣告後面要加分號。
如果宣告的函式在檔案內部,則宣告時不用extern,如果宣告的函式不在檔案內部,而在另乙個檔案中,宣告時須帶extern,指明使用的函式在另乙個檔案中。
【例】函式的使用
#include //包含特殊功能暫存器庫
#include //包含i/o函式庫
int max(int x,int y); //對max函式進行宣告
void main(void) //主函式
int max(int x,int y)
【例24】 外部函式的使用
程式serial_initial.c
#include //包含特殊功能暫存器庫
#include //包含i/o函式庫
void serial_initial(void) //主函式
程式y1.c
#include //包含特殊功能暫存器庫
#include //包含i/o函式庫
extern serial_initial();
void main(void)
3. 函式的巢狀與遞迴
一.函式的巢狀
在乙個函式的呼叫過程中呼叫另乙個函式。c51編譯器通常依靠堆疊來進行引數傳遞,堆疊設在片內ram中,而片內ram的空間有限,因而巢狀的深度比較有限,一般在幾層以內。如果層數過多,就會導致堆疊空間不夠而出錯。
【例】 函式的巢狀呼叫
#include //包含特殊功能暫存器庫
#include //包含i/o函式庫
extern serial_initial();
int max(int a,int b)
int add(int c,int d,int e,int f)
main()
二.函式的遞迴
遞迴呼叫是巢狀呼叫的乙個特殊情況。如果在呼叫乙個函式過程中又出現了直接或間接呼叫該函式本身,則稱為函式的遞迴呼叫。
在函式的遞迴呼叫中要避免出現無終止的自身呼叫,應通過條件控制結束遞迴呼叫,使得遞迴的次數有限。
下面是乙個利用遞迴呼叫求n!的例子。
【例】遞迴求數的階乘n!。
在數學計算中,乙個數n的階乘等於該數本身乘以數n-1的階乘,即n!=n´(n-1)!,用n-1的階乘來表示n的階乘就是一種遞迴表示方法。在程式設計中通過函式遞迴呼叫來實現。
程式如下:
#include //包含特殊功能暫存器庫
#include //包含i/o函式庫
extern serial_initial();
int fac(int n) reentrant
main()
51微控制器與C51
微控制器又稱單片微控制器,是在一塊晶元中整合了cpu 處理器 ram 資料儲存器 rom 程式儲存器 定時器 計數器和多種功能的i o 輸入 輸出 介面等一台計算機所需要的基本功能部件,從而可以完成複雜的運算 邏輯控制 通訊等功能。51微控制器是對所有相容intel 8031指令系統的微控制器的統稱...
51微控制器C51程式
學習c51程式之前需要對c語言有一定的了解和學習 這裡只介紹與c語言有區別的地方 具體的不同如下 1 c51中增加了幾種針對msc 51微控制器的特有資料型別 a sfr和sfr16 用於定義特殊功能暫存器,如 sfr psw 0xd0 一般情況下這些特殊功能暫存器不需要使用者自定義,通常包含在標頭...
C51微控制器入門知識
接觸微控制器也快兩年了,雖然期間偶然玩一玩,但是還是沒有形成乙個完整的微控制器系統。藉著這次同學想學習的機會,再次回到頭來系統的學一遍。其實真正入手微控制器挺容易的,稍微會那麼一點c語言知識,會定義引腳,會置成高低電平就算入門了吧,個人觀點,非喜勿噴。把微控制器總的來分為幾大塊,剩下的就是演算法或者...