




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、在線教務(wù)輔導(dǎo)網(wǎng): :/教材其余課件及動畫素材請查閱在線教務(wù)輔導(dǎo)網(wǎng)QQ:349134187 或者直接輸入下面地址:第四章 C51根本語句用C語言編寫MCS-51單片機(jī)程序與用匯編語言編寫MCS51單片機(jī)程序不一樣,用匯編語言編寫MCS51單片機(jī)程序必須要考慮其存儲器結(jié)構(gòu),尤其必須考慮其片內(nèi)數(shù)據(jù)存儲器與特殊功能存放器的使用以及按實際地址處理端口數(shù)據(jù)。用C語言編寫的MCS51單片機(jī)應(yīng)用程序,那么不用像匯編語言那樣須具體組織、分配存儲器資源和處理端口數(shù)據(jù),但用C語言編程時,對數(shù)據(jù)類型與變量的定義,必須要與單片機(jī)的存儲結(jié)構(gòu)相關(guān)聯(lián),否那么編譯器不能正確地映射定位。所以我們把這種和MCS-51單片機(jī)硬件有關(guān)
2、聯(lián)的C語言也叫C51語言,它和標(biāo)準(zhǔn)的C語言有一些不同。用C51語言編寫單片機(jī)應(yīng)用程序與標(biāo)準(zhǔn)的C語言程序也有相應(yīng)的區(qū)別:C51語言編寫單片機(jī)應(yīng)用程序時,需根據(jù)單片機(jī)存儲結(jié)構(gòu)及內(nèi)部資源定義相應(yīng)的數(shù)據(jù)類型和變量,而標(biāo)準(zhǔn)的C語言程序不需要考慮這些問題;C51包含的數(shù)據(jù)類型、變量存儲模式、輸入輸出處理、函數(shù)等方面與標(biāo)準(zhǔn)的C語言有一定的區(qū)別。其它的語法規(guī)那么、程序結(jié)構(gòu)及程序設(shè)計方法等與標(biāo)準(zhǔn)的C語言程序設(shè)計相同。現(xiàn)在支持MCS-51系列單片機(jī)的C語言編譯器有很多種,如American Automation、Avocet、BSO/TASKING、DUNFIELD SHAREWARE、KEIL/Franklin
3、等。各種編譯器的根本情況相同,但具體處理時有一定的區(qū)別,其中Keil C 以它的代碼緊湊和使用方便等特點優(yōu)于其它編譯器,現(xiàn)在使用特別廣泛。本書以Keil C編譯器介紹MCS-51單片機(jī)C語言程序設(shè)計。4.1.1 C語言的特點1. 語言簡潔、緊湊,使用方便、靈活。2. 運算符豐富。3數(shù)據(jù)結(jié)構(gòu)豐富。具有現(xiàn)代化語言的各種數(shù)據(jù)結(jié)構(gòu)。4可進(jìn)行結(jié)構(gòu)化程序設(shè)計。5可以直接對計算機(jī)硬件進(jìn)行操作。6生成的目標(biāo)代碼質(zhì)量高,程序執(zhí)行效率高。7可移植性好。4.1.2 C語言和C51的程序結(jié)構(gòu) C語言程序采用函數(shù)結(jié)構(gòu),每個C語言程序由一個或多個函數(shù)組成,在這些函數(shù)中至少應(yīng)包含一個主函數(shù)main(),也可以包含一個mai
4、n()函數(shù)和假設(shè)干個其它的功能函數(shù)。不管main()函數(shù)放于何處,程序總是從main()函數(shù)開始執(zhí)行,執(zhí)行到main()函數(shù)結(jié)束。在main()函數(shù)中調(diào)用其它函數(shù),其它函數(shù)也可以相互調(diào)用,但main()函數(shù)只能調(diào)用其它的功能函數(shù),而不能被其它的函數(shù)所調(diào)用。功能函數(shù)可以是C語言編譯器提供的庫函數(shù),也可以是由用戶定義的自定義函數(shù)。在編制C程序時,程序的開始局部一般是預(yù)處理命令、函數(shù)說明和變量定義等。 C語言程序結(jié)構(gòu)一般如下:預(yù)處理命令 include函數(shù)定義 int fun1(); float fun2();變量說明 int x,y; float z;主函數(shù)main函數(shù)體fun1fun2其中,函數(shù)
5、往往由“函數(shù)定義和“函數(shù)體兩個局部組成。函數(shù)定義局部包括有函數(shù)類型、函數(shù)名、形式參數(shù)說明等,函數(shù)名后面必須跟一個圓括號,形式參數(shù)在內(nèi)定義。函數(shù)體由一對花括號“組成,在“的內(nèi)容就是函數(shù)體。如果一個函數(shù)內(nèi)有多個花括號,那么最外層的一對“為函數(shù)體的內(nèi)容。函數(shù)體內(nèi)包含假設(shè)干語句,一般由兩局部組成:聲明語句和執(zhí)行語句。聲明語句用于對函數(shù)中用到的變量進(jìn)行定義。也可能對函數(shù)體中調(diào)用的函數(shù)進(jìn)行聲明。執(zhí)行語句由假設(shè)干語句組成,用來完成一定功能。當(dāng)然也有的函數(shù)體僅有一對“,其中內(nèi)部既沒有聲明語句,也沒有執(zhí)行語句。這種函數(shù)稱為空函數(shù)。C語言程序在書寫時格式十分自由,一條語句可以寫成一行,也可以寫成幾行;還可以一行內(nèi)
6、寫多條語句;但每條語句后面必須以分號“;作為結(jié)束符。C語言程序?qū)Υ笮懽帜该舾校诔绦蛑?,同一個字母的大小寫系統(tǒng)是作不同的處理。在程序中可以用“/*/或“/對C程序中的任何局部作注釋,以增加程序的可讀性。C語言也是一種較好和應(yīng)用很廣的程序控制語言,如果我們說匯編語言是底層語言,那么C語言就是高級語言,它通用性比匯編語言要好,為了實現(xiàn)對底層設(shè)備的驅(qū)動,C語言也有一些端口驅(qū)動函數(shù),例如對屏幕輸出的格式控制輸出函數(shù)printf(),鍵盤輸入的scanf()函數(shù)等。此外還有一組在dos.h中定義的直接對設(shè)備端口進(jìn)行操作的函數(shù):int inport (int portid),unsigned char
7、inportb (int portid),void outport (int portid,int value),void outportb (int portid,unsigned char value ),C語言中的位操作使用戶可以通過bit對設(shè)備進(jìn)行控制。所有這些特點,使C語言在嵌入式控制系統(tǒng)中得到廣泛應(yīng)用。C51的語法吸收了C語言的全部特點,程序結(jié)構(gòu)及程序設(shè)計方法都與標(biāo)準(zhǔn)的C語言程序設(shè)計相同,但C51程序與標(biāo)準(zhǔn)的C程序僅在以下幾個方面不一樣:1C51中定義的庫函數(shù)和標(biāo)準(zhǔn)C語言定義的庫函數(shù)不同。標(biāo)準(zhǔn)的C語言定義的庫函數(shù)是按通用微型計算機(jī)來定義的,而C51中的庫函數(shù)是按MCS-51單片機(jī)相
8、應(yīng)情況來定義的;2C51中的數(shù)據(jù)類型與標(biāo)準(zhǔn)C的數(shù)據(jù)類型也有一定的區(qū)別,在C51中還增加了幾種針對MCS-51單片機(jī)特有的數(shù)據(jù)類型;3C51變量的存儲模式與標(biāo)準(zhǔn)C中變量的存儲模式不一樣,C51中變量的存儲模式是與MCS-51單片機(jī)的存儲器緊密相關(guān);4C51與標(biāo)準(zhǔn)C的輸入輸出處理不一樣,C51中的輸入輸出是通過MCS-51串并口來完成的,輸入輸出指令執(zhí)行前必須要對串行口進(jìn)行初始化;5C51與標(biāo)準(zhǔn)C在函數(shù)使用方面也有一定的區(qū)別,C51中有專門的中斷函數(shù)。4.2 C51數(shù)據(jù)類型C51的數(shù)據(jù)類型分為根本數(shù)據(jù)類型和組合數(shù)據(jù)類型,情況與標(biāo)準(zhǔn)C中的數(shù)據(jù)類型根本相同,其中float型與double型相同,另外,
9、C51中還有專門針對于MCS-51單片機(jī)的特殊功能存放器型和位類型。4.2.1 字符型(字節(jié)型) char有signed char和unsigned char之分,默認(rèn)為signed char。它們的長度為一個字節(jié),用于存放一個單字節(jié)的數(shù)據(jù)。對于signed char,它用于定義帶符號字節(jié)數(shù)據(jù),其字節(jié)的最高位為符號位,“0表示正數(shù),“1表示負(fù)數(shù),補(bǔ)碼表示,所能表示的數(shù)值范圍是-128+127;對于unsigned char,它用于定義無符號字節(jié)數(shù)據(jù)或字符,可以存放一個字節(jié)的無符號數(shù),其取值范圍為0255。unsigned char可以用來存放無符號數(shù),也可以存放西文字符,一個西文字符占一個字節(jié)
10、,在計算機(jī)內(nèi)部用ASCII碼存放。4.2.2 int整型分singed int和unsigned int。默認(rèn)為signed int。它們的長度均為兩個字節(jié),用于存放一個雙字節(jié)數(shù)據(jù)。對于signed int,用于存放兩字節(jié)帶符號數(shù),補(bǔ)碼表示,數(shù)的范疇為-32768+32767。對于unsigned int,用于存放兩字節(jié)無符號數(shù),數(shù)的范圍為065535。4.2.3 long長整型分singed long和unsigned long。默認(rèn)為signed long。它們的長度均為四個字節(jié),用于存放一個四字節(jié)數(shù)據(jù)。對于signed long,用于存放四字節(jié)帶符號數(shù),補(bǔ)碼表示,數(shù)的范疇為-214748
11、3648+2147483647。對于unsigned long,用于存放四字節(jié)無符號數(shù),數(shù)的范圍為04294967295。4.2.4 float浮點型float型數(shù)據(jù)的長度為四個字節(jié),格式符合IEEE-754標(biāo)準(zhǔn)的單精度浮點型數(shù)據(jù),包含指數(shù)和尾數(shù)兩局部,最高位為符號位,“1表示負(fù)數(shù),“0表示正數(shù),其于的8位為階碼,最后的23位為尾數(shù)的有效數(shù)位,由于尾數(shù)的整數(shù)局部隱含為“1,所以尾數(shù)的精度為24位。4.2.5 * 指針型指針型本身就是一個變量,在這個變量中存放的指向另一個數(shù)據(jù)的地址。這個指針變量要占用一定的內(nèi)存單元,對不同的處理器其長度不一樣,在C51中它的長度一般為13個字節(jié)。4.2.6 特殊
12、功能存放器型這是C51擴(kuò)充的數(shù)據(jù)類型,用于訪問MCS-51單片機(jī)中的特殊功能存放器數(shù)據(jù),它分sfr和sfr16兩種類型,其中sfr為字節(jié)型特殊功能存放器類型,占一個內(nèi)存單元,利用它可以訪問MCS-51內(nèi)部的所有特殊功能存放器;sfr16為雙字節(jié)型特殊功能存放器類型,占用兩個字節(jié)單元,利用它可以訪問MCS-51內(nèi)部的所有兩個字節(jié)的特殊功能存放器。在C51中對特殊功能存放器的訪問必須先用sfr或sfr16進(jìn)行聲明。4.2.7 位類型這也是C51中擴(kuò)充的數(shù)據(jù)類型,用于訪問MCS-51單片機(jī)中的可尋址的位單元。在C51中,支持兩種位類型:bit型和sbit型。它們在內(nèi)存中都只占一個二進(jìn)制位,其值可以是
13、“1或“0。其中用bit定義的位變量在C51編譯器編譯時,在不同的時候位地址是可以變化的,而用sbit定義的位變量必須與MCS-51單片機(jī)的一個可以尋址位單元或可位尋址的字節(jié)單元中的某一位聯(lián)系在一起,在C51編譯器編譯時,其對應(yīng)的位地址是不可變化的。在C51語言程序中,有可能會出現(xiàn)在運算中數(shù)據(jù)類型不一致的情況。C51允許任何標(biāo)準(zhǔn)數(shù)據(jù)類型的隱式轉(zhuǎn)換,隱式轉(zhuǎn)換的優(yōu)先級順序如下:bitcharintlongfloatsignedunsigned也就是說,當(dāng)char型與int型進(jìn)行運算時,先自動對char型擴(kuò)展為int型,然后與int型進(jìn)行運算,運算結(jié)果為int型。C51除了支持隱式類型轉(zhuǎn)換外,還可以
14、通過強(qiáng)制類型轉(zhuǎn)換符“對數(shù)據(jù)類型進(jìn)行人為的強(qiáng)制轉(zhuǎn)換。C5l編譯器除了能支持以上這些根本數(shù)據(jù)類型之外,還能支持一些復(fù)雜的組合型數(shù)據(jù)類型,如數(shù)組類型、指針類型、結(jié)構(gòu)類型、聯(lián)合類型等這些復(fù)雜的數(shù)據(jù)類型。 4.3.1 常量常量是指在程序執(zhí)行過程中其值不能改變的量。在C51中支持整型常量、浮點型常量、字符型常量和字符串型常量。1整型常量整型常量也就是整型常數(shù),根據(jù)其值范圍在計算機(jī)中分配不同的字節(jié)數(shù)來存放。在C51中它可以表示成以下幾種形式: 十進(jìn)制整數(shù):如234、-56、0等。 十六進(jìn)制整數(shù):以0 x開頭表示,如0 x12表示十六進(jìn)制數(shù),相當(dāng)十進(jìn)制18。長整型數(shù):在C51中當(dāng)一個整數(shù)的值到達(dá)長整型數(shù)的范圍
15、,那么該數(shù)按長整型數(shù)存放,在存儲器中占四個字節(jié),另外,如一個整數(shù)后面加一個字母L,這個數(shù)在存儲器中也按長整型存放。如123L在存儲器中占四個字節(jié)。2浮點型常量 浮點型常量也就是實型常數(shù)。有十進(jìn)制表示形式和指數(shù)表示形式。 十進(jìn)制表示形式又稱浮點表示形式,由數(shù)字和小數(shù)點組成。如0.123、34.645等都是十進(jìn)制數(shù)表示形式的浮點型常量。 指數(shù)表示形式為: 數(shù)字 .數(shù)字 e 數(shù)字 例如:123.456e-3、-3.123e2等都是指數(shù)形式的浮點型常量。3字符型常量字符型常量是用單引號引起的字符,如、a、1、F等??梢允强娠@示的ASCII字符,也可以是不可顯示的控制字符。對不可顯示的控制字符須在前面加
16、上反斜“組成轉(zhuǎn)義字符。利用它可以完成一些特殊功能和輸出時的格式控制。常用的轉(zhuǎn)義字符如表4.1所示。4字符串型常量字符串型常量由雙引號括起的字符組成。如“D、“1234、“ABCD等。注意字符串常量與字符常量是不一樣,一個字符常量在計算機(jī)內(nèi)只用一個字節(jié)存放,而一個字符串常量在內(nèi)存中存放時不僅雙引號內(nèi)的字符一個占一個字節(jié),而且系統(tǒng)會自動的在后面加一個轉(zhuǎn)義字符“o作為字符串結(jié)束符。因此不要將字符常量和字符串常量混淆,如字符常量A和字符串常量“A是不一樣的。4.3.2 變量變量是在程序運行過程中其值可以改變的量。一個變量由兩局部組成:變量名和變量值。在C51中,變量在使用前必須對其進(jìn)行定義,指出變量的
17、數(shù)據(jù)類型和存儲模式。以便編譯系統(tǒng)為它分配相應(yīng)的存儲單元。定義的格式如下: 存儲種類 數(shù)據(jù)類型說明符 存儲器類型 變量名1=初值,變量名2=初值;1數(shù)據(jù)類型說明符在定義變量時,必須通過數(shù)據(jù)類型說明符指明變量的數(shù)據(jù)類型,指明變量在存儲器中占用的字節(jié)數(shù)。可以是根本數(shù)據(jù)類型說明符,也可以是組合數(shù)據(jù)類型說明符,還可以是用typedef定義的類型別名。在C51中,為了增加程序的可讀性,允許用戶為系統(tǒng)固有的數(shù)據(jù)類型用說明符typedef或#define起別名,格式如下: typedef c51固有的數(shù)據(jù)類型說明符 別名; 定義別名后,就可以用別名代替數(shù)據(jù)類型說明符對變量進(jìn)行定義。別名可以用大寫,也可以用小寫
18、,為了區(qū)別一般用大寫字母表示。 例4.1 typedef和#define的使用。typedef unsigned int WORD#define BYTE unsigned charBYTE a1=0 xff; WORD a2=0 xffff;2變量名變量名是C51區(qū)分不同變量,為不同變量取的名稱。在C51中規(guī)定變量名可以由字母、數(shù)字和下劃線三種字符組成,且第一個字母必須為字母或下劃線。變量名有兩種:普通變量名和指針變量名。它們的區(qū)別是指針變量名前面要帶“*號。3存儲種類存儲種類是指變量在程序執(zhí)行過程中的作用范圍。C51變量的存儲種類有四種,分別是自動(auto)、外部(extern)、靜態(tài)(
19、static)和存放器(register)。(1) auto: 使用auto定義的變量稱為自動變量,其作用范圍在定義它的函數(shù)體或復(fù)合語句內(nèi)部,當(dāng)定義它的函數(shù)體或復(fù)合語句執(zhí)行時,C51才為該變量分配內(nèi)存空間,結(jié)束時占用的內(nèi)存空間釋放。自動變量一般分配在內(nèi)存的堆??臻g中。定義變量時,如果省略存儲種類,那么該變量默認(rèn)為自動(auto)變量。(2) extern:使用extern定義的變量稱為外部變量。在一個函數(shù)體內(nèi),要使用一個已在該函數(shù)體外或別的程序中定義過的外部變量時,該變量在該函數(shù)體內(nèi)要用extern說明。外部變量被定義后分配固定的內(nèi)存空間,在程序整個執(zhí)行時間內(nèi)都有效,直到程序結(jié)束才釋放。(3)
20、 static:使用static定義的變量稱為靜態(tài)變量。它又分為內(nèi)部靜態(tài)變量和外部靜態(tài)變量。在函數(shù)體內(nèi)部定義的靜態(tài)變量為內(nèi)部靜態(tài)變量,它在對應(yīng)的函數(shù)體內(nèi)有效,一直存在,但在函數(shù)體外不可見,這樣不僅使變量在定義它的函數(shù)體外被保護(hù),還可以實現(xiàn)當(dāng)離開函數(shù)時值不被改變。外部靜態(tài)變量是在函數(shù)外部定義的靜態(tài)變量。它在程序中一直存在,但在定義的范圍之外是不可見的。如在多文件或多模塊處理中,外部靜態(tài)變量只在文件內(nèi)部或模塊內(nèi)部有效。(4) register:使用register定義的變量稱為存放器變量。它定義的變量存放在CPU內(nèi)部的存放器中,處理速度快,但數(shù)目少。C51編譯器編譯時能自動識別程序中使用頻率最高的
21、變量,并自動將其作為存放器變量,用戶可以無需專門聲明。(5) 存儲器類型存儲器類型是用于指明變量所處的單片機(jī)的存儲器區(qū)域情況。存儲器類型與存儲種類完全不同。C51編譯器能識別的存儲器類型有以下幾種,如表4.2所示。例4.2 定義變量存儲種類和存儲器類型 char data var1;/ 定義變量var1在片內(nèi)RAM低128字節(jié) int idata var2;/ 定義變量var2在片內(nèi)RAM256字節(jié)內(nèi) int code var3;/ 定義變量var3在片外ROM unsigned char bdata var4;/ 定義變量var4在片內(nèi)位尋址區(qū) (6) 特殊功能存放器變量MCS-51系列單片
22、機(jī)片內(nèi)有許多特殊功能存放器,通過這些特殊功能存放器可以控制MCS-51系列單片機(jī)的定時器、計數(shù)器、串口、I/O及其它功能部件,每一個特殊功能存放器在片內(nèi)RAM中都對應(yīng)于一個字節(jié)單元或兩個字節(jié)單元。在C51中,允許用戶對這些特殊功能存放器進(jìn)行訪問,訪問時須通過sfr或sfr16類型說明符進(jìn)行定義,定義時須指明它們所對應(yīng)的片內(nèi)RAM單元的地址。格式如下: sfr或sfr16 特殊功能存放器名=地址;sfr用于對MCS-51單片機(jī)中單字節(jié)的特殊功能存放器進(jìn)行定義,sfr16用于對雙字節(jié)特殊功能存放器進(jìn)行定義。特殊功能存放器名一般用大寫字母表示,地址一般用直接地址形式。例4.3 定義變量是特殊功能存放
23、器類型sfr PSW=0 xd0; sfr SCON=0 x98;sfr TMOD=0 x89;sfr P1=0 x90;sfr DPTR=0 x82;sfr T0=0 x8a;由于Keil C51在頭文件“reg51.h中已將MCS-51單片機(jī)中所有特殊功能存放器進(jìn)行了定義,我們在程序中只要引進(jìn)該頭文件,特殊功能存放器就不用定義而直接使用了,但要注意特殊功能存放器名要用大寫字母表示。(7) 位變量在C51中,允許用戶通過位類型符定義位變量。位類型符有兩個:bit和sbit??梢远x兩種位變量。bit位類型符用于定義一般的可位處理位變量。它的格式如下:bit 位變量名;在格式中可以加上各種修飾
24、,但注意存儲器類型只能是bdata、data、idata。只能是片內(nèi)RAM的可位尋址區(qū),即只能是bdata。sbit位類型符用于定義在可位尋址字節(jié)或特殊功能存放器中的位,定義時須指明其位地址,可以是位直接地址,可以是可位尋址變量帶bit位號,也可以是特殊功能存放器名帶bit位號。格式如下:sbit 位變量名=位地址;如位地址為位直接地址,其取值范圍為0 x000 xff;如位地址是可位尋址變量帶bit位號或特殊功能存放器名帶bit位號,那么在它前面須對可位尋址變量或特殊功能存放器進(jìn)行定義。字節(jié)地址與bit位號之間、特殊功能存放器與bit位號之間一般用“作間隔。例4.4 bit 和sbit位變量
25、定義bit bdata b; /定義b是bdata區(qū)位變量sbit P1=0 x90; /定義特殊功能存放器P1地址sbit P1_0=P10; /定義特殊功能存放器P1的各位sbit P1_1=P11;sbit P1_2=P12;sbit P1_3=P13;sbit P1_4=P14;sbit P1_5=P15;sbit P1_6=P16;sbit P1_7=P17;4.3.3 存儲模式C51編譯器支持三種存儲模式:SMALL模式、COMPACT模式和LARGE模式。不同的存儲模式對變量默認(rèn)的存儲器類型不一樣。 1SMALL模式。SMALL模式稱為小編譯模式,在SMALL模式下,編譯時,函數(shù)
26、參數(shù)和變量被默認(rèn)在片內(nèi)RAM中,存儲器類型為data。程序代碼不能超過2K,SMALL模式常用在教學(xué)實驗系統(tǒng)的一個具體實驗中。 2COMPACT模式。COMPACT模式稱為緊湊編譯模式,在COMPACT模式下,編譯時,函數(shù)參數(shù)和變量被默認(rèn)在片外RAM的低256字節(jié)空間,存儲器類型為pdata。 3LARGE模式。LARGE模式稱為大編譯模式,在LARGE模式下,編譯時函數(shù)參數(shù)和變量被默認(rèn)在片外RAM的64K字節(jié)空間,存儲器類型為xdata。在實際嵌入式控制系統(tǒng)設(shè)計中只能使用LARGE模式。在程序中,變量的存儲模式的指定通過#pragma預(yù)處理命令來實現(xiàn)。函數(shù)的存儲模式可通過在函數(shù)定義時后面帶存
27、儲模式說明。如果沒有指定,那么系統(tǒng)隱含為SMALL模式。但我們大多都是在建立工程時在開發(fā)環(huán)境中設(shè)定參見圖1.11 編譯選大模式對話框4.3.4 絕對地址的訪問1使用C51運行庫中預(yù)定義宏IBP-PC機(jī)對外部設(shè)備進(jìn)行端口管理,Keil C51也是這樣,為了能對外部設(shè)備進(jìn)行I/O操作,C51編譯器提供了一組宏定義來對51系列單片機(jī)的code、data、pdata和xdata空間進(jìn)行絕對尋址。規(guī)定只能以無符號數(shù)方式訪問,定義了8個宏定義,其函數(shù)原型如下:#define CBYTE(unsigned char volatile*)0 x50000L)#define DBYTE(unsigned cha
28、r volatile*)0 x40000L)#define PBYTE(unsigned char volatile*)0 x30000L)#define XBYTE(unsigned char volatile*)0 x10000L)#define CWORD(unsigned int volatile*)0 x50000L)#define DWORD(unsigned int volatile*)0 x40000L)#define PWORD(unsigned int volatile*)0 x30000L)#define XWORD(unsigned int volatile*)0 x2
29、0000L)這些函數(shù)原型放在absacc.h文件中。使用時須用預(yù)處理命令把該頭文件包含到文件中,形式為:#include 。其中:CBYTE以字節(jié)形式對code區(qū)尋址,DBYTE以字節(jié)形式對data區(qū)尋址,PBYTE以字節(jié)形式對pdata區(qū)尋址,XBYTE以字節(jié)形式對xdata區(qū)尋址,CWORD以字形式對code區(qū)尋址,DWORD以字形式對data區(qū)尋址,PWORD以字形式對pdata區(qū)尋址,XWORD以字形式對xdata區(qū)尋址。訪問形式如下: 宏名地址宏名為CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD或XWORD。地址為存儲單元的絕對地址,一般用十六進(jìn)制
30、形式表示。8個宏中,使用最多的是XBYTE,XBYTE被定義在(unsigned char volatile*)0 x10000L,其中的數(shù)字1代表外部數(shù)據(jù)存儲區(qū),偏移量是0000,這樣XBYTE就成了指向xdata 0地址的指針。我們在使用這些宏時對此細(xì)節(jié)不必深究,在程序中引入absacc.h頭文件,就可以很簡單的使用它們。2通過指針訪問采用指針的方法,可以實現(xiàn)在C51程序中對任意指定的存儲器單元進(jìn)行訪問。3使用C51擴(kuò)展關(guān)鍵字_at_使用_at_對指定的存儲器空間的絕對地址進(jìn)行訪問,一般格式如下: 存儲器類型 數(shù)據(jù)類型說明符 變量名 _at_ 地址常數(shù);其中,存儲器類型為data、bdat
31、a、idata、pdata等C51能識別的存儲器類型,如省略那么按存儲模式規(guī)定的默認(rèn)存儲器類型確定變量的存儲器區(qū)域;數(shù)據(jù)類型為C51支持的數(shù)據(jù)類型。地址常數(shù)用于指定變量的絕對地址,必須位于有效的存儲器空間之內(nèi);使用_at_定義的變量必須為全局變量。例4.5使用absacc.h文件中宏定義絕對地址訪問#include#include#define PortA XBYTEox007c /定義并行接口芯片8255A端口A地址#define PortB XBYTEox007d /定義并行接口芯片8255A端口B地址#define PortC XBYTEox007e /定義并行接口芯片8255A端口C地
32、址#define PortCtrl XBYTEox007f /定義并行接口芯片8255A控制端口地址main() unsigned char i;PortCtrl=0 x82;/ 控制端口賦初值PortA=0 x80;/ 端口A輸出i= PortB;/ 端口B輸入例4.6 使用C51擴(kuò)展關(guān)鍵字_at_絕對地址訪問xdata unsigned char PortA _at_ 0 x8000 ; /定義并行接口芯片8255A端口A地址xdata unsigned char PortB _at_ 0 x8001 ; /定義并行接口芯片8255A端口B地址xdata unsigned char Por
33、tC _at_ 0 x8002 ; /定義并行接口芯片8255A端口C地址定義之后,就可以對端口進(jìn)行讀寫操作,例如,unsigned char i;i=PortA; 讀 PortB=i;寫等等。在嵌入式控制系統(tǒng)設(shè)計中,絕對地址訪問是我們常使用的操作。4.4.1 賦值運算符賦值運算符“=,在C51中,它的功能是將右側(cè)一個數(shù)據(jù)的值賦給左側(cè)一個變量,如x=10。利用賦值運算符將一個變量與一個表達(dá)式連接起來的式子稱為賦值表達(dá)式,在賦值表達(dá)式的后面加一個分號“;就構(gòu)成了賦值語句,一個賦值語句的格式如下: 變量=表達(dá)式;執(zhí)行時先計算出右邊表達(dá)式的值,然后賦給左邊的變量。例如: x=8+9; /將8+9的值
34、賦紿變量x x=y=5; /將常數(shù)5同時賦給變量x和y在C51中,允許在一個語句中同時給多個變量賦值,賦值順序自右向左。 4.4.2 算術(shù)運算符C51中支持的算術(shù)運算符有:+ 加或取正值運算符- 減或取負(fù)值運算符* 乘運算符/ 除運算符% 取余運算符加、減、乘運算相比照較簡單,而對于除運算,如相除的兩個數(shù)為浮點數(shù),那么運算的結(jié)果也為浮點數(shù),如相除的兩個數(shù)為整數(shù),那么運算的結(jié)果也為整數(shù),即為整除。如25.0/20.0結(jié)果為1.25,而25/20結(jié)果為1。對于取余運算,那么要求參加運算的兩個數(shù)必須為整數(shù),運算結(jié)果為它們的余數(shù)。例如:x=5%3,結(jié)果x的值為2。4.4.3 關(guān)系運算符C51中有6種關(guān)
35、系運算符: 大于= 大于等于3,結(jié)果為真1,而10= =100,結(jié)果為假0。注意:關(guān)系運算符等于“= =是由兩個“=組成。4.4.4 邏輯運算符C51有3種邏輯運算符:| 邏輯或& 邏輯與! 邏輯非關(guān)系運算符用于反映兩個表達(dá)式之間的大小關(guān)系,邏輯運算符那么用于求條件式的邏輯值,用邏輯運算符將關(guān)系表達(dá)式或邏輯量連接起來的式子就是邏輯表達(dá)式。 邏輯與,格式: 條件式1 & 條件式2當(dāng)條件式1與條件式2都為真時結(jié)果為真非0值,否那么為假0值。邏輯或,格式: 條件式1 | 條件式2當(dāng)條件式1與條件式2都為假時結(jié)果為假0值,否那么為真非0值。邏輯非,格式: !條件式當(dāng)條件式原來為真非0值,邏輯非后結(jié)果為
36、假0值。當(dāng)條件式原來為假0值,邏輯非后結(jié)果為真非0值。例如:假設(shè)a=8,b=3,c=0,那么!a為假,a & b為真,b & c為假。 4.4.5 位運算符C51語言能對運算對象按位進(jìn)行操作,它與匯編語言使用一樣方便。位運算是按位對變量進(jìn)行運算,但并不改變參與運算的變量的值。如果要求按位改變變量的值,那么要利用相應(yīng)的賦值運算。C51中位運算符只能對整數(shù)進(jìn)行操作,不能對浮點數(shù)進(jìn)行操作。C51中的位運算符有:& 按位與| 按位或 按位異或 按位取反 右移4.4.6 復(fù)合賦值運算符C51語言中支持在賦值運算符“=的前面加上其它運算符,組成復(fù)合賦值運算符。下面是C51中支持的復(fù)合賦值運算符:+= 加法
37、賦值 + 減法賦值*= 乘法賦值 /= 除法賦值%= 取模賦值 &= 邏輯與賦值|= 邏輯或賦值 = 邏輯異或賦值= 邏輯非賦值 = 右移位賦值=2相當(dāng)于x=x2。4.4.7 逗號運算符在C51語言中,逗號“,是一個特殊的運算符,可以用它將兩個或兩個以上的表達(dá)式連接起來,稱為逗號表達(dá)式。逗號表達(dá)式的一般格式為: 表達(dá)式1,表達(dá)式2,表達(dá)式n 程序執(zhí)行時對逗號表達(dá)式的處理:按從左至右的順序依次計算出各個表達(dá)式的值,而整個逗號表達(dá)式的值是最右邊的表達(dá)式表達(dá)式n的值。例如:x=(a=3,6*3)結(jié)果x的值為18。4.4.8 條件運算符條件運算符“?:是C51語言中唯一的一個三目運算符,它要求有三個運
38、算對象,用它可以將三個表達(dá)式連接在一起構(gòu)成一個條件表達(dá)式。條件表達(dá)式的一般格式為: 邏輯表達(dá)式?表達(dá)式1:表達(dá)式2其功能是先計算邏輯表達(dá)式的值,當(dāng)邏輯表達(dá)式的值為真非0值時,將計算的表達(dá)式1的值作為整個條件表達(dá)式的值;當(dāng)邏輯表達(dá)式的值為假0值時,將計算的表達(dá)式2的值作為整個條件表達(dá)式的值。例如:條件表達(dá)式max=(ab)?a:b的執(zhí)行結(jié)果是將a和b中較大的數(shù)賦值給變量max。4.4.9 指針與地址運算符指針是C51語言中的一個十分重要的概念,在C51中的數(shù)據(jù)類型中專門有一種指針類型。指針為變量的訪問提供了另一種方式,變量的指針就是該變量的地址,還可以定義一個專門指向某個變量的地址的指針變量。為
39、了表示指針變量和它所指向的變量地址之間的關(guān)系,C51中提供了兩個專門的運算符:* 指針運算符& 取地址運算符指針運算符“*放在指針變量前面,通過它實現(xiàn)訪問以指針變量的內(nèi)容為地址所指向的存儲單元。例如:指針變量p中的地址為0 x2000,那么*p所訪問的是地址為0 x2000的存儲單元,x=*p,實現(xiàn)把地址為0 x2000的存儲單元的內(nèi)容送給變量x。取地址運算符“&放在變量的前面,通過它取得變量的地址,變量的地址通常送給指針變量。例如:設(shè)變量x的內(nèi)容為0 x12,地址為0 x2000,那么&x的值為0 x2000,如有一指針變量p,那么通常用p=&x,實現(xiàn)將x變量的地址送給指針變量p,指針變量p
40、指向變量x,以后可以通過*p訪問變量x。4.5.1 表達(dá)式語句在表達(dá)式的后邊加一個分號“;就構(gòu)成了表達(dá)式語句 4.5.2 復(fù)合語句復(fù)合語句是由假設(shè)干條語句組合而成的一種語句,在C51中,用一個大括號“將假設(shè)干條語句括在一起就形成了一個復(fù)合語句,復(fù)合語句最后不需要以分號“;結(jié)束,但它內(nèi)部的各條語句仍需以分號“;結(jié)束。復(fù)合語句的一般形式為:局部變量定義;語句l;語句2;復(fù)合語句在執(zhí)行時,其中的各條單語句按順序依次執(zhí)行,整個復(fù)合語句在語法上等價于一條單語句,因此在C51中可以將復(fù)合語句視為一條單語句。通常復(fù)合語句出現(xiàn)在函數(shù)中,實際上,函數(shù)的執(zhí)行局部即函數(shù)體就是一個復(fù)合語句;復(fù)合語句中的單語句一般是可
41、執(zhí)行語句,此外還可以是變量的定義語句說明變量的數(shù)據(jù)類型。在復(fù)合語句內(nèi)部語句所定義的變量,稱為該復(fù)合語句中的局部變量,它僅在當(dāng)前這個復(fù)合語句中有效。利用復(fù)合語句將多條單語句組合在起,以及在復(fù)合語句中進(jìn)行局部變量定義是C51語言的一個重要特征。4.6 C51的輸入輸出在C51語言中,它本身不提供輸入和輸出語句,輸入和輸出操作是由函數(shù)來實現(xiàn)的。在C51的標(biāo)準(zhǔn)函數(shù)庫中提供了一個名為“stdio.h的一般I/O函數(shù)庫,它當(dāng)中定義了C51中的輸入和輸出函數(shù)。當(dāng)對輸入和輸出函數(shù)使用時,須先用預(yù)處理命令“#include 將該函數(shù)庫包含到文件中。在C51的一般I/O函數(shù)庫中定義的I/O函數(shù)都是通過串行接口實現(xiàn)
42、,在使用I/O函數(shù)之前,應(yīng)先對MCS-51單片機(jī)的串行接口進(jìn)行初始化。選擇串口工作方式1,波特率由定時器/計數(shù)器1溢出率定時器/計數(shù)器1工作在8位自動重載方式?jīng)Q定。C51的輸入輸出函數(shù)主要有兩個,一個是格式輸出函數(shù)printf,它主要通過串口向CRT輸出各種程序運行信息;一個是格式輸入函數(shù)scanf, 它主要是通過鍵盤向系統(tǒng)輸入數(shù)據(jù)或命令。但它們僅在程序調(diào)試時在“宿主機(jī)上使用。在“目標(biāo)機(jī)上,由于嵌入式控制系統(tǒng)大多具有小、巧、輕、靈、薄的特點,輸入設(shè)備簡單,顯示設(shè)備大多用LCD,LCD驅(qū)動有專門的程序,在本書第5篇對此有詳細(xì)討論。因此,這兩個輸入輸出函數(shù)在實際系統(tǒng)中用的不多。4.6.1 格式輸出
43、函數(shù)printf()printf()函數(shù)的的作用是通過串行接口向CRT輸出假設(shè)干任意類型的數(shù)據(jù),它的格式如下:printf(格式控制,輸出參數(shù)表)格式控制是用雙引號括起來的字符串,也稱轉(zhuǎn)換控制字符串,它包括三種信息:格式說明符、普通字符和轉(zhuǎn)義字符。1格式說明符,由“%和格式字符組成,它的作用是用于指明輸出的數(shù)據(jù)的格式輸出,如%d、%f等,它們的具體情況見表4.3。2普通字符,這些字符按原樣輸出,用來輸出某些提示信息。3轉(zhuǎn)義字符,就是前面介紹的轉(zhuǎn)義字符表4.1,用來輸出特定的控制符,如輸出轉(zhuǎn)義字符n就是使輸出換一行。輸出參數(shù)表是需要輸出的一組數(shù)據(jù),可以是表達(dá)式。4.6.2 格式輸入函數(shù)scanf
44、scanf函數(shù)的作用是通過串行接口實現(xiàn)數(shù)據(jù)輸入,它的使用方法與printf類似,scanf的格式如下:scanf格式控制,地址列表格式控制與printf函數(shù)的情況類似,也是用雙引號括起來的一些字符,可以包括以下三種信息:空白字符、普通字符和格式說明。空白字符,包含空格、制表符、換行符等,這些字符在輸出時被忽略。1普通字符,除了以百分號“%開頭的格式說明符而外的所有非空白字符,在輸入時要求原樣輸入。2格式說明,由百分號“%和格式說明符組成,用于指明輸入數(shù)據(jù)的格式,它的根本情況與printf相同,具體情況參見表4.4。3地址列表是由假設(shè)干個地址組成,它可以是指針變量、取地址運算符“&加變量變量的地
45、址或字符串名表示字符串的首地址。例4.7 使用格式輸入輸出函數(shù)的例子main() int a,b,c,d;long m,n;/串口初始化略scanf(“%d,%o,%x,%u,&a,&b,&c,&d);scanf(“%ld,%lx,&m,&n);printf(“a=%d,b=%d,a,b)printf(“c=%d,d=%dn,c,d);printf(“m=%ld,n=%ldn,m,n);程序運行結(jié)果:運行到第一個和第二個scanf語句停止,等待輸入,我們輸入:100,100,100,65525123456789,10000顯示屏輸出:a=100,b=64,c=256,d=-11m=123456
46、789,n=65536格式輸入函數(shù)scanf和格式輸出函數(shù)printf更詳細(xì)內(nèi)容可參考C語言教材相關(guān)章節(jié)。4.7.1 C51的根本結(jié)構(gòu)1順序結(jié)構(gòu)順序結(jié)構(gòu)是最根本、最簡單的結(jié)構(gòu),在這種結(jié)構(gòu)中,程序由低地址到高地址依次執(zhí)行。具體如圖4.1所示,程序先執(zhí)行語句A,然后再執(zhí)行語句B。2選擇結(jié)構(gòu)選擇結(jié)構(gòu)可使程序根據(jù)不同的情況,選擇執(zhí)行不同的分支,在選擇結(jié)構(gòu)中,程序先對一個條件進(jìn)行判斷。當(dāng)條件成立,即條件語句為“真時,執(zhí)行一個分支,當(dāng)條件不成立時,即條件語句為“假時,執(zhí)行另一個分支。在C51中,實現(xiàn)選擇結(jié)構(gòu)的語句為if/else,if/else if語句。另外在C51中還支持多分支結(jié)構(gòu),多分支結(jié)構(gòu)既可以通
47、過if和else if語句嵌套實現(xiàn),可用swith/case語句實現(xiàn)。選擇程序結(jié)構(gòu)具體如圖4.2所示。3循環(huán)結(jié)構(gòu)在程序處理過程中,有時需要某一段程序重復(fù)執(zhí)行屢次,這時就需要循環(huán)結(jié)構(gòu)來實現(xiàn),循環(huán)結(jié)構(gòu)就是能夠使程序段重復(fù)執(zhí)行的結(jié)構(gòu)。循環(huán)結(jié)構(gòu)又分為兩種:當(dāng)while型循環(huán)結(jié)構(gòu)和直到do.while型循環(huán)結(jié)構(gòu)。 1當(dāng)型循環(huán)結(jié)構(gòu) 當(dāng)型循環(huán)結(jié)構(gòu)如圖4.3,當(dāng)條件P成立為“真時,重復(fù)執(zhí)行語句A,當(dāng)條件不成立為“假時才停止重復(fù),執(zhí)行后面的程序。2直到型循環(huán)結(jié)構(gòu) 直到型循環(huán)結(jié)構(gòu)如圖4.4,先執(zhí)行語句A,再判斷條件P,當(dāng)條件成立為“真時,再重復(fù)執(zhí)行語句A,直到條件不成立為“假時才停止重復(fù),執(zhí)行后面的程序。4.7.
48、2 if語句if語句是C51中的一個根本條件選擇語句,它通常有三種格式:1if 表達(dá)式 語句;2if 表達(dá)式 語句1; else 語句2;3if 表達(dá)式1 語句1;else if 表達(dá)式2 語句2;else if 表達(dá)式3 語句3;else if表達(dá)式n-1 語句n-1;else 語句n例4.8 if 語句的使用if (score=90) printf(“You result is an An);else if (score=80) printf(“You result is an Bn);else if (score=70) printf(“You result is an Cn);else
49、 if (score=60) printf(“You result is an Dn);else printf(“You result is an En);執(zhí)行以上程序后,就可以根據(jù)分?jǐn)?shù),分別打出A,B,C,D,E五個等級。4.7.3 switch/case語句if語句通過嵌套可以實現(xiàn)多分支結(jié)構(gòu),但結(jié)構(gòu)復(fù)雜。switch是C51中提供的專門處理多分支結(jié)構(gòu)的多分支選擇語句。它的格式如下:switch 表達(dá)式case 常量表達(dá)式1:語句1;break;case 常量表達(dá)式2:語句2;break;case 常量表達(dá)式n:語句n;break;default:語句n+1;說明如下:1switch后面括號
50、內(nèi)的表達(dá)式,可以是整型或字符型表達(dá)式。2當(dāng)該表達(dá)式的值與某一“case后面的常量表達(dá)式的值相等時,就執(zhí)行該“case后面的語句,然后遇到break語句退出switch語句。假設(shè)表達(dá)式的值與所有case后的常量表達(dá)式的值都不相同,那么執(zhí)行default后面的語句,然后退出switch結(jié)構(gòu)。3每一個case常量表達(dá)式的值必須不同否那么會出現(xiàn)自相矛盾的現(xiàn)象。4case語句和default語句的出現(xiàn)次序?qū)?zhí)行過程沒有影響。5每個case語句后面可以有“break,也可以沒有。有break語句,執(zhí)行到break那么退出switch結(jié)構(gòu),假設(shè)沒有,那么會順次執(zhí)行后面的語句,直到遇到break或結(jié)束。6每一
51、個case語句后面可以帶一個語句,也可以帶多個語句,還可以不帶。語句可以用花括號括起,也可以不括。7多個case可以共用一組執(zhí)行語句。例4.9 switch/case語句的使用#includemain()float a,b;char c;printf(“input expression:a+(-,*,/)bn););scanf(“%f%c%f,&a,&c,&b);switch(c) case+:printf(“%fn,a+b);break; case-:printf(“%fn,a-b);break; case*:printf(“%fn,a*b);break; case/:printf(“%fn
52、,a/b);break; default: printf(“input errorn);4.7.4 while語句while語句在C51中用于實現(xiàn)當(dāng)型循環(huán)結(jié)構(gòu),它的格式如下: while表達(dá)式 語句; /循環(huán)體while語句后面的表達(dá)式是能否循環(huán)的條件,后面的語句是循環(huán)體。當(dāng)表達(dá)式為非0真時,就重復(fù)執(zhí)行循環(huán)體內(nèi)的語句;當(dāng)表達(dá)式為0假,那么中止while循環(huán),程序?qū)?zhí)行循環(huán)結(jié)構(gòu)之外的下一條語句。它的特點是:先判斷條件,后執(zhí)行循環(huán)體。在循環(huán)體中對條件進(jìn)行改變,然后再判斷條件,如條件成立,那么再執(zhí)行循環(huán)體,如條件不成立,那么退出循環(huán)。如條件第一次就不成立,那么循環(huán)體一次也不執(zhí)行。 例4.10 while語句的使用#includemain() int sum=0,i=1; while (i=100) sum=sum+i; i+; printf(“1+2+3+100=%dn,sum);程序運行結(jié)果:1+2+3+100=50504.7.5 do while語句do while語句在C51
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 煤礦機(jī)器人與自動化
- 老年人用藥,莫“跟著感覺走”
- 2025年遼寧高校畢業(yè)生“三支一扶”計劃考試筆試試題(含答案)
- 2025年江蘇鹽城市射陽縣城市照明服務(wù)有限公司聘考試筆試試題(含答案)
- 老年疾病護(hù)理
- 老年護(hù)理溝通課件
- 車輛質(zhì)押擔(dān)保貸款服務(wù)合同樣本
- 美容美發(fā)場地租賃合同終止及客戶服務(wù)協(xié)議
- 戀愛期間情感關(guān)懷與財產(chǎn)管理協(xié)議
- 專業(yè)辦公租賃及企業(yè)孵化服務(wù)合同
- 初中學(xué)校教學(xué)常規(guī)培訓(xùn)
- 咖啡拉花培訓(xùn)課程
- 2024年度醫(yī)患溝通課件
- 消化道腫瘤患者的護(hù)理
- 廣東省2024年普通高中學(xué)業(yè)水平合格性考試化學(xué)(一)試題附參考答案(解析)
- 2023年崗位知識-銀行信息科技條線知識考試沖刺-歷年真題演練帶答案
- JB-T 14227-2022 流砂過濾器標(biāo)準(zhǔn)
- 石行業(yè)安全事故案例學(xué)習(xí)
- 更換給水水泵的施工方案
- 三叉神經(jīng)痛(講)課件
- 企業(yè)工會采購制度管理規(guī)定
評論
0/150
提交評論