版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第2章 Keil C51程序設(shè)計基礎(chǔ)單片機原理及應(yīng)用系統(tǒng)設(shè)計主要內(nèi)容1、Keil C51系統(tǒng)概述2、Keil C51軟件開發(fā)結(jié)構(gòu)3、Keil C51與標準C4、運算符與表達式5、C51程序的基本語句6、Keil C51指針7、Keil C51函數(shù)8、C51代碼優(yōu)化及庫函數(shù)9、C51程序結(jié)構(gòu)及應(yīng)用要點10、Keil C51高級編程 Keil C51是一種專門為8051核的單片機設(shè)計的高級語言C編譯器,支持符合ANSI標準的C語言,并針對8051核單片機作了一些特殊擴展。本章主要介紹C51的基本知識,希望讀者能盡快掌握C51的編程技術(shù)。Keil C51介紹 Keil C51是美國Keil Soft
2、ware公司出品的51系列兼容單片機C語言軟件開發(fā)系統(tǒng),與匯編相比,C語言在功能上、結(jié)構(gòu)性、可讀性、可維護性上有明顯的優(yōu)勢,因而易學(xué)易用。用過匯編語言后再使用C來開發(fā),體會更加深刻。 Keil C51軟件提供豐富的庫函數(shù)和功能強大的集成開發(fā)調(diào)試工具,全Windows界面。另外重要的一點,只要看一下編譯后生成的匯編代碼,就能體會到Keil C51生成的目標代碼效率非常之高,多數(shù)語句生成的匯編代碼很緊湊,容易理解。在開發(fā)大型軟件時更能體現(xiàn)高級語言的優(yōu)勢。2.1 Keil C51系統(tǒng)概述2.2 Keil C51軟件開發(fā)結(jié)構(gòu)圖2-1 Keil C51軟件開發(fā)結(jié)構(gòu)框圖(1)uVision與Ishell分
3、別是C51 for Windows和for Dos的集成開發(fā)環(huán)境(IDE),可以完成編輯、編譯、連接、調(diào)試、仿真等整個開發(fā)流程(開發(fā)人員可用IDE本身或其它編輯器編輯C或匯編源文件)。(2)然后分別由C51及A51編譯器編譯生成目標文件(OBJ)。 (3)目標文件可由LIB51創(chuàng)建生成庫文件,也可以與庫文件一起經(jīng)L51連接定位生成絕對目標文件(ABS)。(4)ABS文件由OH51轉(zhuǎn)換成標準的Hex文件,以供調(diào)試器dScope51或tScope51使用進行源代碼級調(diào)試,也可由仿真器使用直接對目標板進行調(diào)試,也可以直接寫入程序存貯器如EPROM中。在Keil C 語言的軟件包中,包含下列文件:(1
4、)C51編譯器Keil C51編譯器是一個針對80C51系列MCU的基于ANSI C標準的C編譯器,生成的可執(zhí)行代碼快速、緊湊,在運行效率和速度上可以和匯編程序得到的代碼相媲美。(2)A51宏匯編器A51宏匯編器是一個8051核的系列MCU的宏匯編器,支持8051及其派生系列的全部指令集。它把匯編語言匯編成機器代碼。該匯編器允許定義程序中的每一個指令,在需要極快的運行速度,很小代碼空間及精確的硬件控制等場合時使用。A51宏匯編器的宏特性讓公共代碼只需要開發(fā)一次,節(jié)約了開發(fā)和維護的時間。A51匯編器將源程序匯編成可重定位的目標代碼,并產(chǎn)生一個列表文件。其中可以包含也可以不包含字符表及交叉信息。(
5、3)BL51連接/定位器BL51連接/定位器是具有代碼分段功能的連接/定位器,利用從庫中提取的目標模塊和由編譯器或匯編器生成的一個或多個目標模塊處理外部和全局數(shù)據(jù),并將可重定位的段分配到固定的地址上。所產(chǎn)生的一個絕對地址目標模塊或文件包含不可重定位的代碼和數(shù)據(jù),所有的代碼和數(shù)據(jù)被安置在固定的存儲器單元中。該絕對地址目標文件可以: 寫入EPROM或其他存儲器件。 由Vision5調(diào)試器使用來模擬和調(diào)試。 由仿真器用來測試程序。(4)LIB51庫管理器LIB51庫管理器讓你建立和維護庫文件。庫文件是格式化的目標模塊(由編譯器或匯編器產(chǎn)生)的集合。庫文件提供了一個方便的方法來組合及使用大量的連接程序
6、可能用到的目標模塊。C51編譯器與ANSIC相比,擴展的內(nèi)容包括數(shù)據(jù)類型、存儲器類型、存儲模式、指針及函數(shù)(包括定義函數(shù)的重入性、指定函數(shù)的寄存器組、指定函數(shù)的存儲模式及定義中斷服務(wù)程序)。2.3 Keil C51與標準C語言深入理解并應(yīng)用C51對標準ANSIC的擴展是學(xué)習(xí)C51的關(guān)鍵之一。因為大多數(shù)擴展功能都是直接針對8051內(nèi)核的系列CPU硬件。大致有以下8類: 8051存儲類型及存儲區(qū)域 存儲模式 存儲器類型聲明 變量類型聲明 位變量與位尋址 特殊功能寄存器(SFR) C51指針 函數(shù)屬性2.3.1 Keil C51擴展關(guān)鍵字C51 V4.0版本有以下擴展關(guān)鍵字(共19個):_at_ _
7、task_ data bdata idataxdata pdata sfr sfr16 alien interrupt small compact large code bit sbit using reentrant 2.3.2 內(nèi)存區(qū)域1. 程序區(qū)域 由Code說明可有多達64kBytes的程序存儲器。2. 內(nèi)部數(shù)據(jù)存儲 內(nèi)部數(shù)據(jù)存儲器可用以下關(guān)鍵字說明: data:直接尋址區(qū)(00H7FH),為內(nèi)部RAM的低128字節(jié)。 idata:間接尋址區(qū)(00HFFH),包括整個內(nèi)部RAM區(qū)。 bdata:可位尋址區(qū)(20H2FH) 3. 外部數(shù)據(jù)存儲外部RAM視使用情況可由以下關(guān)鍵字標識:xda
8、ta:可指定多達64KB的外部直接尋址區(qū),地址范圍0000H 0FFFFHpdata:能訪問1頁(25bBytes)的外部RAM,主要用于緊湊模式(Compact Model)。4. 特殊功能寄存器存儲 8051提供128Bytes的SFR尋址區(qū),這區(qū)域可位尋址、字節(jié)尋址或 字尋址,用以控制定時器、計數(shù)器、串口、I/O及其它部件,可由以下幾種關(guān)鍵字說明:sfr:字節(jié)尋址 比如 sfr P0=0 x80;為PO口地址為80H,“”后HFFH之間的常數(shù)。sfr16:字尋址,如sfr16 T2=0 xcc;指定Timer2口地址T2L=0 xcc T2H=0 xCDsbit:位尋址,如sbit EA
9、=0 xAF;指定第0 xAF位為EA即中斷允許。還可以有如下定義方法: sbit OV=PSW2;(定義0V為PSW的第2位) sbit OV0XDO2;(同上) 或bit OV-0 xD2。(同上) 2.3.3 存儲模式 存儲模式指定了默認的存儲器類型,該類型應(yīng)用于函數(shù)參數(shù)、局部變量和定義時未包含存儲器類型的變量。存儲模式?jīng)Q定了沒有明確指定存儲類型的變量,函數(shù)參數(shù)等的缺省存儲區(qū)域,共三種:1. Small模式 在此模式下所有缺省變量參數(shù)均裝入內(nèi)部RAM,優(yōu)點是訪問速度快,缺點是空間有限,只適用于小程序。2. Compact模式 所有缺省變量均位于外部RAM區(qū)的一頁(256Bytes),具體
10、哪一頁可由P2口指定,在STARTUP.A51文件中說明,也可用pdata指定,優(yōu)點是空間較Small為寬裕速度較Small慢,較large要快,是一種中間狀態(tài)。3. large模式 所有缺省變量可放在多達64KB的外部RAM區(qū),優(yōu)點是空間大,可存變量多,缺點是速度較慢。該模式采用數(shù)據(jù)指針DPTR來尋址,訪問的效率很低?!緜渥ⅰ浚?)存儲模式在C51編譯器選項中選擇; (2)盡可能使用小模式,它產(chǎn)生速度快、效率高的代碼。2.3.4 存儲類型聲明變量或參數(shù)的存儲類型可由存儲模式指定缺省類型,也可由關(guān)鍵字直接聲明指定。各類型分別用:code,data,idata,xdata,pdata說明。例:
11、data uar1 char code array “hello!”; unsigned char xdata arr1044;2.3.5 變量或數(shù)據(jù)類型 C51提供以下幾種擴展數(shù)據(jù)類型:(1)特殊功能寄存器sfr sfr用于聲明字節(jié)型(8位)特殊功能寄存器; sfr16用于聲明字型(16位)特殊功能寄存器。 sfr是sfr字節(jié)地址,其取值范圍是0255。 sfr16是sfr字地址,其取值范圍是065535。(2)位型bit和sbit bit是定義位變量數(shù)據(jù)類型,其取值為0或1。用于定義定位在內(nèi)部RAM的20H2FH單元的位變量,位地址范圍是007FH,編譯器對位地址進行自動分配。 sbit是
12、聲明位變量的數(shù)量類型,其取值為0或1。用于聲明定位在sfr區(qū)域的位變量(或位尋址區(qū)變量的某確定位),編譯器不自動分配位地址。使用時需要注意二者的區(qū)別,例如: bit flag = 0; / 定義flag,位地址由編譯器007FH范圍分配,并賦初始值0 sbit var = 0 xe6; / 聲明位變量var的位地址為0 xe6,“=”含義是聲明,不表示賦值。 其余數(shù)據(jù)類型如:char,short,int,long,float等與ANSI C相同,如表2-1所示。數(shù)據(jù)類型位數(shù)取值范圍標準C數(shù)據(jù)類型字符型signed8-128 127unsigned80 255整型signed16-32768 3
13、2767unsigned160 65535長整型signed32-21474883648 21474883647unsigned320 4294967295浮點型float321.75494E-38 3.402823E+38C51擴展數(shù)據(jù)類型SFR型sfr80 255sfr16160 65535位型bit10,1sbit10,1表2-1 C51常用數(shù)據(jù)類型2.3.6 位變量與聲明 1. bit型變量 bit型變量可用變量類型,函數(shù)聲明、函數(shù)返回值等,存貯于內(nèi)部RAM的20H2FH。注意: (1) 用pragma disable說明函數(shù)和用“usign”指定的函數(shù),不 能返回bit值。 (2)
14、一個bit變量不能聲明為指針,如bit *ptr;錯誤。 (3) 不能有bit數(shù)組如:bit arr5;錯誤。2. 可位尋址區(qū)說明20H2FH可作如下定義: int bdata i ; char bdata arr3;然后: sbit bit15 = I15; sbit arr07 = arr07; sbit arr15 = arri7;2.4 運算符與表達式 Keil C51對數(shù)據(jù)有極強的表達能力,具有十分豐富的運算符,運算符就完成某種特定運算的符號,表達式則是由運算符及運算對象所組成的具有特定含義的一個式子。在任意一個表達式的后面加一個分號“:”就構(gòu)成了一個表達式語句。由運算符和表達式可以
15、組成C51程序的各種語句。 運算符按其在表達式中所起的作用,可分為賦值運算符、算術(shù)運算符、增量與減量運算符、關(guān)系運算符、邏輯運算符、位運算符、復(fù)合賦值運算符、逗號運算符、條件運算符、指針和地址運算符、強制類型轉(zhuǎn)換運算符。2.4.1 賦值運算符 在C語言程序中,符號“=”稱為賦值運算符,它的作用是將一個數(shù)據(jù)的值賦給一個變量,利用賦值運算符將一個變量與一個表達式連接起來的式子稱為賦值表達式,在賦值表達式的后面加一個分號“;”便構(gòu)成了賦值語句,賦值語句的格式如下: 變量 = 表達式;該語句的意義是先計算出右邊的表達式的值,然后將該值賦給左邊的變量。上式中的“表達式”還可以是一個賦值表達式,即C語言允
16、許進行多重賦值。例如: x=9; /*將常數(shù)9賦給變量x*/ x=y=8; /*將常數(shù)8同時賦給變量x和y*/ 在使用賦值運算符“=”應(yīng)注意不要與關(guān)系運算符“=”相混淆。2.4.2 算術(shù)運算符C語言中的算術(shù)運算符有:+(加或取正值)運算符、(減或取負值)運算符、*(乘)運算符、/(除)運算符、%(取余)運算符。這些運算符中對于加、減和乘法符合一般的運算規(guī)則,除法有所不同:如果是兩個整數(shù)相除,其結(jié)果為整數(shù),舍去小數(shù)部分;如果兩個浮點數(shù)相除,其結(jié)果為浮點數(shù)。取余運算要求兩個運算對象均為整型數(shù)據(jù)。算術(shù)運算符將運算對象連接起來的式子即為算術(shù)表達式。算術(shù)運算的一般形式為:表達式1 算術(shù)運算符 表達式2例
17、如:x+y/(a-b),(a+b)*(x-y)都是合法的算術(shù)表達式。 在求一個算術(shù)表達式的值時,要按運算符的優(yōu)先級別進行。 算術(shù)運算符中取負值(-)的優(yōu)先級最高,其次是乘法(*)、除法(/)和取余(%)運算符,加法(+)和減法()運算符的優(yōu)先級最低。 需要時可在算術(shù)表達式中采用圓括號來改變運算符的優(yōu)先級,括號的優(yōu)先級最高。2.4.3 增量與減量運算符 C語言中除了基本的加、減、乘、除運算之外,還提供兩種特殊的運算符:+(增量)運算符和-(減量)運算符。 增量和減量是C51中特有一種運算符,它們的作用分別是對運算對象做加1和減1運算。例如: +i,i+,-j,j-等。 增量運算符和減量運算符只能
18、用于變量,不能用于常數(shù)或表達式,在使用中要注意運算符的位置。例如,+i與i+的意義完全不同,前者為在使用i之前先對i的值加1,而后者則是在使用i之后再對i的值加1。2.4.4 關(guān)系運算符 C語言中有6中關(guān)系運算符:(大于)、=(大于等于)、y,x+yz,(x=3)(y=4)都是合法的關(guān)系表達式。 關(guān)系運算符通常用來判別某個條件是否滿足,關(guān)系運算的結(jié)果只有0和1兩種值。當(dāng)所指定的條件滿足時結(jié)果為1,條件不滿足時結(jié)果為0。2.4.5 邏輯運算符 C語言中有3種邏輯運算符:|(邏輯或)、&(邏輯與)、?。ㄟ壿嫹牵?。邏輯運算符用來求某個條件式的邏輯值,用邏輯運算符將關(guān)系表達式或邏輯量連接起來就是邏輯表
19、達式。邏輯運算的一般形式為:邏輯與 條件式1 & 條件式2邏輯或 條件式1 | 條件式2邏輯非 !條件式 例如:x&y, a|b, !z都是合法的邏輯表達式。 進行邏輯與運算時,首先對條件式1進行判斷,如果結(jié)果為真(非0值),則繼續(xù)對條件式2進行判斷,當(dāng)結(jié)果也為真時,表示邏輯運算結(jié)果為真(值為1);反之,如果條件式1的結(jié)果為假,則不再判斷條件式2,而直接給出邏輯運算的結(jié)果為假(值為0)。 進行邏輯或運算時,只要兩個條件式中有一個為真,邏輯運算的結(jié)果便為真(值為1),只有當(dāng)條件式1和條件式2均不成立時,邏輯運算的結(jié)果才為假(值為0)。 進行邏輯非運算時,對條件式的邏輯值直接取反。 與關(guān)系運算符類
20、似,邏輯運算符通常用來判別某個邏輯條件是否滿足,邏輯運算的結(jié)果只有0和1兩種值。 上面幾種運算符的優(yōu)先級為(由高至低):邏輯非算術(shù)運算符關(guān)系運算符邏輯與邏輯或。2.4.6 位運算符 C能對運算對象進行按位操作是C語言的一大特點,使之能對計算機的硬件直接進行操作、語言中共有6種位運算符:(按位取反)(左移) (右移)&(按位與) 位異或 )|(按位或)位運算的一般形式如下:變量1 位運算符 變量2 位運算符的作用是按位對變量進行運算,并不改變參與運算的變量的值。若希望按位改變變量的值,則應(yīng)采用相應(yīng)的賦值運算。另外位運算符不能用來對浮點型數(shù)據(jù)進行操作,例如,先用賦值語句a=0 xEA;將變量a賦值
21、為0 xEA,接著對變量a進行移位操作a2,其結(jié)果是將十六進制數(shù)0 xEA左移2位,移空的2位補0,移出的2位丟棄,移位的結(jié)果為0 xa8,而變量a的值在執(zhí)行后仍為0 xEA。如果希望變量a在執(zhí)行之后為移位操作的結(jié)果,則應(yīng)采用語句為:a=a2。 位運算符的優(yōu)先級從高到低依次是:按位取反()左移()按位與(&)按位異或()按位或(|)。2.4.7 復(fù)合賦值運算符 在賦值運算符“=”的前面加上其他運算符,就構(gòu)成了所謂復(fù)合賦值運算符,C語言中共有10種賦值復(fù)合運算符:+=(加法賦值)、-=(減法賦值)、*=(乘法賦值)、/=(除法賦值)、%=(取模賦值)、=(右移位賦值)、&=(邏輯與賦值)、|=(
22、邏輯或賦值)、=(邏輯異或賦值)、=(邏輯非賦值)。 復(fù)合賦值運算首先對變量進行某種運算,然后將運算的結(jié)果再賦值給該變量。復(fù)合運算的一般形式為:變量 復(fù)合賦值運算符 表達式例如 :a+=3等價于a=a+3;x*=y+8等價于x=x*(y+8)。采用復(fù)合賦值運算符,可以使程序簡化,同時還可以提高程序的編譯效率。2.4.8 逗號運算符 C語言中的逗號“,”是一個特殊的運算符,可以用它將兩個(或多個)表達式連接起來,稱為逗號表達式。逗號表達式的一般形式為:表達式1,表達式2,表達式n 程序運行時對于逗號表達式的處理,是從左至右依次計算出各個表達式的值,而整個逗號表達式的值是最右邊表達式(即表達式n)
23、的值。 在許多情況下,使用逗號表達式的目的只是為了分別得到各個表達式的值,而并不一定要得到和使用逗號表達式的值。另外還要注意,并不是在程序的任何地方出現(xiàn)的逗號,都可以認為是逗號運算符。有些函數(shù)中的參數(shù)也是用逗號來間隔的,例如,庫輸出函數(shù)printf(“n%d%d%d”,a,b,c)中的“a,b,c”是函數(shù)的三個參數(shù),而不是一個逗號表達式。2.4.9 條件運算符 條件運算符“?:”是C語言中唯一的一個三目運算符,它要求有3個運算對象,用它可以將3個表達式連接構(gòu)成一個條件表達式。 條件表達式的一般形式如下:邏輯表達式?表達式1:表達式2 其功能是首先計算邏輯表達式,當(dāng)值為真(非0值)時,將表達式一
24、的值作為整個條件表達式的值:當(dāng)邏輯表達式的值為假(0值)時,將表達式2的值作為整個表達式的值。例如,條件表達式max=(ab)?ab的執(zhí)行結(jié)果是將a和b中較大者賦值給變量max。另外,條件表達式中邏輯表達式的類型可以與表達式1和表達式2的類型不一樣。2.4.10 指針和地址運算符 指針是C語言中的最重要的概念,也是最難理解和掌握的。C語言中專門規(guī)定了一種指針類型的數(shù)據(jù)。變量的指針就是該變量的地址,還可以定義一個指向某個變量的指針變量。為了表示指針變量和它所指向的變量地址之間的關(guān)系,C語言提供兩個專門的運算符:*(取內(nèi)容)和&(取地址)。 取內(nèi)容和取地址的一般形式為:變量 = *指針變量 指針變
25、量 = &目標變量 取內(nèi)容運算的含義是將指針變量所指向的目標變量的值賦給左邊的變量;取地址運算的含義是將目標變量的地址賦給左邊的變量。需要注意的是,指針變量中只能存放地址(即指針型數(shù)據(jù)),不要將一個非指針類型的數(shù)據(jù)賦值給一個指針變量。例如,下面的語句完成了對指針變量賦值(地址值): char data *p; /*定義指針變量*/ p = 30H; /*給指針變量賦值,30H為片內(nèi)RAM地址*/2.4.11 C51對存儲器和特殊功能寄存器的訪問C51提供了一種對存儲器地址進行訪問的方法,即利用庫函數(shù)中的絕對地址訪問頭文件absacc.h來訪問不同區(qū)域的存儲器和片外擴展I/O端口。在absacc
26、.h頭文件中進行了如下宏定義: CBYTE(地址) (訪問CODE區(qū)char型) DBYTE(地址) (訪問DATA區(qū)char型) PBYTE(地址) (訪問PDATA區(qū)或I/O端口char型) XBYTE(地址) (訪問XDATA區(qū)或I/O端口char型) CWORD(地址) (訪問CODE區(qū)int型) DWORD(地址) (訪問DATA區(qū)int型) PWORD(地址) (訪問PDATA區(qū)或I/O端口int型) XWORD(地址) (訪問XDATA區(qū)或I/O端口int型)下面語句向片內(nèi)外擴展端口地址7FFFH寫入一個字符型數(shù)據(jù): XBYTE0 x7FF=0 x9988; 如果采用如下語句定義
27、一個D/A轉(zhuǎn)換器端口地址: #define DAC0832 XBYTE(0 x7FFF); 那么程序文件中所出現(xiàn)DAC0832的地方,就是對地址為0 x7FFF的外部RAM單元(I/O端口)進行訪問。 8051核單片機具有100多個品種,為了方便訪問不同品種單片機內(nèi)部特殊功能寄存器,C51提供了多個相關(guān)頭文件,如reg51.h、reg52.h等,在頭文件中對單片機內(nèi)部特殊功能寄存器及其有位名稱的可尋地址進行了定義,編程時只要根據(jù)所采用的單片機,在程序文件開始處使用文件包含處理命令“#include”將相關(guān)頭文件包含進來,就可以直接引用特殊功能寄存器(注意必須采用大寫字母)。 例如,下面語句完成
28、了8051定時方式寄存器TM0D的賦值:#include TMOD = 0 x20;2.4.12 強制類型轉(zhuǎn)換運算符 C語言中的圓括號“()”也可作為一種運算符使用,這就是強制類型轉(zhuǎn)換運算符,它的作用是將表達式或變量的類型強制轉(zhuǎn)換為所指定的類型。在C51程序中進行算式運算時需要注意數(shù)據(jù)類型的轉(zhuǎn)換,數(shù)據(jù)類型轉(zhuǎn)換分為隱式轉(zhuǎn)換和顯式轉(zhuǎn)換。隱式轉(zhuǎn)換是在對程序進行編譯時由編譯器自動處理的,并且只有幾本數(shù)據(jù)類型(即char、int、long和float)可以進行隱式轉(zhuǎn)換。其他數(shù)據(jù)類型不能進行隱式轉(zhuǎn)換。例如,我們不能把一個整型數(shù)利用隱式轉(zhuǎn)換賦值給一個指針變量,在這種情況下就必須利用強制類型轉(zhuǎn)換運算符來進行顯
29、式轉(zhuǎn)換。強制類型轉(zhuǎn)換運算符的一般使用形式為:(類型)= 表達式強制類型轉(zhuǎn)換在給指針變量賦值時特別有用。例如,預(yù)先在單片機的片外數(shù)據(jù)存儲器(xdata)中定義了一個字符型指針變量px,如果想給這個指針變量賦一個初值0 xB000,可以寫成:px=(char xdata*) 0 xB000,這種方法特別適合于標識符來存取絕對地址。2.4.13 sizeof運算符C語言中提供了一種用于求取數(shù)據(jù)類型、變量及表達式的字節(jié)數(shù)的運算符:sizeof。該運算符的一般適用形式為:sizeof(表達式)或sizeof(數(shù)據(jù)類型)應(yīng)該注意的是,sizeof是一種特殊的運算符,不要錯誤地認為它是一個函數(shù)。實際上,字節(jié)
30、數(shù)的計算在程序編譯時就完成了,而不是在程序執(zhí)行的過程中才計算出來。2.5 C51程序的基本語句2.5.1 表達式語句C語言提供了十分豐富的程序控制語句,表達式語句是最基本的一種語句。在表達式的后邊加一個分好“:”就構(gòu)成了表達式語句。下面的語句都是合法的表達式語句:a=+b*9;x=8;y=7;z=(x+y)/a;+i;表達式語句也可以僅由一個分號“;”組成,這種語句成為空語句??照Z句在程序設(shè)計中有時是很有用的,當(dāng)程序在語法上需要有一個語句,但在語義上并不要求有具體的動作時,便可以采用空語句??照Z句通常有以下兩種用法。(1)在程序中為有關(guān)語句提供標號,用以標記程序執(zhí)行的位置。例如,采用下面的語句
31、可以構(gòu)成一個循環(huán)。 repeat:; goto repeat;(2)在用while語句構(gòu)成的循環(huán)語句后面加一個分號,形成一個不執(zhí)行其他操作的空循環(huán)體。這種空語句在等待某個事件發(fā)生時特別有用。例如,下面這段程序是讀取8051單片機串行口數(shù)據(jù)的函數(shù),其中就用了一個空語句while(!RI),來等待單片機串行口接受結(jié)束。#include /*插入8051單片機的預(yù)定義文件*/ char _getkey () /*函數(shù)定義*/ /*函數(shù)體開始*/ char c; /*定義變量*/ while(!RI); /*空語句,等待8051單片機串行 口接收結(jié)束*/ c=SBUF; /*讀串行口內(nèi)容*/RI=0;
32、 /*清除串行口接收標志*/Return (0); /*返回*/ /*函數(shù)體結(jié)束*/ 采用分號“;”作為空語句使用時,要注意與簡單語句中有效組成部分的分號相區(qū)別。不能濫用空語句,以免引起程序的誤操作,甚至造成程序語法上的錯誤。2.5.2 復(fù)合語句復(fù)合語句在執(zhí)行時,其中各條單語句一次順序執(zhí)行,整個復(fù)合語句在語法上等價于一條單語句。復(fù)合語句允許嵌套,即在復(fù)合語句內(nèi)部還可以包含別的復(fù)合語句。通常復(fù)合語句出現(xiàn)在函數(shù)中,實際上,函數(shù)的執(zhí)行部分(即函數(shù)體)就是一個復(fù)合語句。復(fù)合語句中的單語句一般是可執(zhí)行語句,也可以是變量定義語句。在復(fù)合語句內(nèi)所定義的變量復(fù)合語句是由若干條語句組合而成的一種語句,它是一個大
33、括號“”將若干條語句組合在一起而形成的一種功能塊。復(fù)合語句不需要以分號“:”結(jié)束,但它內(nèi)部的各條單語句仍需以分號“;”結(jié)束。復(fù)合語句的一般形式為: 局部變量定義; 語句1; 語句2; 語句n;稱為該復(fù)合語句中的局部變量,它僅在當(dāng)前這個復(fù)合語句中有效。2.5.3 條件語句條件語句又稱為分支語句,它是用關(guān)鍵字“if”構(gòu)成的。C語言提供了三種形式的條件語句。if(條件表達式) 語句其含義為:若條件表達式的結(jié)果為真(非0值),就執(zhí)行后面的語句;反之若條件表達式的結(jié)果為假(0值),就不執(zhí)行后面的語句。這里的語句也可以是復(fù)合語句。if(條件表達式) 語句1 else 語句2其含義為:若條件表達式的結(jié)果為真
34、(非0值),就執(zhí)行后面的語句;反之若條件表達式的結(jié)果為假(0值),就 執(zhí)行語句2。這里的語句1和語句2均可以是復(fù)合語句。2.5.4 開關(guān)語句開關(guān)語句也是一種用來實現(xiàn)多方向條件分支的語句。雖然采用條件語句也可以實現(xiàn)多方向條件分支,但是當(dāng)分支較多時會使條件語句的嵌套層次太多,程序冗長,可讀性降低。開關(guān)語句直接處理多分支選擇,使程序結(jié)構(gòu)清晰,使用方便。開關(guān)語句是用關(guān)鍵字switch構(gòu)成的,它的一般形式如下:switch (表達式) case 常量表達式1 : 語句1; break; case 常量表達式 2: 語句2; break; case 常量表達式 n : 語句n; break; defaul
35、t: 語句d 2.5.4 開關(guān)語句 開關(guān)語句的執(zhí)行過程是將switch后面的表達式的值與case后面的各個常量表達式的值逐個進行比較,若遇到匹配時,就執(zhí)行相應(yīng)的case后面的語句,然后執(zhí)行break語句,break語句又稱間斷語句,它的功能是終止當(dāng)前的語句執(zhí)行,使程序跳出switch語句。若無匹配的情況,則執(zhí)行語句d。2.5.5 循環(huán)語句實際應(yīng)用中很多地方需要用到循環(huán)控制,如對于某種操作需要反復(fù)進行多次等。在需要程序中用來構(gòu)成循環(huán)控制語句的有:while語句,do while語句,for語句和goto語句。 采用while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下: while (條件表達式) 語句: 其
36、意義為,當(dāng)條件表達式的結(jié)果為真(非0值時),程序就重復(fù)執(zhí)行后面的語句,一直執(zhí)行到條件表達式的結(jié)果變?yōu)榧?0值)時為止。這種循環(huán)結(jié)構(gòu)是先檢查表達式所給出的條件,再根據(jù)檢查的結(jié)果決定是否執(zhí)行后面的語句。如果條件表達式的結(jié)果一開始就為假,則后面的語句一次也不會被執(zhí)行。這里的語句可以是復(fù)合語句。 2.5.5 循環(huán)語句 采用do-while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下: do 語句 while (條件表達式); 這種循環(huán)結(jié)構(gòu)的特點是先執(zhí)行給定的循環(huán)語句,然后再檢查條件表達式的結(jié)果。當(dāng)條件表達式的值為真(非0值)時,則重復(fù)執(zhí)行循環(huán)體語句,直到條件表達式的值變?yōu)榧贂r為止。因此,用do while語句構(gòu)成的
37、循環(huán)結(jié)構(gòu)在任何條件下,循環(huán)語句至少會被執(zhí)行一次。 采用for語句構(gòu)成循環(huán)語句結(jié)構(gòu)的一般形式如下: for(初值設(shè)定表達式:循環(huán)條件表達式:更新表達式) 語句 for語句的執(zhí)行過程是:先計算出初值設(shè)定表達式的值,將其作為循環(huán)控制變量的初值。再檢查循環(huán)條件表達式的結(jié)果。當(dāng)滿足條件時就執(zhí)行循環(huán)體語句并計算更新表達式,然后再根據(jù)更新表達式的計算結(jié)果來判斷計算結(jié)果是否滿足一直進行到循環(huán)條件表達式為假(0值)時退出循環(huán)體。 循環(huán)結(jié)構(gòu)中,for語句的使用最為靈活。它不僅可以用于循環(huán)次數(shù)已經(jīng)確定的情況,而且可以用于循環(huán)次數(shù)不確定而只給出循環(huán)結(jié)束條件的情況。另外,for語句中的三個表達式是相互獨立的,并不一定要
38、求三個表達式之間有依賴關(guān)系。并且for語句中的三個表達式都可能是默認的,但無論默認的哪一個表達式,其中的兩個分號都不能默認。 一般不要默認的循環(huán)條件表達式,以免形成死循環(huán)。2.5.5 循環(huán)語句2.5.6 goto、break、continue語句goto語句是一個無條件轉(zhuǎn)向語句,它的一般形式為: goto 語句標號: 其中語句標號是一個帶冒號“:”的標識符。將goto語句和if語句一起使用,可以構(gòu)成一個循環(huán)結(jié)構(gòu)。但更常見的是在C51程序中采用goto語句來跳出多重循環(huán),需要注意的是只能用goto語句從內(nèi)層循環(huán)到外層循環(huán),而不允許從外層循環(huán)跳到內(nèi)層循環(huán)。break語句也可以用于跳出循環(huán)體,它的一
39、般形式為: break; 對于多重循環(huán)的情況,break語句只能跳出它所處的那一層循環(huán),而不像goto語句可以直接從最內(nèi)層循環(huán)中跳出來。由此可見,要跳出多重循環(huán)時,采用goto語句比較方便。需要指出的是break語句只能用于開關(guān)語句和循環(huán)語句之中,它是一種具有特殊功能的無條件轉(zhuǎn)移語句。 continue是一種中斷語句,它的功能是中斷本次循環(huán),它的一般形式為: continue; continue語句通常和條件語句一起用在由while、do-while和for語句構(gòu)成的循環(huán)結(jié)構(gòu)中,它也是一種具有特殊功能的無條件轉(zhuǎn)移語句,但與break語句不同,continue語句并不跳出循環(huán)體,而只是根據(jù)循環(huán)控
40、制條件確定是否繼續(xù)執(zhí)行循環(huán)語句。2022/7/192.5.7 返回語句返回語句用于終止函數(shù)的執(zhí)行,并控制程序返回到調(diào)用函數(shù)時所處的位置。返回語句有兩種形式:return(表達式)、return。 如果return語句后邊帶有表達式,則要計算表達式的值,并將表達式的值作為該函數(shù)的返回值。若使用不帶表達式的第2種形式,則被調(diào)用函數(shù)返回主調(diào)函數(shù)時,函數(shù)值不確定。一個函數(shù)的內(nèi)部可以含有多個return語句,但程序僅執(zhí)行其中一個return語句而返回主調(diào)用函數(shù)。一個函數(shù)的內(nèi)部也可以沒有return語句,在這種情況下,當(dāng)程序執(zhí)行到最后一個界限符“”處時,就自動返回主調(diào)函數(shù)。2022/7/192.6 Kei
41、l C51指針2.6.1 C51指針C51支持一般指針(Generic Pointer)和存儲器指針(Memory_Specific Pointer)。 1. 一般指針 一般指針的聲明和使用均與標準C相同,不過同時還可以說明指針的存儲類型,例如: long * state;為一個指向long型整數(shù)的指針,而state本身則依存儲模式存放。 char * xdata ptr;ptr為一個指向char數(shù)據(jù)的指針,而ptr本身放于外部RAM區(qū),以上的long,char等指針指向的數(shù)據(jù)可存放于任何存儲器中。 一般指針本身用3個字節(jié)存放,分別為存儲器類型,高位偏移,低位偏移量。 2022/7/192.6
42、 Keil C51指針2.6.1 C51指針 2. 存儲器指針 基于存儲器的指針說明時即指定了存貯類型,例如: char data * str;str指向data區(qū)中char型數(shù)據(jù)。 int xdata * pow; pow指向外部RAM的int型整數(shù)。 這種指針存放時,只需一個字節(jié)或2個字節(jié)就夠了,因為只需存放偏移量。 2022/7/192.6 Keil C51指針2.6.1 C51指針 3. 指針轉(zhuǎn)換 即指針在上兩種類型之間轉(zhuǎn)化:當(dāng)基于存儲器的指針作為一個實參傳遞給需要一般指針的函數(shù)時,指針自動轉(zhuǎn)化。如果不說明外部函數(shù)原形,基于存儲器的指針自動轉(zhuǎn)化為一般指針,導(dǎo)致錯誤,因而請用“inclu
43、de”說明所有函數(shù)原形??梢詮娦懈淖冎羔橆愋?。2022/7/192.6.2 利用指針實現(xiàn)絕對地址訪問利用關(guān)鍵字“_at_”定義變量可以實現(xiàn)絕對地址存儲單元的訪問,還可以利用指針實現(xiàn)絕對地址存儲單元的訪問。例如:unsigned char data *p; / 定義指針p,指向內(nèi)部RAM數(shù)據(jù)p = 0 x50; / 指針p賦值,指向內(nèi)部RAM的0 x50單元*p = 0 x80; / 數(shù)據(jù)0 x80送入內(nèi)部RAM的0 x50單元2022/7/192.6.2 利用指針實現(xiàn)絕對地址訪問 為了編程方便,C51編譯器還提供了一組宏定義以實現(xiàn)對51單片機絕對地址的訪問。這組宏定義原型放在absacc.h文
44、件中,該文件包括如下語句:#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) #define CWORD(unsigned int volatile code *)0) #define DWORD(unsigned int volatile data *)0) #defi
45、ne PWORD(unsigned int volatile pdata *)0) #define XWORD(unsigned int volatile xdata *)0)2022/7/192.6.2 利用指針實現(xiàn)絕對地址訪問此處把CBYTE定義為(unsigned char volatile code *)0),其中(unsigned char volatile code *)表示對常值地址0進行強制類型轉(zhuǎn)換,形成一個指針,指向了code區(qū)的0地址單元。因此,CBYTE可以用于以字節(jié)形式對code區(qū)進行訪問。*(DBYTE) = 0 x55H / 將0 x55H傳送到內(nèi)部RAM的00H單
46、元*(DBYTE+40H) = 0 x3FH / 將0 x3FH傳送到內(nèi)部RAM的40H單元C語言中指針與數(shù)組可以相互聯(lián)系,上述的語句還可以表示成數(shù)組形式。DBYTE0 = 0 x55H / 將0 x55H傳送到內(nèi)部RAM的00H單元DBYTE40H = 0 x3FH / 將0 x3FH傳送到內(nèi)部RAM的40H單元【注意】在使用C51編程時,不要輕易使用指針給絕對地址單元賦值,因為采用絕對地址賦值可能破壞C51編譯系統(tǒng)構(gòu)造的運行環(huán)境。2022/7/192.7 Keil C51函數(shù)C51程序由主函數(shù)和若干子函數(shù)構(gòu)成,函數(shù)是構(gòu)成C51程序的基本模塊。C51函數(shù)可分為兩大類,一是系統(tǒng)提供的庫函數(shù),二
47、是用戶自定義的函數(shù)。庫函數(shù)及自定義函數(shù)在被調(diào)用前要進行說明。庫函數(shù)的說明由系統(tǒng)提供的若干頭文件分類實現(xiàn),自定義函數(shù)說明由用戶在程序中依規(guī)則完成。 C51函數(shù)聲明對ANSI C作了擴展,具體包括:1. 中斷函數(shù)聲明 中斷聲明方法如下: void serial_ISR () interrupt 4 using 1 /* ISR */ 2022/7/192.7 Keil C51函數(shù) 為提高代碼的容錯能力,在沒用到的中斷入口處生成iret語句,定義沒用到的中斷。/* define not used interrupt, so generate IRET in their entrance */ voi
48、d extern0_ISR() interrupt 0 /* not used */ void timer0_ISR () interrupt 1 /* not used */ void extern1_ISR() interrupt 2 /* not used */ void timer1_ISR () interrupt 3 /* not used */ void serial_ISR () interrupt 4 /* not used */2022/7/192. 通用存儲工作區(qū)3. 選通用存儲工作區(qū)由using x聲明,見上例。4. 指定存儲模式 由small compact 及l(fā)ar
49、ge說明,例如: void fun1(void) small 提示:small說明的函數(shù)內(nèi)部變量全部使用內(nèi)部RAM。關(guān)鍵的經(jīng)常性的耗時的地方可以這樣聲明,以提高運行速度。5. #pragma disable 在函數(shù)前聲明,只對一個函數(shù)有效。該函數(shù)調(diào)用過程中將不可被中斷。2022/7/196. 遞歸或可重入函數(shù)指定 在主程序和中斷中都可調(diào)用的函數(shù),容易產(chǎn)生問題。因為51和PC不同,PC使用堆棧傳遞參數(shù),且靜態(tài)變量以外的內(nèi)部變量都在堆棧中;而51一般使用寄存器傳遞參數(shù),內(nèi)部變量一般在RAM中,函數(shù)重入時會破壞上次調(diào)用的數(shù)據(jù)??梢杂靡韵聝煞N方法解決函數(shù)重入: a、在相應(yīng)的函數(shù)前使用前述“#pragm
50、a disable”聲明,即只允許主程序或中斷之一調(diào)用該函數(shù); b、將該函數(shù)說明為可重入的。如下: void func(param.) reentrant;2022/7/19KeilC51編譯后將生成一個可重入變量堆棧,然后就可以模擬通過堆棧傳遞變量的方法。 由于一般可重入函數(shù)由主程序和中斷調(diào)用,所以通常中斷使用與主程序不同的R寄存器組。 另外,對可重入函數(shù),在相應(yīng)的函數(shù)前面加上開關(guān)“#pragma noaregs”,以禁止編譯器使用絕對寄存器尋址,可生成不依賴于寄存器組的代碼。7. 指定PL/M51函數(shù)由alien指定。2022/7/192.8 C51代碼優(yōu)化及庫函數(shù)2.8.1 C51代碼優(yōu)
51、化C51是一個很好的優(yōu)化編譯器,它通過多個步驟確保產(chǎn)生的代碼是最有效的。編譯器通過分析初步的代碼產(chǎn)生最終的最有效率的代碼序列,以此來保證C語言程序占用最少空間的同時運行得快而有效。 C51編譯器提供10個優(yōu)化級別(0-9),每個高級優(yōu)化級別都包括比它低的所有優(yōu)化級別的優(yōu)化內(nèi)容。目前C51編譯器提供的所有優(yōu)化級別及含義如表2-1所示。表2-1 C51支持的優(yōu)化級別及含義優(yōu)化級別描述0常數(shù)合并:編譯器預(yù)先計算結(jié)果,盡可能用常數(shù)代替表達式。包括運行地址計算。優(yōu)化簡單訪問:編譯器優(yōu)化訪問8051系統(tǒng)的內(nèi)部數(shù)據(jù)和位地址。 跳轉(zhuǎn)優(yōu)化:編譯器總是擴展跳轉(zhuǎn)到最終目標,多級跳轉(zhuǎn)指令被刪除。1死代碼刪除:沒用的代
52、碼段被刪除。拒絕跳轉(zhuǎn):嚴密的檢查條件跳轉(zhuǎn),以定是否可以倒置測試邏輯來改進或刪除。2數(shù)據(jù)覆蓋:適合靜態(tài)覆蓋的數(shù)據(jù)和位段被確定,并內(nèi)部標識。BL51連接/定位器可以通過全局數(shù)據(jù)流分,選擇可被覆蓋的段。3窺孔優(yōu)化:清除多余的MOV指令。這包括不必要的從存儲區(qū)加載和常數(shù)加載操作。當(dāng)存儲空間或執(zhí)行時間可節(jié)省時,用簡單操作代替復(fù)雜操作。2022/7/194寄存器變量:如有可能,自動變量和函數(shù)參數(shù)分配到寄存器上。為這些變量保留的存 儲區(qū)就省略了。優(yōu)化擴展訪問:IDATA、XDATA、PDATA和CODE的變量直接包含在操作中。在多數(shù)時間沒必要使用中間寄存器。局部公共子表達式刪除:如果用一個表達式重復(fù)進行相同
53、的計算,則保存第一次計算結(jié)果,后面有可能就用這結(jié)果。多余的計算就被刪除。Case/Switch優(yōu)化:包含SWITCH和CASE的代碼優(yōu)化為跳轉(zhuǎn)表或跳轉(zhuǎn)隊列。5全局公共子表達式刪除:一個函數(shù)內(nèi)相同的子表達式有可能就只計算一次。中間結(jié)果保存在寄存器中,在一個新的計算中使用。簡單循環(huán)優(yōu)化:用一個常數(shù)填充存儲區(qū)的循環(huán)程序被修改和優(yōu)化。6循環(huán)優(yōu)化:如果結(jié)果程序代碼更快和有效則程序?qū)ρh(huán)進行優(yōu)化。7擴展索引訪問優(yōu)化:適當(dāng)時對寄存器變量用DPTR。對指針和數(shù)組訪問進行執(zhí)行速度和 代碼大小優(yōu)化。8公共尾部合并:當(dāng)一個函數(shù)有多個調(diào)用,一些設(shè)置代碼可以復(fù)用,因此減少程序大小 。9公共塊子程序:檢測循環(huán)指令序列,并
54、轉(zhuǎn)換成子程序。Cx51甚至重排代碼以得到更大的循環(huán)序列。2022/7/192.8.2 C51內(nèi)聯(lián)的庫函數(shù)C51編譯器的庫中包含一定數(shù)量的內(nèi)聯(lián)函數(shù),這種函數(shù)不產(chǎn)生ACALL或LCALL指令來執(zhí)行庫函數(shù),而是直接將函數(shù)代碼添加到調(diào)用函數(shù)中。因此使用內(nèi)聯(lián)函數(shù)比使用一個調(diào)用函數(shù)要快而且有效。C51的內(nèi)聯(lián)函數(shù)及其描述如表2-2所示。表2-2 C51的內(nèi)聯(lián)函數(shù) 內(nèi)聯(lián)函數(shù)描述_crol_字節(jié)左移_cror_字節(jié)右移_irol_整數(shù)左移_irol_整數(shù)右移_lrol_長整數(shù)左移_lrol_長整數(shù)右移_nop_空操作_testbit_判斷并清除2022/7/192.9 C51程序結(jié)構(gòu)及應(yīng)用要點2.9.1 C51
55、程序結(jié)構(gòu)C51程序由函數(shù)構(gòu)成,其中至少應(yīng)包含一個主函數(shù)main。函數(shù)與子程序或過程具有相同的性質(zhì)。程序從主函數(shù)開始執(zhí)行,調(diào)用其他函數(shù)后又返回主函數(shù)。被調(diào)用函數(shù)如果位于主函數(shù)前面,可以直接調(diào)用,否則應(yīng)該先聲明該函數(shù),然后再調(diào)用。被調(diào)用函數(shù)可以是用戶自定義的函數(shù),也可以是C51編譯器提供的庫函數(shù)。C51程序的一般結(jié)構(gòu)如下:預(yù)處理命令;全局變量聲明;函數(shù)聲明;main( ) 局部變量說明; 執(zhí)行語句; 調(diào)用函數(shù)(實際參數(shù)列表);函數(shù)1(形式參數(shù)列表) 局部變量說明; 執(zhí)行語句(可能包括的函數(shù)調(diào)用語句);函數(shù)n(形式參數(shù)列表) 局部變量說明; 執(zhí)行語句(可能包括的函數(shù)調(diào)用語句);2022/7/19所有
56、函數(shù)在定義時都是獨立的,一個函數(shù)中不能定義其他函數(shù),即函數(shù)不能嵌套定義,但可以相互調(diào)用,上面的格式給出了函數(shù)調(diào)用的一般規(guī)則。程序執(zhí)行從主函數(shù)main()開始,在其中可以通過調(diào)用各個定義的函數(shù)完成特定的功能,最后返回主函數(shù)main(),在主函數(shù)中結(jié)束整個C51程序的運行。使用C語言的一些規(guī)則如下: (1)變量必須先聲明后引用,所有符號對大小寫敏感。通常全局變量、特殊功能寄存器名、常數(shù)符號用大寫表示,一般的語句、函數(shù)用小寫。 (2)每條語句必須以分號“;”結(jié)尾,一行可以寫多條語句,一條語句也可以寫多行。 (3)注釋用/*/或/表示。2022/7/192.9.2 C51應(yīng)用要點本章介紹C51的基本數(shù)
57、據(jù)類型、存儲類型及C51對單片機內(nèi)部的定義,這些都是C語言編寫單片機程序的基礎(chǔ),但是要編寫出高效的C語言程序,通常應(yīng)以下問題。1. 定義變量經(jīng)常訪問的數(shù)據(jù)對象放入片內(nèi)數(shù)據(jù)RAM中,這可在任一種模式(COMPACT/LARGE)下實現(xiàn),且訪問片內(nèi)RAM要比訪問片外RAM快很多。片內(nèi)RAM由寄存器組、數(shù)據(jù)區(qū)和堆棧構(gòu)成,且堆棧與用戶data;類型定義的變量可能重疊,初始化時SP要從默認的0 x07指向高端,以避開寄存器組區(qū)。由于片內(nèi)RAM容量的限制,在設(shè)計程序時必須權(quán)衡利弊,以解決訪問效率與這些對象的數(shù)量之間的矛盾。2. 使用最小數(shù)據(jù)類型在程序設(shè)計時,只要滿足要求,應(yīng)盡量使用最小數(shù)據(jù)類型。由基于80
58、51核的STC系列單片機都是8位單片機,因此對具有char類型對象的操作比int和long類型的對象方便很多。3. 使用unsigned數(shù)據(jù)類型由于8051核的單片機CPU不能直接支持有符號的運算,因而C51編譯必須產(chǎn)生與之相關(guān)更多的代碼,以解決這個問題。如果使用無符號類型,產(chǎn)生的代碼要少得多。4. 使用局部函數(shù)變量 編譯器總是嘗試在寄存器里保持局部變量。例如將索引變量聲明為局部變量是最好的,這個優(yōu)化步驟只對局部變量執(zhí)行。使用unsigned char/int類型的對象通常能獲得最好的結(jié)果。2022/7/192.10 Keil C51高級編程2.10.1 絕對地址訪問C51提供了三種訪問絕對地
59、址的方法: 1. 絕對宏 在程序中,用“include”即可使用其中定義的宏來訪問絕對地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD,具體使用可看一看absacc.h便知。例如:rval = CBYTE0 x0002; /指向程序存貯器的0002h地址 rval = XWORD0 x0002; /指向外RAM的0004h地址 2022/7/192.10.1 絕對地址訪問 2. _at_關(guān)鍵字 直接在數(shù)據(jù)定義后加上_at_ const即可,但是注意: (1) 絕對變量不能被初使化; (2) bit型函數(shù)及變量不能用_at_指定。例如:idata struct link list _at_ 0 x40; /指定list結(jié)構(gòu)從40h開始xdata char text25b _at_0 xE000;/指定text數(shù)組從0E000H開始2022/7/
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 沈陽理工大學(xué)《激光器件與技術(shù)》2021-2022學(xué)年第一學(xué)期期末試卷
- 食品安全宣傳主題班會
- 沈陽理工大學(xué)《工程爆破》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽理工大學(xué)《傳感器與檢測技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 國有企業(yè)買賣合同保證金管理辦法
- 合同備案注銷、更名申請書
- 昆明機場控制區(qū)通行證考試
- 2024-2025年度部編版八年級上冊歷史復(fù)習(xí)訓(xùn)練一
- 2024水泥采購運輸合同
- 深圳矯正牙齒-口腔醫(yī)院
- 2020-2021學(xué)年河南省洛陽市高一上學(xué)期期中考試化學(xué)試題
- 四年級上冊語文第六單元任務(wù)群教學(xué)設(shè)計
- 2024-2025學(xué)年北師大版九年級數(shù)學(xué)上冊期中培優(yōu)試題
- 《高血壓科普知識》課件
- 《建筑工程設(shè)計文件編制深度規(guī)定》(2022年版)
- 心理咨詢中知情同意的倫理困境與解決途徑
- 山地光伏除草施工方案
- 2024-2025學(xué)年蘇教版小學(xué)四年級上學(xué)期期中數(shù)學(xué)試卷及解答參考
- 動物園主題認識數(shù)字1-5幼兒教育教學(xué)
- 新疆歷史印記課件
- 2024年西南民族大學(xué)招聘教師歷年高頻500題難、易錯點模擬試題附帶答案詳解
評論
0/150
提交評論