版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、單片機經(jīng)驗總結(jié)2一,C51內(nèi)存結(jié)構(gòu)深度剖析在編寫應(yīng)用程序時,定義一個變量,一個數(shù)組,或是說一個固定表格,到底存儲在什么地方;當(dāng)定義變量大小超過MCU的內(nèi)存范圍時怎么辦;如何控制變量定義不超過存儲范圍;以及如何定義變量才能使得變量訪問速度最快,寫出的程序運行效率最高。以下將一一解答。1 六類關(guān)鍵字(六類存儲類型)data idata xdata pdata code bdata code: code memory (程序存儲器也即只讀存儲器)用來保存常量或是程序。code memory 采用16位地址線編碼,可以是在片內(nèi),或是片外,大小被限制在64KB 作用:定義常量,如八段數(shù)碼表或是編程使用的
2、常,在定義時加上code 或明確指明定義的常量保存到code memory(只讀) 使用方法: char code table=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; 此關(guān)鍵字的使用方法等同于constdata data memory (數(shù)據(jù)存儲區(qū))只能用于聲明變量,不能用來聲明函數(shù),該區(qū)域位于片內(nèi),采用8位地址線編碼,具有最快的存儲速度,但是數(shù)量被限制在128byte或更少。 使用方法: unsigned char data fast_variable=0; idata idata memory(數(shù)據(jù)存儲區(qū))只能用于聲明變量,不能
3、用來聲明函數(shù). 該區(qū)域位于片內(nèi),采用8位地址線編碼,內(nèi)存大小被限制在256byte或更少。該區(qū)域的低地址區(qū)與data memory地址一致;高地址區(qū)域是52系列在51系列基礎(chǔ)上擴展的并與特殊功能寄存器具有相同地址編碼的區(qū)域。即:data memory是idata memory的一個子集。 xdata xdata memory 只能用于聲明變量,不能用來聲明函數(shù),該區(qū)域位于MCU 外部,采用16位地址線進行編碼,存儲大小被限制在64KB以內(nèi)。 使用方法: unsigned char xdata count=0; pdata pdata memory 只能用于聲明變量,不能用來聲明函數(shù),該區(qū)域位于
4、MCU外部,采用8位地址線進行編碼。存儲大小限制在256byte. 是xdata memory的低256byte。為其子集。 使用方法 unsigned char pdata count=0; bdata bdata memory 只能用于聲明變量,不能用來聲明函數(shù)。該區(qū)域位于8051內(nèi)部位數(shù)據(jù)地址。定義的量保存在內(nèi)部位地址空間,可用位指令直接讀寫。 使用方法: unsigned char bdata varab=0 注:有些資料講,定義字符型變量時,在缺省unsigned 時,字符型變量,默認為無符號,與標(biāo)準C不同,但我在Keil uVision3中測試的時候發(fā)現(xiàn)并非如此。在缺省的情況下默認
5、為有符號?;蛟S在以前的編譯器是默認為無符號。所以看到有的資料上面這樣講的時候,要注意一下,不同的編譯器或許不同。所以我們在寫程序的時候,還是乖乖的把unsigned signed 加上,咱也別偷這個懶。 2函數(shù)的參數(shù)和局部變量的存儲模式 C51 編譯器允許采用三種存儲器模式:SMALL,COMPACT 和LARGE。一個函數(shù)的存儲器模式確定了函數(shù)的參數(shù)的局部變量在內(nèi)存中的地址空間。處于SMALL模式下的函數(shù)參數(shù)和局部變量位于8051單片機內(nèi)部RAM中,處于COMPACT和LARGE模式下的函數(shù)參數(shù)和局部變量則使用單片機外部RAM。在定義一個函數(shù)時可以明確指定該函數(shù)的存儲器模式。方法是在形參表列
6、的后面加上一存儲模式。 示例如下: #pragma large /此預(yù)編譯必須放在所有頭文前面 int func0(char x,y) small; char func1(int x) large; int func2(char x); 注: 上面例子在第一行用了一個預(yù)編譯命令#pragma 它的意思是告訴c51編譯器在對程序進行編譯時,按該預(yù)編譯命令后面給出的編譯控制指令LARGE進行編譯,即本例程序編譯時的默認存儲模式為LARGE.隨后定義了三個函數(shù),第一個定義為SMALL存儲模式,第二個函數(shù)定義為LARGE第三個函數(shù)未指定,在用C51進行編譯時,只有最后一個函數(shù)按LARGE存儲器模式處理
7、,其它則分別按它們各自指定的存儲器模式處理。 本例說明,C51編譯器允許采用所謂的存儲器混合模式,即允許在一個程序中將一些函數(shù)使用一種存儲模式,而其它一些則按另一種存儲器模式,采用存儲器混合模式編程,可以充分利用8051系列單片機中有限的存儲器空間,同時還可以加快程序的執(zhí)行速度。 3絕對地址訪問 absacc.h(相當(dāng)重要)#define CBYTE (unsigned char volatile code *) 0)#define DBYTE (unsigned char volatile data *) 0)#define PBYTE (unsigned char volatile pda
8、ta *) 0)#define XBYTE (unsigned char volatile xdata *) 0) 功能:CBYTE 尋址 CODE區(qū) DBYTE 尋址 DATA區(qū) PBYTE 尋址 XDATA(低256)區(qū) XBYTE 尋址 XDATA區(qū) 例: 如下指令在對外部存儲器區(qū)域訪問地址0x1000 xvar=XBYTE0x1000; XBYTE0x1000=20;#define CWORD (unsigned int volatile code *) 0)#define DWORD (unsigned int volatile data *) 0)#define PWORD (un
9、signed int volatile pdata *) 0)#define XWORD (unsigned int volatile xdata *) 0) 功能:與前面的一個宏相似,只是它們指定的數(shù)據(jù)類型為unsigned int .。 通過靈活運用不同的數(shù)據(jù)類型,所有的8051地址空間都是可以進行訪問。 如DWORD0x0004=0x12F8;即內(nèi)部數(shù)據(jù)存儲器中(0x08)=0x12; (0x09)=0xF8注:用以上八個函數(shù),可以完成對單片機內(nèi)部任意ROM和RAM進行訪問,非常方便。還有一種方法,那就是用指鐘,后面會對C51的指針有詳細的介紹。4寄存器變量(register) 為了提高
10、程序的執(zhí)行效率,C語言允許將一些頻率最高的那些變量,定義為能夠直接使用硬件寄存器的所謂的寄存器變量。定義一個變量時,在變量類型名前冠以“register” 即將該變量定義成為了寄存器變量。寄存器變量可以認為是一自動變量的一種。有效作用范圍也自動變量相同。由于計算機寄存器中寄存器是有限的。不能將所有變量都定義成為寄存器變量,通常在程序中定義寄存器變量時,只是給編譯器一個建議,該變量是否真正成為寄存器變量,要由編譯器根據(jù)實際情況來確定。另一方面,C51編譯器能夠識別程序中使用頻率最高的變量,在可能的情況下,即使程序中并未將該變量定義為寄存器變量,編譯器也會自動將其作為寄存器變量處理。被定義的變量是
11、否真正能成為寄存器變量,最終是由編譯器決定的。5內(nèi)存訪問雜談 1指鐘指鐘本身是一個變量,其中存放的內(nèi)容是變量的地址,也即特定的數(shù)據(jù)。8051的地址是16位的,所以指針變量本身占用兩個存儲單元。指針的說明與變量的說明類似,僅在指針名前加上“*”即可。 如 int *int_point; 聲明一個整型指針 char *char_point; 聲明一個字符型指針 利用指針可以間接存取變量。實現(xiàn)這一點要用到兩個特殊運算符 & 取變量地址 * 取指針指向單元的數(shù)據(jù) 示例一:int a,b; int *int_point; /定義一個指向整型變量的指針 a=15; int_point=&a; /int_p
12、oint指向 a *int_point=5; /給int_point指向的變量a 賦值5 等同于a=5; 示例二: char i,table6,*char_point; char_point=table; for(i=0;i6;i+) char_point=i; char_point+;注: 指針可以進行運算,它可以與整數(shù)進行加減運算(移動指針)。但要注意,移動指針后,其地址的增減量是隨指針類型而異的,如,浮點指針進行自增后,其內(nèi)部將在原有的基礎(chǔ)上加4,而字符指針當(dāng)進生自增的時候,其內(nèi)容將加1。原因是浮點數(shù),占4個內(nèi)存單元,而字符占一個字節(jié)。宏晶科技最新一代STC12C5A360S2系列,每一
13、個單片機出廠時都有全球唯一身份證號碼(ID號),用戶可以在單片機上電后讀取內(nèi)部RAM單元F1HF7H的數(shù)值,來獲取此單片機的唯一身份證號碼。使用MOV Ri 指令來讀取。下面介紹C51 獲取方法: char id7=0; char i; char idata *point; for(i=0;i7;i+) idi=*point; point+; (此處只是對指針做一個小的介紹,達到訪問內(nèi)部任何空間的方式,后述有對指針使用的詳細介紹)2對SFR,RAM ,ROM的直接存取C51提供了一組可以直接對其操作的擴展函數(shù)若源程序中,用#include包含頭文件,io51.h 后,就可以在擴展函數(shù)中使用特殊
14、功能寄存器的地址名,以增強程序的可讀性: 注 此方法對SFR,RAM,ROM的直接存取不建議使用.因為,淡io51.h這個頭文件在KEIL中無法打開,可用指針,或是采用absacc.h頭文件, 3 PWM與PCASTC12系列有兩路PWM/PCA PWM:(Pulse Width Modulation)脈寬調(diào)制,是一種使用程序來控制波形占空比,周期,相位波形的技術(shù)。 PCA:(Programmable Counter Array)可編程計數(shù)陣列,它比通常的定時/計數(shù)器的定時能力強,需要CPU的干預(yù)少。其優(yōu)勢一是軟件簡單,二是精度大有提高。二, reg51.頭文件剖析 我們平時寫單片機應(yīng)用程序的
15、時候,所使用的頭文件大多都是用的的reg51.h或是用reg52.h。會寫C51的人都會用,但對其頭文件內(nèi)部的定義有所了解的人確并不多。下面對其內(nèi)部做詳細解釋,方便讀者作進一步的了解,并能運用各類型號的單片機。因為增強型號的單片機的增強功能都是通過特殊功能寄存器控制。 打開 reg52.h 頭文件,會發(fā)現(xiàn)是由大量的 sfr ,sbit的聲明組成,甚至于還有sfr16.其實這樣的聲明都是與單片機內(nèi)部功能寄存器(特殊功能寄存器)聯(lián)系起來的,下面對其做出詳細解釋sfr: 聲明變量 SFR 聲明一個變量,它的聲明與其它的C變量聲明基本相同,唯一的區(qū)別,SFR在聲明的同時為其指定特殊功能寄存器作為存儲地
16、址,而不同于C變量聲明的整型,字符型等等由編譯器自動分配存儲空間。 如reg52.h頭文件,第一條聲明就是sfr P0 = 0x80; 此處聲明一個變量P0,并指定其存儲地址為特殊功能寄存器0x80;,在加入reg52.h頭文件后。編寫應(yīng)用程序時P0就可以直接使用而無需定義,對P0的操作就是,對內(nèi)部特殊功能寄存器(0x80對應(yīng)用MCU的P0口)的操作,可進行讀寫操作。如果將第一條聲明改為sfr K0 = 0x80; 那么,如果要把單片機的P0口全部拉低,則不能寫P0=0x00;而應(yīng)保存后再在應(yīng)用程序中寫成K0=0x00;否則編譯器會提示“P0為未定義標(biāo)識符” 使用方法: sfr variabl
17、e = address /為變量分配一個特殊功能寄存器。 1 等號右邊,只能是十進制,十六進制整型的數(shù)據(jù)常量,不允許帶操作符的表達式 經(jīng)典的8051內(nèi)核支持的SFR地址從0x80H0xFF 飛利浦80C51MX系列0x180H0x1FF 2 SFR不能聲明于任何函數(shù)內(nèi)部,包括main函數(shù)。只能聲明于函數(shù)外。 3 用SFR聲明一個變量后,不能用取地址運算符&獲取其地址, 編譯無法通過,編譯器會提示非法操作。 4 有一點須特別注意,51內(nèi)核0x800xff,為特殊功能寄存器地址區(qū)間,但并不是所有的地址都有定義,如果說你所用的MCU芯片上對于某個地址沒有定義,那么用sfr在定義變量的時候,不要把變量
18、的地址分配到未定義的特殊功能寄存器上,雖然編譯時能通過,用KEIL仿真時貌似是沒有問題,但下載到芯片里運行時,是會出問題的。比如說,向一個未定義的特殊功能寄存器執(zhí)行讀操作,讀出來的就是一個未知的數(shù)。(讀者可自行測試,先把串口通信調(diào)通,然后做一個簡單的人機交互。讀出一個數(shù)后,再發(fā)給計算機,用串口調(diào)試助手或是串口監(jiān)控查看。這用方法在仿真的時候很有用。)所以具體那些特殊功能寄存器能夠用,就要查看你使用的芯片手冊。5 若遇到增強性的單片機,只要知道其擴展的特殊功能寄存器的地址,用SFR定就可以很方便進行編程。sbit: 聲明變量 sbit 同樣是聲明一個變量,和SFR 使用方法類似,但是SBIT是用來
19、聲明一個位變量,因為,在51系列的應(yīng)用中,非常有必要對SFR的單個位進行存取,而通過bit 數(shù)據(jù)類型,使其具備位尋址功能。 如,在reg52.h中有如下聲明 sfr IE = 0xA8; sbit EA = IE7;sbit ET2 = IE5; /8052 onlysbit ES = IE4;sbit ET1 = IE3;sbit EX1 = IE2;sbit ET0 = IE1;sbit EX0 = IE0; 所以,對EA的操作即是對IE最高位的操作。但如果想讓 SP DPL DPH PCON TMOC TL0 TL1 TH0 TH1 SBUF這些特殊功能寄存器具備位尋址,采用上述如IE類
20、似的定義,是不行的,雖然修改后,在編譯的時候不會出現(xiàn)錯誤,但只要用到你定義的位變量名時就會出錯。原因是,只有特殊功能寄存器的地址是8的倍數(shù)(十六進制以0或8結(jié)尾)才能進行位尋址。 打開reg52.h頭文件可以看到,所有用sbit聲明了的特殊功能寄存器的地址均是以0或8結(jié)尾如硬要達到上述要求,可用帶參的宏定義來完成。此處不做詳細說明(意義并不大)。下面對sbit的使用做詳細介紹:隨著8051的應(yīng)用,非常有必要對特殊功能寄存器的單個bit位進行存取,C51編譯器通過sbit 數(shù)據(jù)類型,提供了對特殊功能寄存器的位操作。 以下是sbit的三種應(yīng)用形式:一, sbit name = sfr-namebi
21、t-position; sfr PSW =0xD0; sfr IE =0xA8; sbit OV= PSW2; sbit CY=PSW7; sbit EA= IE7;二, sbit name= sft-addressbit-position; sbit OV =0xD02; sbit CY =0xD07; sbit EA =0xA87;三, sbit name= sbit-address; sbit OV =0xD2; sbit CY =0xD7; sbit EA =0xAF; 現(xiàn)對上述三種形式的聲明做必要的說明 第一種形式sbit name = sfr-namebit-position;如s
22、bit OV= PSW2; 當(dāng)中的這個特殊功能寄存器必須在此之前已經(jīng)用sfr 定義,否則編譯會出錯。bit-position范圍從07; 第二種形式 sbit name= sft-addressbit-position如sbit OV =0xD02; 與第一種形式不同之外在于,此處直接使用PSW的地址.第一種形式須先定義PSW 第三種形式. sbit name= sbit-address 如sbit OV =0xD2 是直接用的OV的地址OV的地址計算方式,是OV所在的寄存器地址加上OV的bit-position 注意: 不是所有的SFR都可位尋址。只有特殊功能寄存器的地址是8的倍數(shù)(十六進制
23、以0或8結(jié)尾)才能進行位尋址,并且sbit聲明的變量名,雖可以是任意取,但是最好不要以下劃線開頭,因為以下劃線開頭的都保留給了C51的頭文件做保留字。 sfr16: 聲明變量 許多8051的派生型單片機,用兩個連續(xù)地址的特殊功能寄存器,來存儲一個16bit的值。例如,8052就用了0xCC和0xCD來保存定時/計數(shù)寄存器2的高字節(jié)和低字節(jié)。編譯器提供sfr16這種數(shù)據(jù)類型,來保存兩個字節(jié)的數(shù)據(jù)。虛擬出一個16bit的寄存器。 如下: sfr16 T2 = 0xCC 存儲方面為小端存儲方式,低字節(jié)在前,高字節(jié)在后。定義時,只寫低字節(jié)地址,如上,則定義T2為一個16位的特殊功能寄存器。 T2L=
24、0CCh, T2H= 0CDh 使用方法: sfr variable = low_address 1 等號右邊,只寫兩個特殊功能寄存器的低地址,且只能是十進制,十六進制的整型數(shù)據(jù)常量,不允許帶操作符的表達式 2 SFR不能聲明于任何函數(shù)內(nèi)部,包括main函數(shù)。只能聲明于函數(shù)外。 3 用SFR聲明一個變量后,不能用取地址運算符&獲取其地址, 編譯無法通過,編譯器會提示非法操作。 4 當(dāng)你向一個sfr16寫入數(shù)據(jù)的時候,KEIL CX51 編譯器生成的代碼,是先寫高字節(jié),后寫低字節(jié),(可通過返匯編窗口查看)在有些情況下,這并非我們所想要的操作順序。使用時,須注意。 5 當(dāng)你所要寫入sfr16的數(shù)據(jù)
25、,當(dāng)是高字節(jié)先寫還是低字節(jié)先寫非常重要的時候,就只能用sfr 這個關(guān)鍵字來定義,并且任意時刻只保存一個字節(jié),這樣操作才能保證寫入正確。三, 淺淡變量類型及其作用域 變量可分為 1.局部變量 (按變量的有效作用范圍劃分) 2.全局變量 1.局部變量 是指函數(shù)內(nèi)部(包括main函數(shù))定義的變量,僅在定義它的那個函數(shù)范圍內(nèi)有效,不同函數(shù)可使用相同的局部變量名,函數(shù)的形式參數(shù)也屬于局部變量,在一個函數(shù)的內(nèi)部復(fù)合語句中也可以定義局部變量,該局部變量只在該復(fù)合語合中有效。 2.全局變量 是指函數(shù)外部定義的變量,以稱外部變量。可為多個函數(shù)共同使用,其有效作用范圍是從它定義開始到整個程序文件結(jié)束。如果全局變量
26、,定義在一個程序文件的開始處,則在整個程序文件范圍都可以使用它,如果一個全局變量不是在程序文件的開始處定義,但又希望在它定義之前的函數(shù)中引用該變量,這時應(yīng)在引用該變量的函數(shù)中用關(guān)鍵字extern將其聲明為“外部變量”。另個,如果在一個程序模塊文件中引用另一個程序模塊文件中定義的變量時,也必須用extern進行說明。 外部變量的說明與外部變量的定義是不同的,外部變量定義只能有一次,定義的位置在所有函數(shù)之外,而同一個程序文件中(不是指模塊文件)的外部變量聲明可以有多次,聲明的置在需要引用該變量的函數(shù)之內(nèi),外部變量的聲明的作用只是聲明該變量是一個已經(jīng)在外部定義過了的變量而已。 如在同一個程序文件中,
27、全局變量與局部變量同名,則在局部變量的有效作用范圍之內(nèi),全局變量不起作用,也就是說,局部變量的優(yōu)先級比全局變量高。 在編寫C語言程序時,不是特別必要的地方一般不要使用全局變量,而應(yīng)當(dāng)盡可能的使用局部變量。因為局部變量只在使用它的時候,才為其分配內(nèi)存單元,而全局變量在整個程序的執(zhí)行過程中都要占用內(nèi)存單元,且當(dāng)全局變量使用過多時,會降低程序的可讀性。 變量的存儲種類 1自動變量(auto) 定義變量時,在變量類型名前加上 “auto” ,自動變量是C語言中使用最為廣泛的一類變量,在函數(shù)體內(nèi)部或是復(fù)合語句內(nèi)部定義的變量,如果省略了存儲種類說明,則該變量默認為自動變量。 例如: 等價于 char x;
28、 auto char x; int y; auto int y; 注: 自動變量的作用范圍在定義它的函數(shù)體或是復(fù)合語句內(nèi)部,只有在定義它的函數(shù)內(nèi)被調(diào)用,或是定義它的復(fù)合語句被執(zhí)行時,編譯器才會為其分配內(nèi)存空間,開始其生存期。當(dāng)函數(shù)調(diào)用結(jié)束返回,或復(fù)合語句執(zhí)行結(jié)束,自動變量所占用的內(nèi)存空間就被釋放,變量的值當(dāng)然也就不復(fù)存在,其生存期結(jié)束。當(dāng)函數(shù)再次調(diào)用,或是復(fù)合語句被再次執(zhí)行時,編譯器又會為其內(nèi)部的自動變量重新分配內(nèi)存空間。但不會保留上一次運行的值。而必須被重新分配。因此自動變量始終是相對于函數(shù)或復(fù)合語句的局部變量。2 外部變量(extern) 用說明符“extern”定義的變量稱為外部變量。按
29、缺省規(guī)則,凡是在所有函數(shù)之前,在函數(shù)外部定義的變量都是外部變量,定義時可以不寫extern說明符,但是一個函數(shù)體內(nèi)說明一個已在該函數(shù)體外或別的程序模塊文件中定義過的外部變量時,剛必須要使用extern說明符。外部變量定義后,它就被分配了固定的內(nèi)存空間。外部變量的生存期為程序的整個執(zhí)行時間。 外部變量的存儲不會隨函數(shù)或復(fù)合語句執(zhí)行完畢而釋放,因此外部變量屬于全局變量。 C語言允許將大型程序分解為若干個獨立的程序模塊文件,各個模塊可分別進行編譯,然后再將它們連接在一起,如果某個變量需要在所有程序模塊文件中使用,只要在一個程序模塊文件中將該變量定義成全局變量,而在其它程序模塊文件中用extern聲明
30、該變量是已被定義過的外部變量就可以了。 函數(shù)是可以相互調(diào)用的,定義函數(shù)時,如果冠以關(guān)鍵字extern 即將其明確定義為一個外部函數(shù)。例如 extern int func2(char a,b) 。如果在定義函數(shù)時省略關(guān)鍵字extern,則隱含為外部函數(shù)。如果在調(diào)用一個在本程序模塊文件以外的其它模塊文件所定義的函數(shù),則必須要用關(guān)鍵字extern說明被調(diào)用的函數(shù)是一個外部函數(shù)。對于具有外部函數(shù)相互調(diào)用的多模塊程序,可用C51編譯器分別對各個模塊文件進行編譯,最后再用L51連接定位器將它們連接成為一個完整的程序。如下為一個多模塊程序程序模塊1,文件名為file1.c#include int x=5;v
31、oid main() extern void fun1( ); extern viod fun2(int y); fun1( ); fun1( ); fun1( );printf( “n%d %dn”,x,fun2(x);程序模塊2,文件名為file2.c#includeextern int x;void fun1( ) static int a=5; /靜態(tài)變量只在第一次調(diào)用函數(shù)時賦值,退出函數(shù)時/會保留上次的值,下次調(diào)用不再重新賦值。 int b=5;printf(“%d %d %d |”,a,b,x);a-=2;b-=2x-=2;printf(“%d %d %d |”,a,b,x);in
32、t fun2(int y) return(35*x*y);程序執(zhí)行如果如下: 5 5 5 | 3 3 3 3 5 3 | 1 3 1 1 5 1 | -1 3 1 -1 35注: C語言不允許在一個函數(shù)內(nèi)嵌套定義另一個函數(shù)。為了能夠訪問不同文件中各個函數(shù)的變量,除了可以采用參數(shù)傳遞的方法外,還可以采用外部變量的方法,上面的例子就說了這一點。不過,盡管使用外部變量在不同函數(shù)之間傳遞數(shù)據(jù)有時比使用函數(shù)參數(shù)傳遞更為方便,不過當(dāng)外部變量過多時,會增加程序的調(diào)試排錯的困難。使得程序不便于維護。別外不通過參數(shù)傳遞直接在函數(shù)中改變?nèi)肿兞康闹担袝r還會發(fā)生一些意想不到的副作用。因些最好還是使用函數(shù)參數(shù)來傳遞
33、數(shù)據(jù)。3寄存器變量(register) 為了提高程序的執(zhí)行效率,C語言允許將一些頻率最高的那些變量,定義為能夠直接使用硬件寄存器的所謂的寄存器變量。定義一個變量時,在變量類型名前冠以“register” 即將該變量定義成為了寄存器變量。寄存器變量可以認為是一自動變量的一種。有效作用范圍也自動變量相同。由于計算機寄存器中寄存器是有限的。不能將所有變量都定義成為寄存器變量,通常在程序中定義寄存器變量時,只是給編譯器一個建議,該變量是否真正成為寄存器變量,要由編譯器根據(jù)實際情況來確定。另一方面,C51編譯器能夠識別程序中使用頻率最高的變量,在可能的情況下,即使程序中并未將該變量定義為寄存器變量,編譯
34、器也會自動將其作為寄存器變量處理。被定義的變量是否真正能成為寄存器變量,最終是由編譯器決定的。4靜態(tài)變量(static)使用存儲種類說明符“static”定義的變量為靜態(tài)變量,在上面模塊2程序文件中使用了一個靜態(tài)變量:static int a =5 ;由于這個變量是在函數(shù)fun1( )內(nèi)部定義,因此稱為內(nèi)部靜態(tài)變量或局部靜態(tài)變量。局部靜態(tài)變量始終都是存在的,但只有在定義它的函數(shù)內(nèi)部進行訪問,退出函數(shù)之后,變量的值仍然保持,但不能進行訪問。還有一種全局靜態(tài)變量,它是在函數(shù)外部被定義的。作用范圍從它的定義點開始,一直到程序結(jié)束,當(dāng)一個C語言程序由若干個模塊文件所組成時,全局靜態(tài)變量始終存在,但它只
35、能在被定義的模塊文件中訪問,其數(shù)據(jù)值可為該模塊文件內(nèi)的所有函數(shù)共享,退出該文件后,雖然變量的值仍然保持著,但不能被其它模塊文件訪問。在一個較大的程序中,這就方便了多人設(shè)計時,各自寫的程序模塊不會被別的模塊文件所引用。 全局靜態(tài)變量和單純的全局變量,在編譯時就已經(jīng)為期分配了固定的內(nèi)存空間,只是他們的作用范圍不同而已。 局部靜態(tài)變量是一種在兩次函數(shù)調(diào)用之間仍能保持其值的局部變量。 如下,局部變量的使用計算度輸出15的階乘值。 #include int fac( int n) static int f=1;f=f*n;return(f); main( ) int i; for(i=1;i=5;i+)
36、 printf(“%d!=%dn”,i,fac(i); 程序執(zhí)行結(jié)果 1!=1 2!=2 3!=6 4!=24 5!=120 注: 在這個程序中一共調(diào)用了5次計算階乘的函數(shù)fac(i),每次調(diào)用后輸出一個階乘值i!,同時保留了這個i!值,以便下次再乘(i+1).由此可見,如果要保留函數(shù)上一次調(diào)用結(jié)束時的值,或是在初始化之后變量只被引用而不改變其值,則這時使用局部靜態(tài)變量;較為方便,以免在每調(diào)用時都要重新進行賦值,但是,使用局部靜態(tài)變量需要占用較多的內(nèi)存空間,而且降低了程序的可讀性,因此并不建議多用局部靜態(tài)變量。 靜態(tài)函數(shù): 對于函數(shù)也可以定義成為具為靜態(tài)存儲種類的屬性,定義函數(shù)時在函數(shù)名前冠以
37、關(guān)鍵字static即將其定義為一個靜態(tài)函數(shù)。例如static int func1(char x, y)函數(shù)是外部型的,使用靜態(tài)函數(shù)可以使該函數(shù)只局限于當(dāng)前定義它的模塊文件中。其它模塊文件是不能調(diào)用它的。換名話說,就是在其它模塊文件中可以定義與靜態(tài)函數(shù)完全同名的另一個函數(shù)。不會因為程序中存在相同的函數(shù)名而發(fā)生函數(shù)調(diào)用時的混亂。 這一點對于進行模塊化程序設(shè)計是很有用的。四, C51常用頭文件在KEIL 中,對于單片機所使用的頭文件,除了reg51 reg52以外,還有一些從各芯片制商的官網(wǎng)下載與reg51,reg52功能類似的頭文件,需了解透外,還要對各類型單片機均可通用且相當(dāng)有用的的頭文件,做相
38、應(yīng)的了解。因為,內(nèi)部所包含的函數(shù)與宏定義,可以及大的方便我們編寫應(yīng)用程序。1字符函數(shù) ctype.h 1 extern bit isalpha(char); 功能:檢查參數(shù)字符是否為英文字母,是則返回12 extern bit isalnum(char) 功能:檢查字符是否為英文字母或數(shù)字字符,是則返回13 extern bit iscntrl(char) 功能:檢查參數(shù)值是否在0x000x1f 之間或等于0x7f,是則返回14 extern bit isdigit(char) 功能: 檢查參數(shù)是否為數(shù)字字符,是則返回15 extern bit isgraph(char) 功能: 檢查參數(shù)值是
39、否為可打印字符,是則返回1,可打印字符為0x210x7e6 extern bit isprint(char) 功能:除了與isgraph相同之外,還接受空格符0x207 extern bit ispunct(char) 功能:不做介紹。8 extern bit islower(char) 功能:檢查參數(shù)字符的值是否為小寫英文字母,是則返回19 extern bit isupper(char) 功能:檢查參數(shù)字符的值是否為大寫英文字母,是則返回110 extern bit isspace(char) 功能:檢查字符是否為下列之一,空格,制表符,回車,換行,垂直制表符和送紙。如果為真則返回111
40、extern bit isxdigit(char) 功能:檢查參數(shù)字符是否為16進制數(shù)字字符,是則返回112 extern char toint(char) 功能:將ASCII字符09 af(大小寫無關(guān))轉(zhuǎn)換成對應(yīng)的16進制數(shù)字,返回值00H0FH13 extern char tolower(char) 功能:將大寫字符轉(zhuǎn)換成小寫形式,如字符變量不在AZ之間,則不作轉(zhuǎn)換而直接返回該字符14 extern char toupper(char) 功能:將小寫字符轉(zhuǎn)換成大寫形式,如字符變量不在az之間,則不作轉(zhuǎn)換而直接返回該字符15 define toascii(c) (c)&0x7f)功能:該宏將
41、任何整形數(shù)值縮小到有效的ASCII范圍之內(nèi),它將變量和0x7f相與從而去掉第7位以上的所有數(shù)位16 #define tolower(c) (c-A+a)功能:該宏將字符與常數(shù)0x20 逐位相或17 #define toupper(c) (c)-a+A)功能:該宏將字符與常數(shù)0xdf 逐位相與2數(shù)學(xué)函數(shù) math.hextern int abs (int val);extern char cabs (char val);extern long labs (long val);extern float fabs (float val);功能:返回絕對值。上面四個函數(shù),除了形參和返回值不一樣之外,其
42、它功能完全相同。extern float exp (float val);extern float log (float val);extern float log10 (float val); 功能: exp 返回eval log 返回 val 的自然對數(shù) log10 返回 以10為底,val的對數(shù) extern float sqrt (float val); 功能: 返回val的正平方根 extern int rand(); extern void srand(int n); 功能: rand返回一個0到32767之間的偽隨機數(shù),srand用來將隨機數(shù)發(fā)生器初始化成一個已知的(期望)值。
43、Keil uVision3中的math.h庫中,不包含此函數(shù)。 extern float sin (float val);extern float cos (float val);extern float tan (float val); 功能: 返回val的正弦,余弦,正切值。val為弧度 fabs(var) =65535extern float asin (float val);extern float acos (float val);extern float atan (float val);extern float atan2 (float y, float x); 功能: asin
44、 返回val的反正弦值。acos 返回val的反余弦值。 atan 返回val的反正切值。 asin atan acos的值域均為 -/2+/2 atan2返回x/y,的反正切值,其值域為-+extern float sinh (float val);extern float cosh (float val);extern float tanh (float val); 功能:cosh返回var的雙曲余弦值,sinh返回var的雙曲正弦值, tanh返回var的雙曲正切值。extern float ceil (float val); 功能: 向上取整,返回一個大于val的最小整數(shù)。extern
45、 float floor (float val); 功能: 向下取整,返回一個小于val的最大整數(shù)。extern float pow (float x, float y); 功能: 計算計算xy的值。當(dāng)(x=0,y=0)或(x0.y不是整數(shù))時會發(fā)生錯誤。extern void fpsave(struct FPBUF *p)extern void fprestore(struct FPBUF *p) 功能:fpsave 保存浮點了程序的狀態(tài),fprestore恢復(fù)浮點子程序的原始狀態(tài),當(dāng)中斷程序中需要執(zhí)行浮點運算時,這兩個函數(shù)是很有用的。 注: Keil uVision3中的math.h庫中,
46、不包含此函數(shù)。3絕對地址訪問 absacc.h#define CBYTE (unsigned char volatile code *) 0)#define DBYTE (unsigned char volatile data *) 0)#define PBYTE (unsigned char volatile pdata *) 0)#define XBYTE (unsigned char volatile xdata *) 0) 功能:CBYTE 尋址 CODE區(qū) DBYTE 尋址 DATA區(qū) PBYTE 尋址 XDATA(低256)區(qū) XBYTE 尋址 XDATA區(qū) 例: 如下指令在對外部
47、存儲器區(qū)域訪問地址0x1000 xvar=XBYTE0x1000; XBYTE0x1000=20;#define CWORD (unsigned int volatile code *) 0)#define DWORD (unsigned int volatile data *) 0)#define PWORD (unsigned int volatile pdata *) 0)#define XWORD (unsigned int volatile xdata *) 0) 功能:與前面的一個宏相似,只是它們指定的數(shù)據(jù)類型為unsigned int .。 通過靈活運用不同的數(shù)據(jù)類型,所有的80
48、51地址空間都是可以進行訪問。 如DWORD0x0004=0x12F8;即內(nèi)部數(shù)據(jù)存儲器中(0x08)=0x12; (0x09)=0xF84 內(nèi)部函數(shù) intrins.h extern unsigned char _cror_ (unsigned char var, unsigned char n);extern unsigned int _iror_ (unsigned int var, unsigned char n);extern unsigned long _lror_ (unsigned long var, unsigned char n); 功能:將變量var 循環(huán)右移 n 位。上三個函數(shù)的區(qū)別在于,參數(shù)及返回值的類型不同extern unsigned char _crol_ (unsigned char var, unsigned char n);extern unsigned int _irol_ (unsigned int var, unsigned char n);extern unsigned long _lrol_ (unsigned long var, unsigned
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 海南省三亞市(2024年-2025年小學(xué)六年級語文)部編版課后作業(yè)(上學(xué)期)試卷及答案
- 陜西省咸陽市(2024年-2025年小學(xué)六年級語文)統(tǒng)編版階段練習(xí)(上學(xué)期)試卷及答案
- 貴州盛華職業(yè)學(xué)院《化學(xué)分析實驗》2023-2024學(xué)年第一學(xué)期期末試卷
- 貴州黔南經(jīng)濟學(xué)院《自動化學(xué)科前沿》2023-2024學(xué)年第一學(xué)期期末試卷
- 新疆塔城地區(qū)(2024年-2025年小學(xué)六年級語文)部編版開學(xué)考試(下學(xué)期)試卷及答案
- Unit 8 Section A 3a-3c 英文版說課稿 2024-2025學(xué)年人教版八年級英語下冊
- 新疆克拉瑪依市(2024年-2025年小學(xué)六年級語文)部編版小升初真題((上下)學(xué)期)試卷及答案
- 貴州民族大學(xué)《室內(nèi)設(shè)計(實踐)》2023-2024學(xué)年第一學(xué)期期末試卷
- 貴州民用航空職業(yè)學(xué)院《空間構(gòu)成與表現(xiàn)》2023-2024學(xué)年第一學(xué)期期末試卷
- 貴州警察學(xué)院《醫(yī)學(xué)統(tǒng)計學(xué)實驗》2023-2024學(xué)年第一學(xué)期期末試卷
- GB/T 40537-2021航天產(chǎn)品裕度設(shè)計指南
- 政協(xié)個人簡歷模板12篇
- 木工工具及使用方法課件
- 節(jié)能減排獎懲制度(5篇)
- 部編六年級語文上冊 讀音易錯字
- 全國醫(yī)學(xué)博士英語統(tǒng)一考試詞匯表(10000詞全) - 打印版
- COPD(慢性阻塞性肺病)診治指南(2023年中文版)
- 氣相色譜儀作業(yè)指導(dǎo)書
- ?中醫(yī)院醫(yī)院等級復(fù)評實施方案
- 跨高速橋梁施工保通專項方案
- 鐵路貨車主要輪對型式和基本尺寸
評論
0/150
提交評論