![C51編程基礎(chǔ)課件_第1頁](http://file4.renrendoc.com/view10/M01/29/18/wKhkGWW0ZfuADGdxAAGxmhJa1Hw467.jpg)
![C51編程基礎(chǔ)課件_第2頁](http://file4.renrendoc.com/view10/M01/29/18/wKhkGWW0ZfuADGdxAAGxmhJa1Hw4672.jpg)
![C51編程基礎(chǔ)課件_第3頁](http://file4.renrendoc.com/view10/M01/29/18/wKhkGWW0ZfuADGdxAAGxmhJa1Hw4673.jpg)
![C51編程基礎(chǔ)課件_第4頁](http://file4.renrendoc.com/view10/M01/29/18/wKhkGWW0ZfuADGdxAAGxmhJa1Hw4674.jpg)
![C51編程基礎(chǔ)課件_第5頁](http://file4.renrendoc.com/view10/M01/29/18/wKhkGWW0ZfuADGdxAAGxmhJa1Hw4675.jpg)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
4C語言及程序設(shè)計4.1C51概述4.2C51數(shù)據(jù)類型及存儲4.3C51變量的定義及數(shù)據(jù)存儲區(qū)域4.4C51位變量的定義4.5C51特殊功能寄存器的定義4.6C51指令的定義4.7C51的輸入/輸出4.8C51函數(shù)的定義4.9C51與匯編語言混合編程目錄C51編程基礎(chǔ)第4章單片機C語言及程序設(shè)計
本章內(nèi)容的安排,認為讀者已經(jīng)學(xué)習(xí)過C語言,具有C語言的基本知識,因此,本章內(nèi)容完全是結(jié)合單片機來講解,也就是補充C語言在單片機方面的概念、數(shù)據(jù)定義和函數(shù)定義等。 通過本章學(xué)習(xí),使讀者能夠比較順利地編寫C51程序。
C51編程基礎(chǔ)4.1C51概述主要內(nèi)容4.1.1C語言編程的優(yōu)勢4.1.2C51與ANSIC的區(qū)別4.1.3C51擴展的關(guān)鍵字C51編程基礎(chǔ)4.1C51概述
學(xué)習(xí)單片機C語言的必要性 隨著單片機性能的不斷提高,C語言編譯調(diào)試工具的不斷完善,以及現(xiàn)在對單片機產(chǎn)品輔助功能的要求、對開發(fā)周期不斷縮短的要求,使得越來越多的單片機編程人員轉(zhuǎn)向使用C語言,因此有必要在單片機課程中講授“單片機C語言”。
“C51”概念:為了與ANSIC區(qū)別,把“單片機C語言”稱為“C51”,也稱為“KeilC”。
C51編程基礎(chǔ)4.1.1C語言編程的優(yōu)勢
在編程方面,使用C51較匯編語言有諸多優(yōu)勢:
1)編程容易
2)容易實現(xiàn)復(fù)雜的數(shù)值計算
3)容易閱讀與交流
4)容易調(diào)試與維護程序
5)容易實現(xiàn)模塊化開發(fā)
6)程序可移植性好
C51編程基礎(chǔ)4.1.2C語言與ANSI的區(qū)別
用匯編語言編寫單片機程序時,必須要考慮其存儲器的結(jié)構(gòu),尤其要考慮其片內(nèi)數(shù)據(jù)存儲器、特殊功能寄存器是否正確合理的使用,以及按照實際地址端口數(shù)據(jù)的處理。 用C51編寫程序,雖然不像匯編語言那樣需要具體地組織、分配存儲器資源,但是C51對數(shù)據(jù)類型和變量的定義,必須要與單片機的存儲結(jié)構(gòu)相關(guān)聯(lián),否則編譯器不能正確地映射定位。
C51編程基礎(chǔ)4.1.2C語言與ANSI的區(qū)別
用C51編寫單片機程序,與用ANSIC編寫程序的不同之處是,需要根據(jù)單片機存儲器結(jié)構(gòu)及內(nèi)部資源,定義相應(yīng)的數(shù)據(jù)類型和變量。 其它的語法規(guī)定、程序結(jié)構(gòu)及程序設(shè)計方法,都與ANSIC相同。所以本章主要介紹C51各種變量的定義、指針定義、函數(shù)定義和混合編程。
C51編程基礎(chǔ)4.1.3C51擴展的關(guān)鍵字
由于單片機在結(jié)構(gòu)及編程上的特殊要求,C51有自己的特殊關(guān)鍵字,稱之為C51擴展的關(guān)鍵字,下面給出常用的C51擴展的關(guān)鍵字。
_at_ bdata bit code data idata interrupt pdata reentrant sbit sfr sfr16 using volatile xdata
這些關(guān)鍵字在后面會陸續(xù)接觸到,此處先不給出它們的含義。C51編程基礎(chǔ)4.2C51數(shù)據(jù)類型及存儲主要內(nèi)容4.2.1C51的數(shù)據(jù)類型4.2.2C51數(shù)據(jù)的存儲C51編程基礎(chǔ)4.2.1C51的數(shù)據(jù)類型表4-1C51數(shù)據(jù)類型、長度和數(shù)值范圍數(shù)據(jù)類型表示方法長度數(shù)值范圍無符號字符型unsignedchar1字節(jié)0~255有符號字符型signedchar1字節(jié)-128~127無符號整型unsignedint2字節(jié)0~65535有符號整型signedint2字節(jié)-32768~32767無符號長整型unsignedlong4字節(jié)0~4294967295有符號長整型signedlong4字節(jié)-2147483648~2147483647浮點型float4字節(jié)±1.1755E-38~±3.40E+38特殊功能寄存器型sfrsfr161字節(jié)2字節(jié)0~2550~65535位類型bit、sbit1位0或1C51編程基礎(chǔ)4.2.1C51的數(shù)據(jù)類型
數(shù)據(jù)類型轉(zhuǎn)換
1)自動轉(zhuǎn)換
轉(zhuǎn)換規(guī)則是向高精度數(shù)據(jù)類型轉(zhuǎn)換、向有符號數(shù)據(jù)類型轉(zhuǎn)換。如字符型變量與整型變量相加時,則位變量先轉(zhuǎn)換字符型或整型數(shù)據(jù),然后相加。
2)強制轉(zhuǎn)換 像ANSIC一樣,通過強制類型轉(zhuǎn)換的方式進行轉(zhuǎn)換。如:
unsigned int b; float c; b=(int)c;
C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
MCS-51單片機只有bit和unsignedchar兩種數(shù)據(jù)類型支持機器指令,而其它類型的數(shù)據(jù)都需要轉(zhuǎn)換成bit或unsignedchar型進行存儲。 為了減少單片機的存儲空間和提高運行速度,要盡可能地使用unsignedchar型數(shù)據(jù)。
一、位變量的存儲
bit和sbit型位變量,直接存于RAM的位尋址空間,包括低128位和特殊功能寄存器位。C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
二、字符變量的存儲
字符變量(char):無論是unsignedchar數(shù)據(jù)還是signedchar數(shù)據(jù),均為1個字節(jié),能夠被直接存儲在RAM中,可以存儲在0~0x7f區(qū)域,也可以存儲在0x80~0xff區(qū)域,與變量的定義有關(guān)。
unsignedchar數(shù):可直接被MSC-51接受
signedchar數(shù)據(jù):用補碼表示。需要額外的操作來測試、處理符號位,使用的是兩種庫函數(shù),代碼量大,運算速度降低。C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
三、整型變量的存儲
整型變量(int):不管是unsignedint數(shù)據(jù)還是signedint數(shù)據(jù),均為2個字節(jié),其存儲方法是高位字節(jié)保存在低地址(在前面),低位字節(jié)保存在高地址(在后面)。
例如,整型變量的值為0x1234,在內(nèi)存中的存放如右圖所示。
signedint數(shù)據(jù)用補碼表示。地址低高::1234::C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
四、長整型變量的存儲 長整型變量(long)為4個字節(jié),其存儲方法與整型數(shù)據(jù)一樣,是最高位字節(jié)保存的地址最低(在最前面),最低位字節(jié)保存的地址最高(在最后面)。
如長整型變量的值為0x12345678,在內(nèi)存中的存放方法如右圖所示。不管是unsignedlong數(shù)據(jù)還是signedlong數(shù)據(jù)。地址低高::12345678::C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
五、浮點型變量的存儲
浮點型變量(fload)占4個字節(jié),用指數(shù)方式表示,其具體格式與編譯器有關(guān)。
對于KeilC,采用的是IEEE-754標(biāo)準,具有24位精度,尾數(shù)的最高位始終為1,因而不保存。具體分布為:1位符號位,8位階碼位,23位尾數(shù),如下圖所示。
字節(jié)地址0123浮點數(shù)內(nèi)容SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM符號和階碼尾數(shù)高位尾數(shù)低位C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
符號位S:1表示負數(shù),0表示正數(shù)。
階碼:用移碼表示。如,實際階碼-126用1表示,實際階碼0用127表示,即實際階碼數(shù)加上127得到階碼的表達數(shù)。 階碼數(shù)值范圍:-126~+128。C51編程基礎(chǔ)4.2.2C51數(shù)據(jù)的存儲
例如浮點數(shù)-12.5
符號位為1,12.5的二進制數(shù)為1100.1=1.1001E+0011,階碼數(shù)值為3+127=130=10000010B,尾數(shù)為1001。 因此,其十六進制數(shù)為0xC1480000,則存儲結(jié)構(gòu)如右圖所示。
地址低高::C1480000::說明:教材中存儲結(jié)構(gòu)是錯的。C51編程基礎(chǔ)4.3C51變量的定義及數(shù)據(jù)存儲區(qū)域主要內(nèi)容4.3.1C51變量的定義4.3.2C51變量的存儲類型4.3.3C51變量的存儲區(qū)域4.3.4C51變量定義舉例4.3.5C51變量的存儲模式4.3.6C51變量的絕對定位C51編程基礎(chǔ)4.3.1C51變量的定義
C51變量定義的一般格式為:
[存儲類型] 數(shù)據(jù)類型 [存儲區(qū)]變量名1[=初值][,變量名2[=初值]][,…]或 [存儲類型] [存儲區(qū)]
數(shù)據(jù)類型變量名1[=初值][,變量名2[=初值]][,…]
可見變量(非位變量)的定義由4部分組成,即在變量定義時,指定變量4種屬性。
數(shù)據(jù)類型:在前面的4.2中已經(jīng)敘述過,對于變量名也無須多說,下面主要解釋“存儲類型”和“存儲區(qū)”等概念。
C51編程基礎(chǔ)4.3.2C51變量的存儲類型
存儲類型這個屬性我們?nèi)匝赜肁NSIC的說法,盡量不改變原來的含義。
按照ANSIC,C語言的變量有4種存儲類型: 動態(tài)存儲(auto) 靜態(tài)存儲(static) 全局存儲(extern) 寄存器存儲(register)
C51編程基礎(chǔ)4.3.2C51變量的存儲類型
一、動態(tài)存儲
動態(tài)(存儲)變量:用auto定義的為動態(tài)變量,也叫自動變量。
作用范圍:在定義它的函數(shù)內(nèi)或復(fù)合語句內(nèi)部。 當(dāng)定義它的函數(shù)或復(fù)合語句執(zhí)行時,C51才為變量分配存儲空間,結(jié)束時所占用的存儲空間釋放。 定義變量時,auto可以省略,或者說如果省略了存儲類型項,則認為是動態(tài)變量。動態(tài)變量一般分配使用寄存器或堆棧。
C51編程基礎(chǔ)4.3.2C51變量的存儲類型
二、靜態(tài)存儲
靜態(tài)(存儲)變量:用static定義的為靜態(tài)變量。分為內(nèi)部靜態(tài)和外部靜態(tài)變量。
內(nèi)部靜態(tài)變量:在函數(shù)體內(nèi)定義的為內(nèi)部靜態(tài)變量。 在函數(shù)內(nèi)可以任意使用和修改,函數(shù)運行結(jié)束后會一直存在,但在函數(shù)外不可見,即在函數(shù)體外得到保護。
外部靜態(tài)變量:在函數(shù)體外部定義的為外部靜態(tài)變量。在定義的文件內(nèi)可以任意使用和修改,外部靜態(tài)變量會一直存在,但在文件外不可見,即在文件外得到保護。
C51編程基礎(chǔ)4.3.2C51變量的存儲類型
三、外部存儲
外部(存儲)變量:用extern聲明的變量為外部變量,是在其它文件定義過的全局變量。 用extern聲明后,便可以在所聲明的文件中使用。
需要注意的是:在定義變量時,即便是全局變量,也不能使用extern定義。
C51編程基礎(chǔ)4.3.2C51變量的存儲類型
四、寄存器存儲
寄存器(存儲)變量:用register定義的變量為寄存器變量。
寄存器變量存放在CPU的寄存器中,這種變量處理速度快,但數(shù)目少。
C51中的寄存器變量:
C51的編譯器在編譯時,能夠自動識別程序中使用頻率高的變量,并將其安排為寄存器變量,用戶不用專門聲明。
C51編程基礎(chǔ)4.3.3C51變量的存儲區(qū)域
變量的存儲區(qū)屬性是單片機擴展的概念,非常重要,它涉及到7個新的關(guān)鍵字。
MCS-51單片機有四個存儲空間,分成三類,它們是片內(nèi)數(shù)據(jù)存儲空間、片外數(shù)據(jù)存儲空間和程序存儲空間。
MCS-51單片機有更多的存儲區(qū)域:由于片內(nèi)數(shù)據(jù)存儲器和片外數(shù)據(jù)存儲器又分成不同的區(qū)域,所以單片機的變量有更多的存儲區(qū)域。 在定義變量時,必須明確指出是存放在哪個區(qū)域。C51編程基礎(chǔ)4.3.3C51變量的存儲區(qū)域表4-2C51存儲區(qū)與存儲空間的對應(yīng)關(guān)系關(guān)鍵字對應(yīng)的存儲空間及范圍codeROM空間,64KB全空間data片內(nèi)RAM,直接尋址,低128字節(jié)bdata片內(nèi)RAM,位尋址區(qū)0x20~0x2f,可字節(jié)訪問idata
片內(nèi)RAM,間接尋址,256字節(jié),與@Ri對應(yīng)pdata片外RAM,分頁尋址的256字節(jié)(P2不變),P2改變可尋址64KB全空間,與MOVX@Ri對應(yīng)xdata片外RAM,64KB全空間bit片內(nèi)RAM位尋找區(qū),位地址0x00~0x7f,128位C51編程基礎(chǔ)4.3.4C51變量定義舉例 1)定義存儲在data區(qū)域的動態(tài)unsignedchar變量:
unsignedchardatasec=0,min=0,hou=0; 2)定義存儲在data區(qū)域的靜態(tài)unsignedchar變量:
staticunsignedchardatascan_code=0xfe;
3)定義存儲在data區(qū)域的靜態(tài)unsignedint變量:
staticunsignedintdatadd; C51編程基礎(chǔ)4.3.4C51變量定義舉例 4)定義存儲在bdata區(qū)域的動態(tài)unsignedchar變量:
unsignedcharbdataoperate,operate1; //定義指示操作的可位尋址的變量 5)定義存儲在idata區(qū)域的動態(tài)unsignedchar數(shù)組:
unsignedcharidatatemp[20]; 6)定義在pdata區(qū)域的動態(tài)有符號int數(shù)組:
intpdatasend_data[30]; //定義存放發(fā)送數(shù)據(jù)的數(shù)組
C51編程基礎(chǔ)4.3.4C51變量定義舉例 7)定義存儲在xdata區(qū)域的動態(tài)unsignedint數(shù)組:
unsignedintxdatareceiv_buf[50]; //定義存放接受數(shù)據(jù)的數(shù)組 8)定義存儲在code區(qū)域的unsignedchar數(shù)組:
unsignedcharcodedis_code[10]= {0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f};
//定義共陰極數(shù)碼管段碼數(shù)組C51編程基礎(chǔ)4.3.5C51變量的存儲模式
存儲模式:如果在定義變量時缺省了存儲區(qū)屬性,則編譯器會自動選擇默認的存儲區(qū)域,也就是存儲模式。
變量的存儲模式也就是程序(或函數(shù))的編譯模式。
編譯模式分為三種:小模式(small)、緊湊模式(compact)和大模式(large)。編譯模式由編譯控制命令決定。
存儲模式(編譯模式)決定了變量的默認存儲區(qū)域和參數(shù)的傳遞方法。
C51編程基礎(chǔ)4.3.5C51變量的存儲模式
一、small模式
在small模式下,變量的默認存儲區(qū)域是“data”、“idata”,即未指出存儲區(qū)域的變量保存到片內(nèi)數(shù)據(jù)存儲器中,并且堆棧也安排在該區(qū)域中。
small模式的特點:存儲容量小,但速度快。
在small模式下參數(shù)的傳遞:通過寄存器、堆棧或片內(nèi)數(shù)據(jù)存儲區(qū)完成的。
C51編程基礎(chǔ)4.3.5C51變量的存儲模式
二、compact模式
在compact模式下,變量的默認存儲區(qū)域是“pdata”,即未指出存儲區(qū)域的變量保存到片外數(shù)據(jù)存儲器的一頁中,最大變量數(shù)為256字節(jié),并且堆棧也安排在該區(qū)域中。
compact模式的其特點:是存儲容量較small模式大,速度較small模式稍慢,但比large模式要快。
在compact模式下參數(shù)的傳遞:通過片外數(shù)據(jù)區(qū)的一個固定頁完成的。
C51編程基礎(chǔ)4.3.5C51變量的存儲模式
三、large模式
在large模式下,變量的默認存儲區(qū)域是“xdata”,即未指出存儲區(qū)域的變量保存到片外數(shù)據(jù)存儲器,最大變量數(shù)可達64KB,并且堆棧也安排在該區(qū)域中。
large模式的特點:存儲容量大,速度慢
large模式下參數(shù)的傳遞方式:參數(shù)的傳遞也是通過片外數(shù)據(jù)存儲器完成的。
C51編程基礎(chǔ)4.3.5C51變量的存儲模式
C51支持混合模式:即可以對函數(shù)設(shè)置編譯模式,所以在large模式下,可以對某些函數(shù)設(shè)置為compact模式或small模式,從而提高運行速度。
默認編譯模式:如果文件或函數(shù)未指明編譯模式,則編譯器按small模式處理。
編譯模式控制命令:“#pragmasmall(或compact、large)”應(yīng)放在文件的開始。
C51編程基礎(chǔ)4.3.6C51變量的絕對定位
C51有三種方式可以對變量(I/O端口)絕對定位:絕對定位關(guān)鍵字_at_、指針、庫函數(shù)的絕對定位宏。 對于后兩種方式,在后面指針一節(jié)介紹。
C51擴展的關(guān)鍵字_at_專門用于對變量作絕對定位,_at_使用在變量的定義中,其格式為:
[存儲類型]數(shù)據(jù)類型[存儲區(qū)]變量名1_at_地址常數(shù)[,變量名2…]
C51編程基礎(chǔ)4.3.6C51變量的絕對定位
舉例說明_at_的使用方法
1)對data區(qū)域中的unsignedchar變量aa作絕對定位:
unsigned char dataaa_at_0x30; 2)對pdata區(qū)域中的unsignedint數(shù)組cc作絕對定位:
unsigned intpdatacc[10]_at_0x34; 3)對xdata區(qū)域中的unsignedchar變量printer_port作絕對定位:
unsigned char xdataprinter_port
_at_0x7fff;
C51編程基礎(chǔ)4.3.6C51變量的絕對定位
對變量絕對定位的幾點說明:
1)絕對地址變量在定義時不能初始化,因此不能對code型變量絕對定位;
2)絕對地址變量只能夠是全局變量,不能在函數(shù)中對變量絕對定位;
3)絕對地址變量多用于I/O端口,一般情況下不對變量作絕對定位;
3)位變量不能使用_at_絕對定位。C51編程基礎(chǔ)4.4C51位變量的定義主要內(nèi)容4.4.1bit型位變量的定義4.4.2sbit型位變量的定義C51編程基礎(chǔ)4.4.1bit型位變量的定義
常說的位變量指的就是bit型位變量。C51的bit型位變量定義的一般格式為:
[存儲類型]bit 位變量名1[=初值][,位變量名2[=初值]][,…]
bit位變量被保存在RAM中的位尋址區(qū)域(字節(jié)地址為0x20~0x2f,16字節(jié))。 例如: bit flag_run,receiv_bit=0;
staticbit send_bit;
C51編程基礎(chǔ)4.4.1bit型位變量的定義
兩點說明:
1)bit型位變量與其它變量一樣,可以作為函數(shù)的形參,也可以作為函數(shù)的返回值,即函數(shù)的類型可以是位型的;
2)位變量不能定義指針,不能定義數(shù)組。
C51編程基礎(chǔ)4.4.2sbit型位變量的定義
對于能夠按位尋址的特殊功能寄存器、定義在位尋址區(qū)域的變量(字節(jié)型、整型、長整型),可以對其各位用sbit定義位變量。
為了方便起見,分開討論按位尋址的特殊功能寄存器中位變量的定義、按位尋址的變量中位變量的定義。C51編程基礎(chǔ)4.4.2sbit型位變量的定義
一、特殊功能寄存器中位變量定義 能夠按位尋址的特殊功能寄存器中位變量定義的一般格式為:
sbit 位變量名=位地址表達式
這里的位地址表達式有三種形式:
直接位地址 特殊功能寄存器名帶位號 字節(jié)地址帶位號C51編程基礎(chǔ)4.4.2sbit型位變量的定義
1、用直接位地址定義位變量
這種情況下位變量的定義格式為:
sbit 位變量名=位地址常數(shù)
這里的位地址常數(shù)范圍為0x80~0xff,實際是定義特殊功能寄存器的位。例如:
sbit P0_0=0x80; sbit P1_1=0x91; sbit RS0=0xd3; //定義PSW的第3位
sbit ET0=0xa9; //定義IE的第1位
C51編程基礎(chǔ)4.4.2sbit型位變量的定義
2、特殊功能寄存器名帶位號定義
這時位變量的定義格式為:
sbit 位變量名=特殊功能寄存器名^位號常數(shù) 這里的位號常數(shù)為0~7。例如:
sbit P0_3=P0^3; sbit P1_4=P1^4; sbit OV=PSW^2; //定義PSW的第2位
sbit ES=IE^4; //定義IE的第4位
C51編程基礎(chǔ)4.4.2sbit型位變量的定義
3、寄存器地址帶位號定義位變量
在這種情況下位變量的定義格式為:
sbit 位變量名=特殊功能寄存器地址^位號常數(shù) 這里的位號常數(shù)同上,為0~7。例如:
sbit P0_6=0x80^6; sbit P1_7=0x90^7; sbit AC=0xd0^6; //定義PSW的第6位
sbit EA=0xa8^7; //定義IE的第7位
C51編程基礎(chǔ)4.4.2sbit型位變量的定義
4、幾點說明
1)用sbit定義的位變量,必須能夠按位操作,而不能夠?qū)o位操作功能的位定義位變量。 2)用sbit定義位變量,必須放在函數(shù)外面作為全局位變量,而不能在函數(shù)內(nèi)部定義。
3)用sbit每次只能定義一個位變量。
4)對其它模塊定義的位變量(bit型或sbit型)的引用聲明,都使用bit。
5)用sbit定義的是一種絕對定位的位變量(因為名字是與確定位地址對應(yīng)的),具有特定的意義,在應(yīng)用時不能像bit型位變量那樣隨便使用。C51編程基礎(chǔ)4.4.2sbit型位變量的定義
二、位尋址區(qū)變量的位定義 對bdata型變量(字節(jié)型、整型、長整型),被保存在RAM中的位尋址區(qū),因此可以對bdata型變量各位作位變量定義。 這樣,既可以對bdata型變量作字節(jié)(或整型、長整型)操作,也可以作位操作。
bdata型變量的位定義格式:
sbit位變量名=bdata型變量名^位號常數(shù)
C51編程基礎(chǔ)4.4.2sbit型位變量的定義
bdata型變量為在此之前應(yīng)該是定義過的,位號常數(shù)可以是0~7(8位字節(jié)變量),或0~15(16位整型變量),或0~31(32位字長整型變量)。例如:
unsigned char bdata operate;
對operate的低4位作位變量定義:
sbitflag_key=operate^0; //鍵盤標(biāo)志位
sbitflag_dis=operate^1; //顯示標(biāo)志位
sbitflag_mus=operate^2; //音樂標(biāo)志位
sbitflag_run=operate^3; //運行標(biāo)志位
C51編程基礎(chǔ)4.5C51特殊功能寄存器的定義主要內(nèi)容4.5.18位特殊功能寄存器的定義4.5.216位特殊功能寄存器的定義C51編程基礎(chǔ)4.5.18位特殊功能寄存器的定義
定義的一般格式為:
sfr 特殊功能寄存器名=地址常數(shù)
地址常數(shù)范圍:0x80~0xff。 特殊功能寄存器定義例子(見reg51.h、reg52.h等文件):
sfr P0=0x80; //定義P0寄存器
sfr P1=0x90; //定義P1口寄存器
sfr PSW=0xd0; //定義PSW sfr IE=0xa8; //定義IE
C51編程基礎(chǔ)4.5.216位特殊功能寄存器的定義
定義的一般格式為:
sfr16 特殊功能寄存器名=地址常數(shù) 地址常數(shù)范圍:0x80~0xff。 例如(見reg51.h、reg52.h等文件):
sfr16DPTR=0x82; sfr16T2=0xcc; //含TL2和TH2 sfr16RCAP2=0xca;
//含RCAP2L //和RCAP2H,0xca為RCAP2L的地址C51編程基礎(chǔ)4.5.216位特殊功能寄存器的定義
幾點說明:
1)定義特殊功能寄存器中的地址必須在0x80~0xff范圍內(nèi)。 2)定義特殊功能寄存器,必須放在函數(shù)外面作為全局變量。
3)用sfr或sfr16每次只能定義一個特殊功能寄存器。
4)像sbit一樣,用sfr或sfr16定義的是絕對定位的變量(因為名字是與確定地址對應(yīng)的),具有特定的意義,在應(yīng)用時不能像一般變量那樣隨便使用。
C51編程基礎(chǔ)4.6C51指針的定義主要內(nèi)容4.6.1通用指針4.6.2存儲器專用指針4.6.3指針變換4.6.4C51指針應(yīng)用C51編程基礎(chǔ)4.6C51指針的定義
由于MCS-51單片機有三種不同類型的存儲空間,并且還有不同的存儲區(qū)域,因此C51指針的內(nèi)容更豐富。
指針除了具有像變量的四種屬性(存儲類型、數(shù)據(jù)類型、存儲區(qū)、變量名)外,按存儲區(qū),將指針分為通用指針和不同存儲區(qū)域的專用指針。
C51編程基礎(chǔ)4.6.1通用指針
所謂通用指針,就是通過該類指針可以訪問所有的存儲空間。 在C51庫函數(shù)中通常使用這種指針來訪問。
通用指針用3個字節(jié)來表示: 第一個字節(jié):表示指針?biāo)赶虻拇鎯臻g 第二個字節(jié):為指針地址的高字節(jié) 第三個字節(jié):為指針地址的低字節(jié)C51編程基礎(chǔ)4.6.1通用指針
通用指針的定義與一般C語言指針的定義相同,其格式為:
[存儲類型]數(shù)據(jù)類型*指針名1[,*指針名2][,…]例如:
unsignedchar*cpt; int*dpt; long*lpt; staticchar*ccpt;
通用指針的特點: 定義簡單 訪問所有空間 訪問速度慢
C51編程基礎(chǔ)4.6.2存儲器專用指針
所謂存儲器專用指針,就是通過該類指針,只能夠訪問規(guī)定的存儲空間區(qū)域。 指針本身占用1個字節(jié)(data*,idata*,bdata*,pdata*)或2個字節(jié)(xdata*,code*)。
存儲器專用指針的一般定義格式為:
[存儲類型]數(shù)據(jù)類型指向存儲區(qū)
*[指針存儲區(qū)
]指針名1 [,*[指針存儲區(qū)]指針名2,…]
C51編程基礎(chǔ)4.6.2存儲器專用指針
指向存儲區(qū):
是指針變量所指向的數(shù)據(jù)存儲空間區(qū)域。不能夠缺省。
指針存儲區(qū):
是指針變量本身所存儲的空間區(qū)域。
缺省時認為指針存儲區(qū)在默認的存儲區(qū)域,其默認存儲區(qū)域決定于所設(shè)定的編譯模式。
指向和指針存儲區(qū),兩者可以是同一個區(qū)域,但多數(shù)情況下不會是同一個區(qū)域。
C51編程基礎(chǔ)4.6.2存儲器專用指針
存儲器專用指針例子:
unsignedchardata*cpt1,*cpt2; signedintidata*dpt1,*dpt2; unsignedcharpdata*ppt; signedlongxdata*lpt1,*lpt2; unsignedcharcode*ccpt;
上面所定義的指針雖然所指向的空間不同,但指針變量本身都存儲在默認的存儲區(qū)域。
C51編程基礎(chǔ)4.6.2存儲器專用指針
又如:
1)unsignedchardata*idatacpt1,*idatacpt2; 2)signedintidata*datadpt1,*datadpt2; 3)unsignedcharpdata*xdatappt; 4)signedlongxdata*lpt1,*xdatalpt2; 5)unsignedcharcode*dataccpt;
綠色關(guān)鍵字為指針?biāo)赶虻拇鎯^(qū)
藍色關(guān)鍵字為指針本身所存儲的區(qū)域C51編程基礎(chǔ)4.6.2存儲器專用指針
注意:(1)要區(qū)分指針變量指向的空間區(qū)域和指針變量本身所存儲的區(qū)域;(2)定義時,前者不能缺省,而后者可以缺?。唬?)指針變量的長度:指向不同的區(qū)域,占用的字節(jié)數(shù)不同。
說明:指針變量本身所存儲的區(qū)域,在定義指針時一般都省略了,指針變量本身保存在缺省存儲的區(qū)域中。 定義時,缺省指針存儲的區(qū)域,顯得簡單,并且對初學(xué)者更容易理解。
C51編程基礎(chǔ)4.6.3指針變換
一、通用指針格式 由前面的討論知,通用指針由3個字節(jié)組成,第一個字節(jié)為數(shù)據(jù)的存儲區(qū)域,后兩個字節(jié)為指針地址,第一個字節(jié)的存儲區(qū)域編碼如表4-6所示。
表4-6通用指針存儲區(qū)域編碼存儲區(qū)idataxdatapdatadatacode編碼12345C51編程基礎(chǔ)4.6.3指針變換
一、指針轉(zhuǎn)換
指針轉(zhuǎn)換有兩種途徑,一種是顯式的編程轉(zhuǎn)換,另一種是隱式的自動轉(zhuǎn)換。
指針的編程轉(zhuǎn)換:(1)通用指針的第一字節(jié),與專用指針的指向數(shù)據(jù)區(qū)屬性,二者相互轉(zhuǎn)換;(2)通用指針后兩個字節(jié)的地址,與專用指針值的轉(zhuǎn)換。
指針的隱式自動轉(zhuǎn)換:由編譯器在進行編譯時自動完成。
C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
指針在PC機上的C語言中應(yīng)用很廣泛。 在單片機中,由于不使用操作系統(tǒng),指針的應(yīng)用可以獨立于變量,獨立地指向所需要訪問的存儲空間位置。
本節(jié)通過例子來學(xué)習(xí)和認識C51指針的這種獨立應(yīng)用性。 下面介紹兩種利用指針訪問存儲區(qū)的方法。也可以訪問函數(shù)。C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
二、通過指針定義的宏訪問存儲器
1、訪問存儲器宏的定義
用指針定義的、訪問存儲器宏的格式:
#define宏名((數(shù)據(jù)類型volatile存儲區(qū)*)0)
格式中的數(shù)據(jù)類型主要為無符號的字符型數(shù)、整型;格式中的存儲區(qū)域主要使用data、idata、pdata、xdata和code類型,不使用bdata存儲區(qū)類型。
C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
格式中的關(guān)鍵字“volatile”:
“volatile”是單片機中定義的,其含義為:這種變量在程序執(zhí)行中可被隱含地改變而編譯器無法檢測到,告知編譯器不要做優(yōu)化處理,使應(yīng)用者能夠得到正確的變量值。
volatile的應(yīng)用:volatile常用于定義寄存器,特別是狀態(tài)寄存器,因為狀態(tài)寄存器的值不是程序員設(shè)置,而是單片機在運行中CPU設(shè)置的。
特別說明:“volatile”的含義與教材上表述不太一致,此處表述直觀更容易理解。C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
2、庫函數(shù)中訪問存儲器宏的原型
C51編譯器提供了兩組用指針定義的絕對存儲器訪問的宏,其原型如下。
1)按字節(jié)訪問存儲器的宏:#defineCBYTE((unsignedcharvolatilecode*)0)#defineDBYTE((unsignedcharvolatiledata*)0)#definePBYTE ((unsignedcharvolatilepdata*)0)#defineXBYTE((unsignedcharvolatilexdata*)0)C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
2)按整型雙字節(jié)訪問存儲器的宏:#defineCWORD((unsignedintvolatilecode*)0)#defineDWORD((unsignedintvolatiledata*)0)#definePWORD((unsignedintvolatilepdata*)0)#defineXWORD((unsignedintvolatilexdata*)0)
無idata型,不能訪問片內(nèi)RAM高128字節(jié)區(qū)域(0x80~0xff),需要時可以自己定義。
這些宏定義原型放在absacc.h文件中,使用時需要用預(yù)處理命令把該頭文件包含到文件中,形式為:#include<absacc.h>。
C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
3、絕對訪問存儲器宏的應(yīng)用 使用宏定義訪問存儲器的形式類似于數(shù)組。
1)按字節(jié)訪問存儲器宏的形式
宏名[地址]
即數(shù)組中的下標(biāo)就是存儲器的地址,因此使用起來非常方便。例如:
DBYTE[0x30]=48; //給片內(nèi)RAM送數(shù)據(jù)
XBYTE[0x0002]=0x36; //給片外RAM送數(shù)據(jù)
dis_buf[0]=CBYTE[TABLE+5];
//從CODE區(qū)讀取數(shù)據(jù)C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
2)按整型數(shù)訪問存儲器宏的形式
宏名[下標(biāo)]
由于整型數(shù)占兩個字節(jié),所以下標(biāo)與地址的關(guān)系為:地址=下標(biāo)×2。 由于數(shù)組中的下標(biāo)與存儲器的地址是倍數(shù)關(guān)系,使用時要注意。例如:
DWORD[0x20]=0x1234;//給0x40、0x41送數(shù)
XWORD[0x0002]=0x5678;//給4、5單元送數(shù)
通過指針定義的宏訪問存儲器這種方法,特別適用于訪問I/O口。
C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
一、通過專用指針直接訪問存儲器 使用指針直接訪問存儲器對PC機是禁止的,但對于單片機來說使用時注意是可以的。
使用指針直接訪問存儲器方法是先定義所需要的指針,給指針賦地址值,然后使用指針訪問存儲器。例如:
unsignedcharxdata*xcpt; xcpt=0x2000; *xcpt=123; //給0x2000送數(shù)
xcpt++; *xcpt=234;
//給0x2001送數(shù)C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
例4-1
編寫程序,將單片機片外數(shù)據(jù)存儲器中地址從0x1000開始20個字節(jié)數(shù)據(jù),傳送到片內(nèi)數(shù)據(jù)存儲器地址從0x30開始的區(qū)域。
程序段如下:
unsignedchardata i,*dcpt; unsignedcharxdata *xcpt; dcpt=0x30; //給指針賦地址
xcpt=0x1000; for(i=0;i<20;i++) *(dcpt+i)=*(xcpt+i);
dcpt和xcpt兩個指針變量存儲在什么地方?C51編程基礎(chǔ)4.6.4C51指針應(yīng)用
例4-2
在數(shù)字濾波中有一種叫做“中值濾波”技術(shù),就是對采集的數(shù)據(jù)按照從大到小或者從小到大進行排序,然后取中間位置的數(shù)作為采樣值。試編寫一函數(shù),對存放在片內(nèi)數(shù)據(jù)存儲器中,從0x50開始的21個單元的采樣數(shù)據(jù),用冒泡法排序進行中值濾波,并把得到的中值數(shù)據(jù)返回。
中值濾波函數(shù)如下:
unsignedcharmedian_filter()
{ unsignedchardata*point,i,j,n,d;
C51編程基礎(chǔ)4.6.4C51指針應(yīng)用 for(i=0;i<20;i++) //外層循環(huán)20次
{ point=0x50; //point指向0x50處
n=20﹣i; //n為內(nèi)層循環(huán)次數(shù)
for(j=0;j<n;j++) //內(nèi)層循環(huán)
{ if(*point<*(point+1)) //從大到小排
{ d=*point;*point=*(point+1); *(point+1)=d;
} point++; //指針指向下一個數(shù)
} } point=0x50+10; //指向位于中間的數(shù)
return*point; //返回得到的中值
}
C51編程基礎(chǔ)4.7C51的輸入/輸出主要內(nèi)容4.7.1基本輸入/輸出函數(shù)4.7.2格式輸出函數(shù)printf4.7.3格式輸入函數(shù)scanfC51編程基礎(chǔ)4.7C51的輸入/輸出
C51的輸入和輸出函數(shù)的形式雖然與ANSIC的一樣,但實際意義和使用方法都大不一樣,因此,有必要專門介紹一下C51的輸入/輸出函數(shù)。
在C51的I/O函數(shù)庫中定義的I/O函數(shù),都是以_getkey和putchar函數(shù)為基礎(chǔ)。
這些I/O函數(shù)包括:字符輸入/輸出函數(shù)getchar和putchar,字符串輸入/輸出函數(shù)gets和puts,格式輸入/輸出函數(shù)printf和scanf等。C51編程基礎(chǔ)4.7C51的輸入/輸出
C51的輸入/輸出函數(shù),都是通過單片機的串行接口實現(xiàn)的。 在使用這些I/O函數(shù)之前,必須先對單片機的串行口、定時器/計數(shù)器T1進行初始化。假設(shè)單片機的晶振為11.0592MHz,波特率為9600bps,則初始化程序段為:
SCON=0x52; //設(shè)置串口方式1收、發(fā)
TMOD=0x20; //設(shè)置T1以模式2工作
TL1=0xfd; //設(shè)置T1低8位初值
TH1=0xfd; //設(shè)置T1自動重裝初值
TR1=1; //開T1
C51編程基礎(chǔ)4.7.1基本輸入/輸出函數(shù)
1、基本輸入函數(shù)getkey getkey函數(shù)是基本的字符輸入函數(shù),原型為
char _getkey(void)
函數(shù)功能:從單片機串行口讀入一個字符,如果沒有字符輸入則等待,返回值為讀入的字符,不顯示。 可重入函數(shù)。
字符輸入函數(shù)getchar()
功能:與getkey基本相同,
唯一的區(qū)別:還要從串行口返回字符。C51編程基礎(chǔ)4.7.1基本輸入/輸出函數(shù)
2.基本輸出函數(shù)putchar putchar函數(shù)是基本的字符輸出函數(shù),其原型為:
char putchar(char)
函數(shù)功能:是從單片機的串行口輸出一個字符,返回值為輸出的字符。
putchar為可重入函數(shù)。C51編程基礎(chǔ)4.7.2格式輸出函數(shù)printf
函數(shù)功能:通過單片機的串行口輸出若干任意類型的數(shù)據(jù)。格式如下:
printf(格式控制,輸出參數(shù)表)
格式控制 是用雙引號括起來的字符串,也稱為轉(zhuǎn)換控制字符串,它包括三種信息: 格式說明符 普通字符 轉(zhuǎn)義字符。C51編程基礎(chǔ)4.7.1格式輸出函數(shù)printf
1)格式說明符:由百分號“%”和格式字符組成,其作用是指明輸出數(shù)據(jù)的格式,如%d、%c、%s等,詳細情況見表4-3。
2)普通字符:這些字符按原樣輸出,主要用來輸出一些提示信息。
3)轉(zhuǎn)義字符:由“\”和字母或字符組成,它的作用是輸出特定的控制符,如轉(zhuǎn)義字符\n的含義是輸出換行,詳細情況見表4-4。
C51編程基礎(chǔ)4.7.1格式輸出函數(shù)printf表4-3printf函數(shù)的格式字符表4-4常用的轉(zhuǎn)義字符格式字符數(shù)據(jù)類型輸出格式轉(zhuǎn)義字符含義ASCII碼dint有符號十進制數(shù)\0空字符0x00uint無符號十進制數(shù)\n換行符0x0aoint無符號八進制數(shù)\r回車符0x0dx,Xint無符號十六進制數(shù)\t水平制表0x09ffloat十進制浮點數(shù)\b退格符0x08e,Efloat科學(xué)計數(shù)法的十進制浮點數(shù)\f換頁符0x0cg,Gfloat自動選擇e或f格式\’單引號0x27cchar單個字符\”雙引號0x22s指針帶結(jié)束符的字符串\\反斜杠0x5cC51編程基礎(chǔ)4.7.1格式輸出函數(shù)printf
用printf函數(shù)輸出例子(假設(shè)y已定義過,也賦值過): printf(“x=%d”,36); //從串行口輸出x=36 printf(“y=%d”,y);
//從串行口輸出y=y的值 printf(“c1=%c,c2=%c”,‘A’,‘B’);
//從串行口輸出c1=A,c2=B printf(“%s\n”,“OK,Senddatabegin!”); //從串行口輸出OK,Senddatabegin!和\n
C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf
scanf函數(shù)的功能:通過單片機串行口實現(xiàn)各種數(shù)據(jù)輸入。函數(shù)格式如下:
scanf(格式控制,地址列表)
格式控制 格式控制與printf函數(shù)的類似,也是用雙引號括起來的一些字符,包括三種信息:格式說明符、普通字符和空白字符。
1)格式說明符:由百分號“%”和格式字符組成,其作用是指明輸入數(shù)據(jù)的格式,見表4-5。
C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf
2)普通字符:在輸入時,要求這些字符按原樣輸入。
3)空白字符:包括空格、制表符和換行符等,這些字符在輸入時被忽略。
地址列表:是由若干個地址組成,它可以是指針變量、變量地址(取地址運算符“&”加變量)、數(shù)組地址(數(shù)組名)或字符串地址(字符串名)等。
C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf
用scanf函數(shù)輸入例子(假設(shè)x、y、z、c1、c2是定義過的變量,str1是定義過的指針):
scanf(“%d”,&x);
scanf(“%d%d”,&y,&z);
scanf(“%c%c”,&c1,&c2); scanf(“%s”,str1); 在實際的串行通信中,傳輸?shù)臄?shù)據(jù)多數(shù)是字符型和字符串,以字符串居多,往往把數(shù)字型數(shù)據(jù)轉(zhuǎn)換成字符串傳輸。
C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf
例4-3
有一單片機時鐘系統(tǒng),為了演示輸出函數(shù)putchar和輸入函數(shù)getkey的應(yīng)用,編寫程序,用串行口方式1自發(fā)自收,每一秒鐘從串行口發(fā)送一次時間數(shù)據(jù)的時、分、秒,從串行口接收到數(shù)據(jù)后,送給6位數(shù)碼管顯示。設(shè)晶振頻率為11.0592MHz,波特率為9600bps。不用編寫時鐘計時函數(shù)和數(shù)碼管顯示函數(shù)。C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf#include<reg52.h> //包含頭文件#include<stdio.h> //包含I/O函數(shù)庫unsignedchardatat1[3]; //存放原始的時分秒unsignedchardatadis_buf[6]; //數(shù)碼管顯示voidmain(void){ unsignedchardatat2[3]; //放接收的時間
unsignedchardatasec0=61; //秒備份
unsignedchardatai;C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf SCON=0x52; //串行口初始化
TMOD=0x20; //設(shè)置定時器工作模式
TH1=0xfd; //設(shè)置T1重裝的初值
TR1=1; //開T1運行
while(1)
{if(sec0!=t1[2]) //判斷秒是否已經(jīng)改變
{ putchar(t1[i]);
t2[i++]=_getkey();C51編程基礎(chǔ)4.7.2格式輸入函數(shù)scanf if(i>2) {dis_buf[0]=t2[0]/10;dis_buf[1]=t2[0]%10;
dis_buf[2]=t2[1]/10;dis_buf[3]=t2[1]%10;
dis_buf[4]=t2[2]/10;dis_buf[5]=t2[2]%10; i=0; sec0=t1[2]; //更新秒備份 }
}
display(); //調(diào)用數(shù)碼管掃描顯示函數(shù) }}C51編程基礎(chǔ)4.8C51函數(shù)的定義主要內(nèi)容4.8.1C51函數(shù)的定義4.8.2C51中斷函數(shù)的定義 C51函數(shù)的定義與ANSIC相似,但有更多的屬性要求。本節(jié)先討論函數(shù)的一般定義,然后專門給出中斷函數(shù)的定義,因為中斷函數(shù)有其特殊性。
C51編程基礎(chǔ)4.8.1C51函數(shù)的定義
在C51中,函數(shù)的定義與ANSIC中是相同的。唯一不同的就是在函數(shù)的后面需要帶上若干個C51的專用關(guān)鍵字。C51函數(shù)定義的一般格式如下: 返回類型函數(shù)名(形參表)[函數(shù)模式][reentrant][interruptm][usingn] {
局部變量定義 執(zhí)行語句
}
C51編程基礎(chǔ)4.8.1C51函數(shù)的定義
各屬性含義如下:
函數(shù)模式:也就是編譯模式、存儲模式,可以為small、compact和large。缺省時則使用文件的編譯模式。
reentrant:表示重入函數(shù)。所謂可重入函數(shù),就是允許被遞歸調(diào)用的函數(shù)。是C51定義的關(guān)鍵字。
在編譯時會為重入函數(shù)生成一個堆棧,通過這個堆棧來完成參數(shù)的傳遞和存放局部變量。 重入函數(shù)不能使用bit型參數(shù);函數(shù)返回值也不能是bit型。C51編程基礎(chǔ)4.8.1C51函數(shù)的定義
interruptm:中斷關(guān)鍵字和中斷號。interrupt是C51定義的。C51支持32個中斷源 中斷入口地址與中斷號m的關(guān)系:
中斷入口地址=3+8×m。表4-7單片機中斷源與中斷號的關(guān)系中斷源外中斷0T0中斷外中斷1T1中斷串行中斷T2中斷中斷號012345中斷入口地址0x00030x000b0x00130x001b0x00230x002bC51編程基礎(chǔ)4.8.1C51函數(shù)的定義
usingn:選擇工作寄存器組和組號,
n可以為0~3,對應(yīng)第0組到第3組。關(guān)鍵字using是C51定義的。
如果函數(shù)有返回值,不能使用該屬性,因為返回值是存于寄存器中,函數(shù)返回時要恢復(fù)原來的寄存器組,導(dǎo)致返回值錯誤。
C51編程基礎(chǔ)4.8.2C51中斷函數(shù)的定義 C51函數(shù)的定義實際上已經(jīng)包含了中斷服務(wù)函數(shù),但為了明確起見,下面專門給出中斷處理函數(shù)的具體定義形式:
void函數(shù)名(void)[函數(shù)模式]interruptm[usingn] {
局部變量定義 執(zhí)行語句
}
C51編程基礎(chǔ)4.8.2C51中斷函數(shù)的定義
中斷服務(wù)函數(shù)需要注意以下幾點:
1)中斷服務(wù)函數(shù)不傳遞參數(shù);
2)中斷服務(wù)函數(shù)沒有返回值;
3)中斷服務(wù)函數(shù)必須有interruptm屬性;
4)進入中斷服務(wù)函數(shù),ACC、B、PSW會進棧,根據(jù)需要,DPL、DPH也可能進棧,如果沒有usingn屬性,R0~R7也可能進棧,否則不進棧;
5)在中斷服務(wù)函數(shù)中調(diào)用其它函數(shù),被調(diào)函數(shù)最好設(shè)置為可重入的,因為中斷是隨機的,有可能中斷服務(wù)函數(shù)所調(diào)用的函數(shù)出現(xiàn)嵌套調(diào)用;
6)不能夠直接調(diào)用中斷服務(wù)函數(shù)。
C51編程基礎(chǔ)4.8.2C51中斷函數(shù)的定義
例4-4
編寫程序,使用定時器/計數(shù)器0定時并產(chǎn)生中斷,實現(xiàn)從P1.7產(chǎn)生方波的功能。
程序如下:#include<reg52.h>#define TIMER0L 0x18 //設(shè)振蕩頻率為12MHz#define TIMER0H 0xfc //定時1ms(1000微秒)voidtimer0_int(void)interrupt1{ TL0=TIMER0L;
TH0=TIMER0H;
P1_7=~P1_7; //產(chǎn)生的方波頻率為500Hz}
C51編程基礎(chǔ)4.8.2C51中斷函數(shù)的定義void main(void){ TMOD=0x01; //設(shè)置T1模式1定時
TL0=TIMER0L; //設(shè)置T0低8位初值
TH0=TIMER0H; //設(shè)置T0高8位初值
IE=0x82; //開T0中斷和總中斷
TR0=1; //開T0運行
while(1); //等待中斷,產(chǎn)生方波}
C51編程基礎(chǔ)4.9C51與匯編語言混合編程主要內(nèi)容4.9.1在C51程序中嵌入?yún)R編程序4.9.2C51程序與匯編程序混合編程C51編程基礎(chǔ)4.9C51與匯編語言混合編程
混合編程有兩種方式:
一種是在C語言函數(shù)中嵌入?yún)R編語言程序,程序中沒有獨立的匯編語言函數(shù),只有個別C語言函數(shù)中嵌入有匯編程序;
另一種是C語言文件與匯編語言文件混合編程,程序中有獨立的匯編程序函數(shù)和匯編語言文件。 無論是哪種混合編程方式,采用C51后,程序的大部分是C語言,只有少部分是匯編語言。
C51編程基礎(chǔ)4.9.1
在C51程序中嵌入?yún)R編程序
其方法是用編譯控制指令“#pragmasrc”、“#pragmaasm”和“#pragmaendasm”實現(xiàn)。
“#pragmasrc”是控制編譯器將C源文件編譯成匯編文件,“#pragmasrc”要放在文件的開始;
“#pragmaasm”和“#pragmaendasm”指示匯編語言程序的開始和結(jié)束,分別放在匯編程序段的前面和后面。C51編程基礎(chǔ)4.9.1
在C51程序中嵌入?yún)R編程序
例4-5
編寫一從單片機P1口做循環(huán)右移輸出的流水燈子程序。#pragmasrc //指示將C文件編譯成匯編文件
……voidround_lamp(void){ staticunsignedcharlamp=0x55; P1=lamp;#pragmaasm //指示匯編語言程序開始
MOV A,lamp //對變量lamp做循環(huán)右移
RR A MOV lamp,A#pragmaendasm //指示匯編語言程序結(jié)束}
C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
在這種情況下,C語言與匯編語言程序都是獨立的文件,它們的函數(shù)要相互調(diào)用,這就涉及到了匯編語言程序的參數(shù)傳遞和函數(shù)命名兩個問題。 下面先討論匯編語言函數(shù)的命名和參數(shù)傳遞問題,然后討論混合編程。
C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程主要內(nèi)容一、C51函數(shù)的命名規(guī)則二、C51函數(shù)段與數(shù)據(jù)段的格式三、C51函數(shù)的參數(shù)傳遞規(guī)則四、匯編語言文件及函數(shù)編寫方法五、匯編語言文件編程舉例六、在C語言中調(diào)用匯編語言的方法C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
一、C51函數(shù)的命名規(guī)則 從表4-8中可以看出,C51函數(shù)的命名規(guī)則主要有:
函數(shù)名字符串
//不傳遞參數(shù)的函數(shù)
_函數(shù)名字符串
//通過寄存器傳遞參數(shù)
_?函數(shù)名字符串
//通過堆棧傳遞參數(shù)的可重入函數(shù)
C51函數(shù)名還有其它的格式,如通過存儲器傳遞參數(shù)的函數(shù)等,在混合編程中基本不用,所以不再介紹。
C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程表4-8C51中函數(shù)名的轉(zhuǎn)換規(guī)則C51函數(shù)聲明匯編函數(shù)名說明typefunc1(void)FUNC1調(diào)用時不傳遞參數(shù),但有返回值,函數(shù)名不變typefunc2(args)_FUNC2通過寄存器傳遞參數(shù),函數(shù)名加前綴“_”typefunc3(args)reentrant_?FUNC3重入函數(shù),通過堆棧傳遞參數(shù),函數(shù)名加前綴“_?”C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
二、C51函數(shù)段與數(shù)據(jù)段的格式
C51編譯后對每個函數(shù)都分配一個獨立的CODE段,并且匯編函數(shù)名字還要帶上模塊名,所以C51匯編語言函數(shù)段的格式為:
?PR?函數(shù)名字符串?模塊名
?PR?_函數(shù)名字符串?模塊名
?PR?_?函數(shù)名字符串?模塊名 如果函數(shù)中定義有局部變量,編譯時也給局部變量分配數(shù)據(jù)段,數(shù)據(jù)段的格式為:
?數(shù)據(jù)段前綴?函數(shù)名?數(shù)據(jù)類型C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程表4-9C51段類型前綴與存儲段前綴存儲區(qū)類型說明?PR?code可執(zhí)行程序段?CO?code程序存儲器中的常數(shù)數(shù)據(jù)段?BI?bit內(nèi)部RAM的位類型數(shù)據(jù)段?BA?bdata內(nèi)部RAM的可位尋址的數(shù)據(jù)段?DT?data內(nèi)部RAM的數(shù)據(jù)段?ID?idata內(nèi)部RAM的間接尋址的數(shù)據(jù)段?PD?pdata外部RAM的分頁數(shù)據(jù)段?XD?xdata外部RAM的一般數(shù)據(jù)段C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
三、C51函數(shù)的參數(shù)傳遞規(guī)則 分為調(diào)用時的參數(shù)傳遞和返回時參數(shù)的傳遞。
1、調(diào)用時參數(shù)的傳遞
分三種情況:少于等于3個參數(shù)時通過寄存器傳遞(寄存器不夠用時通過存儲區(qū)傳遞);多于3個時有一部分通過存儲區(qū)傳遞;對于重入函數(shù)參數(shù)通過堆棧傳遞。 通過寄存器傳遞速度最快。表4-10給出了第一種情況通過寄存器傳遞參數(shù)的規(guī)則。
C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程表4-10C51利用寄存器傳遞參數(shù)規(guī)則參數(shù)號charintlong,float一般指針1R7R6,R7(低字節(jié))R4~R7R1R2R3(R3為存儲區(qū),R2為高地址,R1為低地址)2R5R4,R5(低字節(jié))R4~R7或存儲區(qū)R1R2R3或存儲區(qū)3R3R2,R3(低字節(jié))存儲區(qū)R1R2R3或存儲區(qū)C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
2、函數(shù)返回值的傳遞 當(dāng)函數(shù)有返回值時,通過寄存器傳遞。表4-11C51函數(shù)返回值傳遞規(guī)則返回類型使用的寄存器說明bitC(進位標(biāo)志)由進位標(biāo)志位返回char或1字節(jié)指針R7由R7返回int或2字節(jié)指針R6,R7高字節(jié)在R6,低字節(jié)在R7longR4~R7高字節(jié)在R4,低字節(jié)在R7floatR4~R732位IEEE格式一般指針R1~R3R3為存儲區(qū),R1為低地址C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
四、匯編語言文件及函數(shù)編寫方法
匯編語言文件的構(gòu)成主要有:定義模塊名、函數(shù)聲明、公共函數(shù)聲明、引用函數(shù)聲明、引用變量聲明、函數(shù)定義等部分。
1、定義模塊 對匯編語言文件定義模塊名,一般一個文件為一個模塊,也可以多個文件為同一個模塊名。模塊定義格式如下:
NAME模塊名 定義模塊要放在文件的開始。 例如: NAMEEXAMP
C51編程基礎(chǔ)4.9.2
C51程序與匯編程序混合編程
2、函數(shù)聲明 即對本模塊定義的函數(shù)作聲明,其格式為:
?PR?函數(shù)名?模塊名SEGMENTCODE
格式中的函數(shù)名規(guī)則如上面一所述。例如:
?PR?DISPLAY?EXAMPSEGMENTCODE ?PR?_RIGHT?EXAMP SEGMENTCODE ?PR?_?MUSIC?EXAMPSEGMENTCODE
說明:函數(shù)的聲明放在文件的前面,一般在模塊定義之后,并且緊接著模塊定義。
C51編程基礎(chǔ)4.
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 環(huán)境管理在企業(yè)發(fā)展中的作用研究
- 生產(chǎn)流程優(yōu)化基于數(shù)據(jù)的決策支持方案
- 珠寶鑒定與法律法規(guī)關(guān)系解析
- 安保安全措施方案
- 2023九年級化學(xué)下冊 第九章 現(xiàn)在生活與化學(xué)9.4 化學(xué)物質(zhì)與健康第3課時 治病用的藥品、防范有害化學(xué)物質(zhì)、保護身體健康說課稿 科粵版
- Unit1 Making friends Part A Letters and sounds(說課稿)-2024-2025學(xué)年人教PEP版(2024)英語三年級上冊
- 3 學(xué)習(xí)有方法 說課稿-2024-2025學(xué)年道德與法治三年級上冊統(tǒng)編版
- Unit 3 Fascinating parks Discover Useful Structures 說課稿 -2024-2025學(xué)年高中英語人教版(2019)選擇性必修第一冊
- 《2 拉拉手交朋友》說課稿-2023-2024學(xué)年道德與法治一年級上冊統(tǒng)編版
- 2023六年級數(shù)學(xué)上冊 三 分數(shù)除法 1分數(shù)除法第1課時 倒數(shù)的認識說課稿 西師大版
- 貨運有限公司2024年春節(jié)后復(fù)工復(fù)產(chǎn)安全生產(chǎn)方案
- 2024年孝感中小學(xué)教師招聘真題
- 社交禮儀-儀態(tài)禮儀
- 2024暑期夏日露營潮趣互動音樂節(jié)(唱享潮夏旋律季)活動策劃方案
- 臨床成人ICU患者外周動脈導(dǎo)管管理要點
- 2024年長沙衛(wèi)生職業(yè)學(xué)院單招職業(yè)適應(yīng)性測試題庫及參考答案
- 死亡病例討論模板
- 《讓學(xué)生創(chuàng)造著長大》讀書心得
- 畢業(yè)旅游活動設(shè)計與實施方案
- 宜城安達特種水泥有限公司雙寨子礦區(qū)鋁土礦礦產(chǎn)資源開發(fā)利用與生態(tài)復(fù)綠方案
- 2024-2026招商信諾人壽中國健康指數(shù)白皮書
評論
0/150
提交評論