《單片機原理及應(yīng)用 》課件-第3章_第1頁
《單片機原理及應(yīng)用 》課件-第3章_第2頁
《單片機原理及應(yīng)用 》課件-第3章_第3頁
《單片機原理及應(yīng)用 》課件-第3章_第4頁
《單片機原理及應(yīng)用 》課件-第3章_第5頁
已閱讀5頁,還剩152頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第3章單片機C語言開發(fā)基礎(chǔ)3.1C語言源程序的結(jié)構(gòu)特點3.2標識符和關(guān)鍵字3.3數(shù)據(jù)類型與運算符

任務(wù)3-1不同數(shù)據(jù)類型控制LED閃爍

任務(wù)3-2數(shù)據(jù)運算的LED顯示3.4C語言的語句

任務(wù)3-3用if語句控制LED的亮滅狀態(tài)

任務(wù)3-4用for語句控制LED的循環(huán)亮滅狀態(tài)第3章單片機C語言開發(fā)基礎(chǔ)3.5C語言的數(shù)組

任務(wù)3-5用字符型數(shù)組實現(xiàn)LED循環(huán)亮滅3.6C語言的函數(shù)

任務(wù)3-6用函數(shù)實現(xiàn)LED流水速度控制3.7C語言的編譯預(yù)處理

任務(wù)3-7用宏定義方式實現(xiàn)LED顯示本章小結(jié)習題

3.1C語言源程序的結(jié)構(gòu)特點

在計算機中,所有的指令、數(shù)據(jù)都是用二進制代碼來表示的。這種用二進制代碼表示的指令系統(tǒng)稱為機器語言,用機器語言編寫的程序稱為機器語言程序或“目標程序”。對于計算機,機器語言能被直接識別并快速執(zhí)行。但對于使用者,這種用機器語言編寫的程序很難識別和記憶,容易出錯。為了克服這些缺點,出現(xiàn)了匯編語言和高級語言。

匯編語言是一種用文字助記符來表示機器指令的符號語言,可以說是最接近機器碼的一種單片機編程語言,主要優(yōu)點是占用資源少,程序執(zhí)行率高,當然也由于一條指令就對應(yīng)一條機器碼,所以每一步的執(zhí)行動作都是比較清楚的,調(diào)試起來也是比較方便的。但對于程序開發(fā)來說,不同類型的單片機,其匯編語言是有差異的。程序員寫出的匯編語言程序的確有執(zhí)行效率高的優(yōu)點,但匯編語言的可移植性和可讀性差的特點,使得開發(fā)出來的產(chǎn)品在維護和功能升級時有極大的困難,從而導致整個系統(tǒng)的可靠性和可維護性比較差。

C51是針對8051系列單片機開發(fā)的高級語言。它與標準的C語言基本一致,但根據(jù)8051單片機的硬件特點作了少量的擴展和重新定義。例如,C51中定義的庫函數(shù)和標準C語言定義的庫函數(shù)不同,標準的C語言定義的庫函數(shù)是按通用微型計算機來定義的,而C51中的庫函數(shù)是按MCS-51單片機相應(yīng)情況來定義的;C51支持位變量,printf函數(shù)由串行口輸出而不是由屏幕輸出,且不同廠家的單片機為描述其硬件的差異需要使用特定的頭文件;C51與標準C在函數(shù)使用方面也有一定的區(qū)別,C51中有專門的中斷函數(shù)等。

C51主要有以下特點:

(1)語言簡潔、緊湊,使用方便、靈活;

(2)運算符極其豐富;

(3)生產(chǎn)的目標代碼質(zhì)量高,程序執(zhí)行效率高;

(4)C51程序由若干函數(shù)組成,具有良好的模塊化結(jié)構(gòu),便于改進和擴充;

(5)有豐富的庫函數(shù),可大大減少用戶的編程量,顯著縮短編程與調(diào)試時間,大大提高軟件開發(fā)效率;

(6)可以直接對硬件進行操作;

(7)程序具有良好的可讀性和可維護性。

單片機C51語言繼承了C語言的特點,其程序結(jié)構(gòu)與一般C語言結(jié)構(gòu)沒有差別。C51源程序文件擴展名為“.c”。C51程序和標準C程序結(jié)構(gòu)相同,采用函數(shù)結(jié)構(gòu)。每個C51程序由一個或多個函數(shù)組成,在這些函數(shù)中至少應(yīng)包含一個主函數(shù)main(),也可以包含一個main()函數(shù)和若干個其他的功能函數(shù)。程序的執(zhí)行總是從main()函數(shù)開始的,當主函數(shù)所有語句執(zhí)行完畢時,程序執(zhí)行完畢。

程序的開始部分一般是預(yù)處理命令、函數(shù)說明和變量定義等。

一個C51語言源程序是由一個或若干個函數(shù)組成的,每一個函數(shù)完成相對獨立的功能。每個C51程序都必須有(且僅有)一個主函數(shù)main(),程序的執(zhí)行總是從主函數(shù)開始,再調(diào)用其他函數(shù)后返回主函數(shù)main(),不管函數(shù)的排列順序如何,最后在主函數(shù)中結(jié)束整個程序。

一個函數(shù)由兩部分組成:函數(shù)定義和函數(shù)體。

函數(shù)定義部分包括函數(shù)名、函數(shù)類型、函數(shù)屬性、函數(shù)參數(shù)(形式參數(shù))名、參數(shù)類型等。對于main()函數(shù)來說,main是函數(shù)名,函數(shù)名前面的void說明函數(shù)類型(空類型,表

示沒有返回值),函數(shù)名后面必須跟一對圓括號,里面是函數(shù)的形式參數(shù)定義,如main()表示該函數(shù)沒有形式參數(shù)。

main()函數(shù)后面一對大括號內(nèi)的部分稱為函數(shù)體,函數(shù)體由定義數(shù)據(jù)類型的說明部分和實現(xiàn)函數(shù)功能的執(zhí)行部分組成。

C51語言程序中可以有一些專用的預(yù)處理命令,例如上述源程序中的“#include<reg51.h>”,預(yù)處理命令通常放在源程序的最前面。

從上面的兩個源程序我們也可以看出,C51和C語言一樣,使用“;”作為語句的結(jié)束符,一條語句可以多行書寫,也可以一行書寫多條語句。

3.2標識符和關(guān)鍵字

3.2.1標識符標識符常用來聲明某個對象的名稱,如變量和常量的聲明、數(shù)組和結(jié)構(gòu)的聲明、自定義函數(shù)的聲明以及數(shù)據(jù)類型的聲明等。示例如下:intsum;intkey;voiddelay();在上面的例子中,sum為整型變量的標識符,delay為自定義函數(shù)的標識符。

在C51語言中,標識符可以由字母、數(shù)字(0~9)或者下劃線“_”組成,最多可支持32個字符。C51標識符的第一個字符必須為字母或者下劃線,例如“unt”、“ch_2”等都是正確的,而“5count”則是錯誤的標識符。程序中對于標識符的命名應(yīng)當簡潔明了,含義清晰,便于閱讀理解,如用標識符“min”表示最小值,用“TIMER1”表示定時器1等。有些編譯系統(tǒng)專用的標識符是以下劃線開頭的,所以一般不要以下劃線開頭命名標識符,可以將下劃線用做分段符。標識符在命名時應(yīng)當簡單,含義清晰,這樣有助于閱讀和理解程序。

另外,C51的標識符區(qū)分大小寫,例如“sum”和“SUM”代表兩個不同的標識符,使用標識符時應(yīng)注意以下幾點:

?在命名C51標識符時,需要能夠清楚地表達其功能含義,這樣有助于閱讀和理解源程序。

?C51的標識符原則上可以使用下劃線開頭,但有些編譯系統(tǒng)的專用標識符或者預(yù)定義項是以下劃線開頭的,因此為了程序的兼容性和可移植性,建議一般不使用下劃線開頭來命名標識符。

?盡量不要使用過長的標識符,以便于使用和程序理解方便。

?自定義的C51標識符不能使用C51語言保留的關(guān)鍵字,也不能和用戶已使用的函數(shù)名或C51庫函數(shù)同名。例如“

char”是關(guān)鍵字,所以不能作為標識符使用。

3.2.2關(guān)鍵字

關(guān)鍵字是C51語言的重要組成部分,是編程語言保留的特殊標識符,它們具有固定名稱和含義,如int、if、for、do、while、case等。在編寫C語言源程序時一般不允許標識符的命名與關(guān)鍵字相同。在KeilμVision中的關(guān)鍵字除了有ANSIC標準的32個關(guān)鍵字外,還根據(jù)51單片機的特點擴展了相關(guān)的關(guān)鍵字。ANSIC標準的關(guān)鍵字及其擴展關(guān)鍵字分別如表3-1和表3-2所示。在C51語言程序設(shè)計中,用戶自定義的標識符不能和這些關(guān)鍵字沖突,否則無法通過編譯。

3.3數(shù)據(jù)類型與運算符

具有一定格式的數(shù)字或數(shù)值叫做數(shù)據(jù)。數(shù)據(jù)是計算機操作的對象,無論使用何種語言、算法進行程序設(shè)計,最終在計算機中運行的都是數(shù)據(jù)流,任何程序設(shè)計都離不開對于數(shù)據(jù)的處理。數(shù)據(jù)的不同存儲格式稱為數(shù)據(jù)類型,數(shù)據(jù)按一定的數(shù)據(jù)類型進行排列、組合、架構(gòu)則稱為數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)在計算機內(nèi)存中的存放情況由數(shù)據(jù)結(jié)構(gòu)決定。

3.3.1數(shù)據(jù)類型

C語言的數(shù)據(jù)結(jié)構(gòu)是以數(shù)據(jù)類型體現(xiàn)的,數(shù)據(jù)類型可分為基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型,復(fù)雜數(shù)據(jù)類型由基本數(shù)據(jù)類型構(gòu)造而成。

C語言數(shù)據(jù)類型包括:基本類型、構(gòu)造類型、指針類型以及空類型等?;绢愋陀形?bit)、字符(char)、整型(int)、短整型(short)、長整型(1ong)、浮點型(float)以及雙精度浮點型(double)等;構(gòu)造類型包括數(shù)組(array)、結(jié)構(gòu)體(struct)、共用體(union)以及枚舉類型(enum)等。

C語言中的基本數(shù)據(jù)類型有char、int、short、long、float和double。對于C51編譯器來說,short型與int型相同,double型與float型相同。C51的基本數(shù)據(jù)類型如表3-3所示。

分別說明如下:

(1)char:字符類型,通常用于定義處理字符數(shù)據(jù)的變量或常量,有signedchar和unsignedchar之分,默認為signedchar。對于signedchar型數(shù)據(jù),其字節(jié)中的最高位表示該數(shù)據(jù)的符號,“0”表示正數(shù),“1”表示負數(shù),負數(shù)用補碼表示,所能表示的數(shù)值范圍是-128~127;unsignedchar型數(shù)據(jù)是無符號字符型數(shù)據(jù),其字節(jié)中的所有位均用來表示數(shù)據(jù)的數(shù)值,所表示的數(shù)值范圍是0~255。

(2)int:整型,長度為兩個字節(jié),用于存放一個雙字節(jié)數(shù)據(jù)。int型分有符號整型數(shù)signedint和無符號整型數(shù)unsignedint,默認為signedint類型。signedint表示的數(shù)值范圍是-32768~+32767,字節(jié)中最高位表示數(shù)據(jù)的符號,“0”表示正數(shù),“1”表示負數(shù)。unsignedint表示的數(shù)值范圍是0~65535。

(3)long:長整型,有signedlong和unsignedlong之分,默認值為signedlong。它們的長度均為四個字節(jié)。singedlong是有符號的長整型數(shù)據(jù),字節(jié)中的最高位表示數(shù)據(jù)的符號,“0”表示正數(shù),“1”表示負數(shù),數(shù)值的表示范圍是-2147483648~2147483647;unsignedlong是無符號長整型數(shù)據(jù),數(shù)值的表示范圍是0~4294967295。

(4)float:浮點型,是符合IEEE754標準的單精度浮點型數(shù)據(jù),在十進制中具有7位有效數(shù)字。float型數(shù)據(jù)占用四個字節(jié)(2位二進制數(shù))。需要指出的是,對于浮點型數(shù)據(jù),除了有正常數(shù)值之外,還可能出現(xiàn)非正常數(shù)值。

(5)*:指針型,不同于以上四種基本數(shù)據(jù)類型,它本身是一個變量,在這個變量中存放的不是一般的數(shù)據(jù)而是指向另一個數(shù)據(jù)的地址。指針變量也要占據(jù)一定的內(nèi)存單元,在C51中指針變量的長度一般為1~3個字節(jié)。指針變量也具有類型,其表示方法是在指針符號“*”的前面冠以數(shù)據(jù)類型符號。如“char*point1”表示point1是一個字符型的指針變

量;“float*point2”表示point2是一個浮點型的指針變量。指針變量的類型表示該指針所指向地址中數(shù)據(jù)的類型。使用指針型變量可以方便地對8051單片機的各部分物理地址直

接進行操作。

(6)bit:位標量,是C51編譯器的一種擴充數(shù)據(jù)類型,利用它可定義一個位標量,但不能定義位指針,也不能定義位數(shù)組。它的值是一個二進制位,不是0就是1,類似于一些高級語言中的Boolean類型中的True和False。

(7)sfr:特殊功能寄存器,也是一種擴充數(shù)據(jù)類型,占用一個內(nèi)存單元,值域為0~255。利用它能訪問51單片機內(nèi)部的所有特殊功能寄存器。如用“sfrP1=0x90”定義P1為P1端口在片內(nèi)的寄存器,在后面的語句中用P1=255(對P1端口的所有引腳置高電平)之類的語句來操作特殊功能寄存器。

(8)sfr16:16位特殊功能寄存器,占用兩個內(nèi)存單元,值域為0~65535。sfr16和sfr一樣用于操作特殊功能寄存器,所不同的是它用于操作占兩個字節(jié)的寄存器,如定時器T0

和T1。

(9)sbit:可尋址位,同樣是單片機C語言中的一種擴充數(shù)據(jù)類型。利用它能訪問芯片內(nèi)部的RAM中的可尋址位或特殊功能寄存器中的可尋址位。

在C51語言程序的表達式或變量賦值運算中,有時會出現(xiàn)運算對象的數(shù)據(jù)類型不一致的情況,C語言允許任何標準數(shù)據(jù)類型之間的隱式轉(zhuǎn)換。隱式轉(zhuǎn)換按以下優(yōu)先級別自動進行:

其中,箭頭方向僅表示數(shù)據(jù)類型級別的高低,轉(zhuǎn)換時由低向高進行,而不是數(shù)據(jù)轉(zhuǎn)換時的順序。例如,將一個bit型變量賦給一個int型變量時,直接把bit型變量值轉(zhuǎn)換成int型變

量值并完成賦值運算。一般來說,如果有幾個不同類型的數(shù)據(jù)同時參加運算,先將低級別類型的數(shù)據(jù)轉(zhuǎn)換成高級別類型,再做運算處理,并且運算結(jié)果為高級別類型數(shù)據(jù)。C語言除了能對數(shù)據(jù)類型做自動的隱式轉(zhuǎn)換之外,還可以采用強制類型轉(zhuǎn)換符“()”對數(shù)據(jù)類型做顯式轉(zhuǎn)換。

強制類型轉(zhuǎn)換需要使用強制類型轉(zhuǎn)換運算符,其形式為

(類型名)(表達式);

例如,“(double)a;”表示將a強制轉(zhuǎn)換成double類型。

3.3.2常量和變量

常量是在程序運行過程中不能改變值的量,而變量是可以在程序運行過程中不斷變化的量。變量的定義可以使用所有C51編譯器支持的數(shù)據(jù)類型,而常量的數(shù)據(jù)類型只有整型、浮點型、字符型、字符串型和位標量。

1.常量

常量是指在程序執(zhí)行過程中其值不能改變的量,如固定的數(shù)據(jù)表、字庫等。C51支持整型常量、浮點型常量、字符型常量和字符串型常量。

1)整型常量

C51中整型常量可以表示成以下幾種形式:

(1)十進制整數(shù),如120、-78、0等。

(2)十六進制整數(shù),以0x開頭,如0x11表示十六進制數(shù)11H。

(3)長整數(shù)。在C51中當一個整數(shù)的值達到長整型的范圍時,該數(shù)按長整型存放,在存儲器中占四個字節(jié)。另外,如在一個整數(shù)后面加一個字母L,則這個數(shù)在存儲器中也按長整型存放,如123L在存儲器中占四個字節(jié)。

2)浮點型常量

浮點型常量也即實型常數(shù),有十進制和指數(shù)兩種表示形式。

十進制表示形式又稱定點表示形式,由數(shù)字和小數(shù)點組成,如0.123、34.645等都是十進制數(shù)表示形式的浮點型常量。

指數(shù)表示形式為

[±]數(shù)字[.數(shù)字]e[±]數(shù)字

例如,523.658e-3、-6.324e2等都是指數(shù)形式的浮點型常量。

3)字符型常量

字符型常量是加單引號的字符,如'b'、'3'、'M'等??梢允强娠@示的ASCII字符,也可以是不可顯示的控制字符。對不可顯示的控制字符須在前面加上反斜杠“\”組成轉(zhuǎn)義字符。利用它可以完成一些特殊功能和輸出時的格式控制。常用的轉(zhuǎn)義字符如表3-4所示。

4)字符串型常量

字符串型常量由雙引號括起的字符組成,如″LED″、″76″、″hello″等。字符串常量與字符常量是不一樣的,一個字符常量在計算機內(nèi)只用一個字節(jié)存放,而一個字符串常量在內(nèi)存中存放時不僅雙引號內(nèi)的字符一個占一個字節(jié),而且系統(tǒng)會自動地在后面加一個轉(zhuǎn)義字符“\0”作為字符串結(jié)束符。因此不要將字符常量和字符串常量混淆,如字符常量'A'和字符串常量″A″是不一樣的。

2.變量

編寫程序時,常常需要將數(shù)據(jù)存儲在內(nèi)存中,方便后面使用或者修改這個數(shù)據(jù)的值。因此,需要引入變量的概念。在程序運行過程中,其值可以被改變的量稱為變量。變量有以下三個要素。

?變量名:每個變量都必須有一個名字,即變量名。變量的命名規(guī)則與用戶自定義標識符的命名規(guī)則相同。

?變量值:在程序運行過程中,變量值存儲在內(nèi)存中;不同類型的變量占用的內(nèi)存單元(字節(jié))數(shù)不同。在程序中,通過變量名來引用變量值。

?變量的地址:即變量在內(nèi)存中存放其值的起始單元地址。

在C51中,使用變量前必須對變量進行定義,指出變量的數(shù)據(jù)類型和存儲模式,以便編譯系統(tǒng)為它分配相應(yīng)的存儲單元。定義的格式如下:

[存儲種類]數(shù)據(jù)類型[存儲器類型]變量名表

在定義格式中除了數(shù)據(jù)類型和變量名表是必要的,其他都是可選項。

(1)存儲種類有四種:自動(auto)、外部(extern)、靜態(tài)(static)和寄存器(register),缺省類型為自動(auto)。

(2)數(shù)據(jù)類型說明符:指明變量的數(shù)據(jù)類型。指明變量在存儲器中占用的字節(jié)數(shù);數(shù)據(jù)類型可以是基本數(shù)據(jù)類型說明符,也可以是組合數(shù)據(jù)類型說明符,還可以是用typedef或#define定義的類型別名。

在C51中,為了增加程序的可讀性,允許用戶為系統(tǒng)固有的數(shù)據(jù)類型說明符用typedef或#define起別名,格式如下:

typedefC51固有的數(shù)據(jù)類型說明符別名;

#define別名C51固有的數(shù)據(jù)類型說明符;

定義別名后,就可以用別名代替數(shù)據(jù)類型說明符對變量進行定義了。別名可以用大寫字母,也可以用小寫字母。如:

#defineucharunsignedchar

這樣,在編程中,就可以用uchar代替unsignedchar。

(3)存儲器類型:指定義變量時,根據(jù)51單片機存儲器的特點,指明該變量所處的單片機的內(nèi)存空間。

C51單片機的存儲器主要有:片內(nèi)數(shù)據(jù)存儲器、特殊功能寄存器、片外數(shù)據(jù)存儲器、片內(nèi)程序存儲器和片外程序存儲器,如表3-5所示。

使用匯編指令訪問時,依據(jù)不同的指令和不同的尋址方式即可區(qū)分存儲器類型。在C51中,則要通過定義存儲器類型來加以說明。

C51編譯器支持MCS51單片機的硬件結(jié)構(gòu),可完全訪問MCS51硬件系統(tǒng)的所有部分。

編譯器通過將變量或者常量定義成不同的存儲類型(

data、bdata、idata、pdata、xdata、code)的方法,將它們定位在不同的存儲區(qū)中。

(4)變量名表格式:

變量名1[=初值],變量名2[=初值],...

在C51中,規(guī)定變量名可以由字母、數(shù)字和下劃線三種字符組成,且第一位必須為字母或下劃線。

變量名有兩種:普通變量名和指針變量名。指針變量名前面要帶“*”號。

3.3.3運算符

運算符就是完成某種特定運算的符號。運算符按其表達式中與運算符的關(guān)系可分為單目運算符、雙目運算符和三目運算符。單目指只有一個運算對象,雙目有兩個運算對象,三目則有三個運算對象。由運算符及運算對象所組成的具有特定含義的式子稱為表達式。

1.賦值運算符

賦值運算符只有一個,即“=”。

在C中,它的功能是給變量賦值,如x=10。

賦值表達式后面加“;”號就構(gòu)成了一個賦值表達式語句。賦值運算符是右結(jié)合性,且優(yōu)先級最低。例如:

a=(b=2)+(c=3);

該表達式的值為5,變量a的值為5。

在賦值運算中,當“=”兩側(cè)的類型不一致時,要將其轉(zhuǎn)換成同一數(shù)據(jù)類型。

2.算術(shù)運算符

C51中的算術(shù)運算符如下:

+:加或取正值運算符;

-:減或取負值運算符;

*:乘運算符;

/:除運算符;

%:模(取余)運算符。

這些運算符中加、減、乘、除為雙目運算符,它們要求有兩個運算對象。例如:9%4=1,即9除以4的余數(shù)是1。

3.自增自減運算符

自增運算符為“++”;自減運算符為“--”。

自增自減運算符的作用是使變量值自動加1或減1。自增自減運算符可用在操作數(shù)之前,也可放在其后。例如,“

x=x+1”既可以寫成“++x”,也可寫成“x++”,其運算結(jié)果完全相同。但在表達式中這兩種用法是有區(qū)別的。

++i,--i:“運算符在前,先運算后使用”,即在使用i之前,先使i值加(減)1;

i++,i--:“運算符在后,先使用后運算”,即在使用i之后,再使i值加(減)1。

例如:若i值原來為4,則對于“j=++i;”語句,j值為5,i值為5;對于“j=i++;”語句,j值為4,i值為5。

一般來說,用自增和自減操作生成的程序代碼比等價的賦值語句生成的代碼運行的速度更快。

4.關(guān)系運算符

C51中有6種關(guān)系運算符:

>:大于;

<:小于;

>=:大于等于;

<=:小于等于;

==:測試等于;

!=:測試不等于。

關(guān)系和邏輯運算符的優(yōu)先級比算術(shù)運算符低,例如表達式“10>x+12”的計算,應(yīng)看做是“10>(x+12)”。

5.邏輯運算符

C51中的邏輯運算符有:

&&:邏輯與;

||:邏輯或;

!:邏輯非。

具體用法如下:

邏輯與:條件式1&&條件式2;

邏輯或:條件式1||條件式2;

邏輯非:!條件式。

6.位運算符

位運算符的作用是按位對變量進行運算,但并不改變參與運算的變量的值。位運算符不能用來對浮點型數(shù)據(jù)進行操作。位運算一般的表達形式如下:

變量1位運算符變量2

C51中共有6種位運算符(優(yōu)先級從上往下遞減):

&:按位與;

|:按位或;

^:按位異或;

~:按位取反;

<<:左移;

>>:右移。

7.復(fù)合運算符

復(fù)合運算符就是在賦值運算符“=”的前面加上其他運算符。以下是C51語言中的復(fù)合賦值運算符:

+=:加法賦值;

>>=:右移位賦值;

-=:減法賦值;

&=:邏輯與賦值;

*=:乘法賦值;

|=:邏輯或賦值;

/=:除法賦值;

^=:邏輯異或賦值;

%=:取模賦值;

~=:邏輯非賦值;

<<=:左移位賦值。

其含義就是變量與表達式先進行運算符所要求的運算,再把運算結(jié)果賦值給參與運算的變量。其實這是C語言中簡化程序的一種方法,凡是二目運算都可以用復(fù)合賦值運算符去簡化表達。例如:

8.對指針操作的運算符

對指針操作的運算符只有一個,即“&”,其又能用于按位與,此時“&”的兩邊必須有操作對象。還可作為指針變量的標志,但此時一定出現(xiàn)在對指針定義中。

9.條件運算符

C51中的條件運算符為“?:”。

條件運算符是C51語言中唯一的一個三目運算符,它要求有三個運算對象,用它可以將三個表達式連接在一起構(gòu)成一個條件表達式。條件表達式的一般格式為

邏輯表達式?表達式1:表達式2

邏輯表達式?表達式1:表達式2

其功能是先計算邏輯表達式的值,當邏輯表達式的值為真(非0值)時,將計算的表達式1的值作為整個條件表達式的值;當邏輯表達式的值為假(0值)時,將計算的表達式2的值

作為整個條件表達式的值。

例如,條件表達式“max=(a>b)?a:b”的執(zhí)行結(jié)果是將a和b中較大的數(shù)賦值給變量max。

10.強制轉(zhuǎn)換運算符

當參與運算的數(shù)據(jù)的類型不同時,先轉(zhuǎn)換成同一數(shù)據(jù)類型,再進行運算。數(shù)據(jù)類型的轉(zhuǎn)換方式有兩種:一種是自動類型轉(zhuǎn)換:另一種是強制轉(zhuǎn)換。

自動類型轉(zhuǎn)換是在對程序進行編譯時由編譯器自動處理的。自動類型轉(zhuǎn)換的基本規(guī)則是轉(zhuǎn)換后計算精度不降低,所以當char、int、unsigned、long、double類型的數(shù)據(jù)同時存在時,其轉(zhuǎn)換關(guān)系為char→int→unsigned→long→double。例如,當char型數(shù)據(jù)與int型數(shù)據(jù)共存時,先將char型轉(zhuǎn)化為int型再計算。

強制轉(zhuǎn)換是通過強制類型轉(zhuǎn)換運算符“()”進行的,其作用是將一個表達式轉(zhuǎn)化為所需類型。其一般形式為

(類型標識符)(表達式)

例如,“int(x+y)”將x+y的結(jié)果強制轉(zhuǎn)換為整型。

任務(wù)3-1不同數(shù)據(jù)類型控制LED閃爍

任務(wù)目的分別采用兩種不同的數(shù)據(jù)類型,即整型和字符型設(shè)計延時函數(shù),用同樣大小數(shù)字來控制延時時間,實現(xiàn)LED的閃爍,通過觀察閃爍現(xiàn)象來理解不同數(shù)據(jù)類型的區(qū)別。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

(1)分別采用無符號整型和無符號字符型數(shù)據(jù)類型來控制延時函數(shù)的時間。unsignedchar類型用單字節(jié)來表示數(shù)值,數(shù)值范圍是0~255。unsignedint類型是用雙字節(jié)來表示

數(shù)值的,數(shù)值范圍是0~65535。

(2)對不同類型的變量設(shè)置相同的延時控制參數(shù),使得兩燈相互交替閃爍,觀察不同數(shù)據(jù)類型控制的LED閃爍的區(qū)別。任務(wù)電路Proteus原理圖如圖3-1所示,當P1.0或P1.1輸出為0時,對應(yīng)發(fā)光二極管D1或D2點亮。當P1.0或P1.1輸出為1時,對應(yīng)發(fā)光二極管D1或D2熄滅。圖3-1不同數(shù)據(jù)類型實現(xiàn)LED閃爍電路圖

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-1所示的電路原理圖,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-2所示。圖3-2不同數(shù)據(jù)類型實現(xiàn)LED閃爍仿真圖

任務(wù)結(jié)論

采用整型和字符型同樣大小數(shù)值的延時時間控制LED的閃爍,通過仿真和實際電路板運行現(xiàn)象觀察,很明顯D1點亮和熄滅的時間長于D2點亮和熄滅的時間。由此看出不同

數(shù)據(jù)類型在數(shù)據(jù)存儲及處理時的區(qū)別。

任務(wù)3-2數(shù)據(jù)運算的LED顯示

任務(wù)目的利用51單片機編程實現(xiàn)“60+43”和“6043”兩道加法和減法運算,并將運算結(jié)果分別采用P1口外接的8個LED以二進制的方式顯示。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

定義兩個無符號字符型變量a和b,并將其分別賦值為60和43,然后直接將n+m和n-m的結(jié)果分別送入寄存器P1。任務(wù)電路Proteus原理圖如圖3-3所示,當P0口或P1口引腳輸出為0時,對應(yīng)發(fā)光二極管點亮;當P1口引腳輸出為1時,對應(yīng)發(fā)光二極管熄滅。根據(jù)P0口或P1口分別所接的8個LED的亮滅狀態(tài)可以看出P0口或P1口輸出的高低電平組合,進一步可得出其二進制組合信息,從而驗證相應(yīng)算數(shù)運算的正確性。圖3-3數(shù)據(jù)運算的LED實現(xiàn)

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-3所示的電路,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-4所示。圖3-4數(shù)據(jù)運算的LED實現(xiàn)仿真效果圖

任務(wù)結(jié)論

通過仿真圖和開發(fā)板的指示燈可以看到P0口和P1口外接的LED的亮滅狀態(tài)實現(xiàn)了“60+43”和“60-43”兩道加法和減法運算結(jié)果與預(yù)期結(jié)果相同,驗證了51單片機的加減算術(shù)運算。

3.4C語言的語句

一個C程序是由若干語句組成的,每個語句以分號作為結(jié)束符。C語言的語句可以分為5類,即控制語句、表達式語句、函數(shù)調(diào)用語句、空語句和復(fù)合語句。其中,除了控制語句外,其余4類都屬于順序執(zhí)行語句。

3.4.1順序執(zhí)行語句

1.表達式語句

表達式語句由表達式加上分號組成,最常見的就是賦值語句,由一個賦值表達式后面跟一個分號組成。例如:

n=8;/*將8賦值給變量n*/

x=5*x;/*將變量x的值乘以5的結(jié)果賦給變量x*/

事實上,任何表達式都可以加上分號成為語句,例如,經(jīng)常在程序中出現(xiàn)如下的語句:

i++;/*使i變量的值加1*/

需要注意的是,有些寫法雖然是合法的,但是沒有保留計算結(jié)果,因而沒有實際的意義。例如:

b-3;

i++-6;

2.函數(shù)調(diào)用語句

由函數(shù)調(diào)用加上分號組成,例如:

printf(″Hello″);/*調(diào)用庫函數(shù),輸出字符串*/

函數(shù)是一段程序,這段程序可能存在于函數(shù)庫中,也可能是由用戶自己定義的,當調(diào)用函數(shù)時會轉(zhuǎn)到該段程序執(zhí)行。但函數(shù)調(diào)用語句與前后語句之間的關(guān)系是順序執(zhí)行的。

3.空語句

只有分號組成的語句稱為空語句。在程序中,如果沒有什么操作需要進行,但從語句的結(jié)構(gòu)上來說必須有一個語句時,可以書寫一個空語句。

4.復(fù)合語句

把多個語句用大括號括起來組成的一個語句稱為復(fù)合語句。例如:

{

a=3+9j

b=15;

c=Sqrt(a*a+b*b);

}

復(fù)合語句內(nèi)的各條語句都必須以分號結(jié)尾,在大括號外不能加分號。

3.4.2控制語句

控制語句用于控制程序流程,實現(xiàn)程序執(zhí)行流程的轉(zhuǎn)移??刂普Z句包括以下9種:

if()...else...:條件語句;

switch:多分支選擇語句;

for()...

:循環(huán)語句;

do...while():循環(huán)語句;

while():循環(huán)語句;

goto:無條件轉(zhuǎn)向語句;

continue:結(jié)束本次循環(huán)語句;

return:從函數(shù)返回語句;

break:終止執(zhí)行switch或循環(huán)語句。

上述語句中的“()”表示其中是一個判定條件;“...”表示內(nèi)嵌的語句。

1.條件語句

條件語句又被稱為分支語句,也有人稱之為判斷語句,其關(guān)鍵字由if構(gòu)成,這在眾多的高級語言中都是基本相同的。C語言提供了三種形式的條件語句:

(1)if(條件表達式)語句

當條件表達式的結(jié)果為真時,就執(zhí)行語句,不然就跳過。如“if(a==b)a++;”表示當a等于b時,a加1。

(2)if(條件表達式)語句1

else語句2當條件表達式成立時,執(zhí)行語句1,否則執(zhí)行語句2。例如:

if(a==b)

a++;

else

a--;

表示當a等于b時,a加1,否則a減1。

(3)if(條件表達式1)語句1

elseif(條件表達式2)語句2

elseif(條件表達式3)語句3

elseif(條件表達式m)語句n

else語句m

這是由ifelse語句組成的嵌套,用來實現(xiàn)多方向條件分支,使用時應(yīng)注意if和else要配對使用,少了一個就會語法出錯,且else總是與最臨近的if相配對。一般條件語句只會用做單一條件或少數(shù)量的分支,分支較多時則會用到下面將介紹的開關(guān)語句。

2.分支語句

用多個條件語句能實現(xiàn)多方向條件分支,但是使用過多的條件語句實現(xiàn)多方向分支會使條件語句嵌套過多,程序冗長,不宜讀。使用分支語句不但能達到處理多分支選擇的目

的,而且能使程序結(jié)構(gòu)清晰。

分支語句格式如下:

switch(表達式)

{

case常量表達式1:語句1;break;

case常量表達式2:語句2;break;

case常量表達式3:語句3;break;

case常量表達式n:語句n;break;

default:語句;

}

運行中,switch后面的表達式的值將會作為條件,與case后面的各個常量表達式的值相對比,如果相等則執(zhí)行case后面的語句,再執(zhí)行break(間斷語句)語句,以跳出switch語句。如果case后沒有和條件相等的值時就執(zhí)行default后的語句。若在沒有符合的條件時要求不做任何處理,則可以不寫default語句。

3.for語句

采用for語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:

for([初值設(shè)定表達式];[循環(huán)條件表達式];

[更新表達式])循環(huán)體語句;

for語句的執(zhí)行過程是:先計算出初值設(shè)定表達式的值作為循環(huán)控制變量的初值,再檢查循環(huán)條件表達式的結(jié)果,當滿足循環(huán)條件時就執(zhí)行循環(huán)體語句并計算更新表達式,然后根據(jù)更新表達式的計算結(jié)果來判斷循環(huán)條件是否滿足……一直進行到循環(huán)條件表達式的結(jié)果為假(0值)時,退出循環(huán)體。

在C語言程序的循環(huán)結(jié)構(gòu)中,for語句的使用最為靈活,它不僅可以用于循環(huán)次數(shù)已經(jīng)確定的情況,而且可以用于循環(huán)次數(shù)不確定而只給出循環(huán)結(jié)束條件的情況。另外,for語

句中的三個表達式是相互獨立的,并不一定要求三個表達式之間有依賴關(guān)系。并且for語句中的三個表達式都可能缺省,但無論缺省哪一個表達式,其中的兩個分號都不能缺省。一般不要缺省循環(huán)條件表達式,以免形成死循環(huán)。

4.do...while語句

采用do...while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:

do循環(huán)體語句while(條件表達式);

這種循環(huán)結(jié)構(gòu)的特點是先執(zhí)行給定的循環(huán)體語句,再檢查條件表達式的結(jié)果。當多件表達式的值為真(非0值)時,重復(fù)執(zhí)行循環(huán)體語句,直到條件表達式的值為假(0值時為止。因此,do...while語句構(gòu)成的循環(huán)結(jié)構(gòu)在任何條件下,循環(huán)體語句至少會被執(zhí)行一次。

5.while語句

采用while語句構(gòu)成循環(huán)結(jié)構(gòu)的一般形式如下:

while(條件表達式)循環(huán)體語句;

其意義為,當條件表達式的結(jié)果為真(非0值)時,程序就重復(fù)執(zhí)行后面的循環(huán)體語句,一直執(zhí)行到條件表達式的結(jié)果為假(0值)為止。這種循環(huán)結(jié)構(gòu)是先檢查條件表達式所給出

的條件,再根據(jù)檢查的結(jié)果決定是否執(zhí)行后面的語句。如果條件表達式的結(jié)果一開始就為假,則后面的語句一次也不會被執(zhí)行。這里的語句可以是復(fù)合語句。

6.goto語句

goto語句是一個無條件轉(zhuǎn)向語句,它的一般形式為

goto語句標號;

其中,語句標號是一個帶冒號“:”的標識符。將goto語句和if語句一起使用,可以構(gòu)成一個循環(huán)結(jié)構(gòu)。但更常見的是在C語言程序中采用goto語句來跳出多重循環(huán)。需要注意的是,只能用goto語句從內(nèi)層循環(huán)跳到外層循環(huán),而不允許從外層循環(huán)跳到內(nèi)層循環(huán)。

7.continue語句

continue語句是一種中斷語句,它一般用在循環(huán)結(jié)構(gòu)中,其功能是結(jié)束本次循環(huán),即跳過循環(huán)體中下面尚未執(zhí)行的語句,把程序流程轉(zhuǎn)移到當前循環(huán)語句的下一個循環(huán)周期,

并根據(jù)循環(huán)控制條件決定是否重復(fù)執(zhí)行該循環(huán)體。

continue語句的一般形式為

continue;

continue語句通常和條件語句一起用在由while、do...while和for語句構(gòu)成的循環(huán)結(jié)構(gòu)中。continue語句也是一種具有特殊功能的無條件轉(zhuǎn)移語句,但與break語句不同,continue語句并不跳出循環(huán)體,而只是根據(jù)循環(huán)控制條件確定是否繼續(xù)執(zhí)行循環(huán)語句。

8.return語句

return語句的一般形式為

return(表達式);

如果return語句后面帶有表達式,則要計算表達式的值,并將表達式的值作為該函數(shù)的返回值;如果不帶表達式,則被調(diào)用函數(shù)返回主調(diào)用函數(shù)時,函數(shù)值不確定。一個函數(shù)的內(nèi)部可以含有多個return語句,但程序僅執(zhí)行其中的一個return語句而返回主調(diào)用函數(shù)。一個函數(shù)的內(nèi)部也可以沒有return語句,在這種情況下,當程序執(zhí)行到最后一個界限符“}”處時,就自動返回主調(diào)用函數(shù)。

9.break語句

break語句可以跳出switch結(jié)構(gòu),使程序繼續(xù)執(zhí)行switch結(jié)構(gòu)后面的一個語句。

break語句還可以從循環(huán)體中跳出循環(huán),提前結(jié)束循環(huán)而接著執(zhí)行循環(huán)結(jié)構(gòu)下面的語句。對于多重循環(huán)的情況,break語句只能跳出它所處的那一層循環(huán),而不像goto語句可以直接從最內(nèi)層循環(huán)中跳出來。由此可見,要退出多重循環(huán)時,采用goto語句比較方便。需要指出的是,break語句只能用于開關(guān)語句和循環(huán)語句之中,它是一種具有特殊功能的無條件轉(zhuǎn)移語句。另外還要注意,在進行實際程序設(shè)計時,為了保證程序具有良好的結(jié)構(gòu),應(yīng)當盡可能地少采用goto語句,以使程序結(jié)構(gòu)清晰易讀。

任務(wù)3-3用if語句控制LED的亮滅狀態(tài)

任務(wù)目的設(shè)計一個函數(shù),采用單片機和開關(guān)配合控制LED的亮滅。一個按鍵S1接在P3.5與GND之間,另一個按鍵S2接在P3.4與GND之間,發(fā)光二極管D1接單片機P1.0引腳。按下開關(guān)S1后LED亮,按下開關(guān)S2后LED滅。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

通過單片機獲取S1和S2的開關(guān)狀態(tài),并根據(jù)開關(guān)的閉合情況來控制LED的亮滅。任務(wù)電路Proteus原理圖如圖3-5所示,由圖可知,當開關(guān)S1或S2被按下時,對應(yīng)的單片機P3.5和P3.4引腳會被拉低成低電平。通過引腳狀態(tài)來判斷按鍵是否被按下,從而控制單片機P1.0引腳輸出電平的高低狀態(tài),進一步控制D1的亮滅。其中引腳狀態(tài)的判斷可用if語句來實現(xiàn)。圖3-5if語句控制LED亮滅閃爍

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-5所示的電路原理圖,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-6所示。圖3-6if語句控制LED亮滅閃爍仿真效果圖

任務(wù)結(jié)論

通過任務(wù)實施結(jié)果可以看出,用if語句可以對單片機引腳狀態(tài)的不同情況加以區(qū)分和判斷,從而實現(xiàn)對單片機的有效控制。

任務(wù)3-4用for語句控制LED的循環(huán)亮滅狀態(tài)

任務(wù)目的用單片機的P1口控制8個發(fā)光二極管來模擬8個信號燈。按照規(guī)律依次點亮每一個發(fā)光二極管并延時一段時間,以實現(xiàn)流水燈的效果。編程時使用for語句來實現(xiàn)程序的循環(huán)部分控制代碼。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

任務(wù)要求單片機控制P1口所接的8個LED,實現(xiàn)流水亮滅效果??梢酝ㄟ^單獨位控制方式實現(xiàn)LED的亮滅,但由于要控制8個燈的亮滅狀態(tài),所以編程會比較繁瑣,程序不

夠優(yōu)化。當需要對某個I/O口的8位一起操作時,一般采用整體操作的方式。在軟件設(shè)計時可以定義一個變量來給P1口賦值,賦的值不同,點亮的LED不同。控制好賦值的間隔

時間,即可實現(xiàn)8個LED發(fā)光二極管的流水效果。程序流程圖如圖3-7所示。圖3-78個LED循環(huán)亮滅控制程序流程圖

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-8所示電路原理圖,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-9所示。圖3-8for語句控制LED循環(huán)亮滅圖圖3-9for語句控制LED循環(huán)亮滅仿真效果圖

任務(wù)結(jié)論

通過仿真運行圖和開發(fā)板運行可以看到8個LED循環(huán)亮滅,說明for語句可以實現(xiàn)控制LED循環(huán)亮滅的功能。使用for語句按照一定的時間間隔循環(huán)給P1口送相應(yīng)顯示數(shù)據(jù),實現(xiàn)8燈流水功能,程序更加簡潔明了。

3.5C語言的數(shù)組

3.5.1一維數(shù)組一維數(shù)組只有一個下標,定義的形式如下:

數(shù)據(jù)類型說明符數(shù)組名[常量表達式][={初值,初值...}]各部分說明如下:(1)數(shù)據(jù)類型說明符說明了數(shù)組中各個元素存儲的數(shù)據(jù)的類型。(2)數(shù)組名是整個數(shù)組的標識符,它的取名方法與變量的取名方法相同。

(3)常量表達式的取值須為整型常量,且必須用方括號“[]”括起來,用以說明該數(shù)組的長度,即該數(shù)組元素的個數(shù)。

(4)初值用于給數(shù)組元素賦初值,這部分在數(shù)組定義時屬于可選項。對數(shù)組元素賦值,可以在定義時賦值,也可以在定義之后賦值。在定義時賦值,后面須帶等號;初值須用花括號括起來,括號內(nèi)的初值兩兩之間用逗號相隔;可以對數(shù)組的全部元素賦值,也可以只對部分元素賦值。初值為0的元素可以只用逗號占位而不寫初值0。

對數(shù)組元素的初始化可以用以下方法實現(xiàn):

(1)在定義數(shù)組時對數(shù)組元素賦以初值。例如:

inta[10]={0,1,2,3,4,5,6,7,8,9};

(2)只給一部分元素賦值。例如:

inta[10]={0,1,2,3,4};

該語句定義a數(shù)組有10個元素,但花括弧內(nèi)只提供5個初值,這表示只給前面5個元素賦初值,后5個元素值為0。

(3)如果想使一個數(shù)組中全部元素值為0,可以寫成

inta[10]={0,0,0,0,0,0,0,0,0,0};

不能寫成

inta[10]={0*10};

(4)在對全部數(shù)組元素賦初值時,可以不指定數(shù)組長度。例如:

inta[5]={1,2,3,4,5};

可以寫成

inta[]={1,2,3,4,5}

3.5.2二維數(shù)組

二維數(shù)組的定義:

類型說明符數(shù)組名[整型表達式1][整型表達式2];

二維數(shù)組的元素個數(shù)=行數(shù)×列數(shù),例如:

inta[3][2];

語句定義了一個3行2列共6個數(shù)組元素的數(shù)組。

二維數(shù)組的引用格式如下:

數(shù)組名[下標1][下標2]

注:內(nèi)存是一維的,數(shù)組元素在存儲器中的存放順序按行序優(yōu)先,即“先行后列”。

二維數(shù)組初始化也是在類型說明時給各下標變量賦以初值。二維數(shù)組可按行分段賦值,也可按行連續(xù)賦值。例如,對數(shù)組a[5][3],如果按行分段賦值可寫為

inta[5][3]={{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};

如果按行連續(xù)賦值可寫為

inta[5][3]={80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};

3.5.3字符數(shù)組

用來存放字符數(shù)據(jù)的數(shù)組稱為字符數(shù)組,它是C語言中常用的一種數(shù)組。字符數(shù)組中的每一個元素都用來存放一個字符,也可用字符數(shù)組來存放字符串。字符數(shù)組的定義與一

般數(shù)組相同,只是在定義時把數(shù)據(jù)類型定義為char型。例如:

charstring1[10];

charstring2[20];

這兩個語句定義了兩個字符數(shù)組,分別定義了10個元素和20個元素。

在C51中,字符數(shù)組用于存放一組字符或字符串,字符串以“\0”作為結(jié)束符,只存放一般字符的字符數(shù)組的賦值與使用和一般的數(shù)組完全相同。對于存放字符串的字符數(shù)組,

既可以對字符數(shù)組的元素逐個進行訪問,也可以對整個數(shù)組按字符串的方式進行處理。

任務(wù)3-5用字符型數(shù)組實現(xiàn)LED循環(huán)亮滅

任務(wù)目的采用單片機控制LED的循環(huán)亮滅狀態(tài),實現(xiàn)流水效果。把P1口8位LED的控制碼賦給一個數(shù)組,再依次引用數(shù)組元素,并送P1口顯示,通過LED觀察LED流水效果。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

定義一個一維數(shù)組用來存放8個LED的顯示數(shù)據(jù),依次為0xfe、0xfd、0xfb、0xf7、0xef、0xdf、0xbf、0x7f。通過循環(huán)將這8個數(shù)組元素按照一定時間間隔分別送至單片機P1口,即可實現(xiàn)D1至D7循環(huán)點亮,實現(xiàn)流水效果。

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-10所示的電路原理圖,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-11所示。圖3-10字符型數(shù)組控制LED循環(huán)亮滅電路原理圖圖3-11字符型數(shù)組控制LED循環(huán)亮滅仿真效果圖

任務(wù)結(jié)論

該程序?qū)⒁痪S數(shù)組和for語句搭配,按照一定的時間間隔循環(huán)給P1口送相應(yīng)顯示數(shù)據(jù),實現(xiàn)8燈流水效果功能,無需對送顯數(shù)據(jù)做進一步處理,程序思路更加清晰,實現(xiàn)起來也較為方便。

3.6C語言的函數(shù)

3.6.1函數(shù)的定義函數(shù)定義的一般格式如下:函數(shù)類型函數(shù)名(形式參數(shù)表)[interruptn][usingn]形式參數(shù)說明{局部變量定義函數(shù)體(有返回值的要有return語句)}

1)函數(shù)類型

函數(shù)類型說明了函數(shù)返回值的類型。

2)函數(shù)名

函數(shù)名是用戶為自定義函數(shù)取的名字,以便調(diào)用函數(shù)時使用。

3)形式參數(shù)表

形式參數(shù)表用于列錄在主調(diào)函數(shù)與被調(diào)用函數(shù)之間進行數(shù)據(jù)傳遞的形式參數(shù)。

4)interruptn修飾符

interruptn是C51函數(shù)中非常重要的一個修飾符,這是因為中斷函數(shù)必須通過它進行修飾。在C51程序設(shè)計中,若在函數(shù)定義時用了interruptn修飾符,系統(tǒng)編譯時就把對應(yīng)函數(shù)轉(zhuǎn)化為中斷函數(shù),自動加上程序頭段和尾段,并按MCS51系統(tǒng)中斷的處理方式自動把它安排在程序存儲器中的相應(yīng)位置。

該修飾符中n的取值為0~31,對應(yīng)的中斷情況如下:

0———外部中斷0;

1———定時/計數(shù)器T0;

2———外部中斷1;

3———定時/計數(shù)器T1;

4———串行口中斷;

5———定時/計數(shù)器T2;

其他值預(yù)留。

5)函數(shù)返回值

返回語句return用來回送一個數(shù)值給定義的函數(shù),從函數(shù)中退出。

返回值是通過return語句返回的。

返回值的類型如果與函數(shù)定義的類型不一致,那么返回值將被自動轉(zhuǎn)換成函數(shù)定義的類型。

如果函數(shù)無需返回值,可以用void類型說明符指明函數(shù)無返回值。

6)usingn修飾符

修飾符usingn用于指定本函數(shù)內(nèi)部使用的工作寄存器組,其中n的取值為0~3,表示寄存器組號。

使用usingn修飾符時應(yīng)注意以下幾點:

(1)加入usingn后,C51在編譯時自動在函數(shù)的開始和結(jié)束處加入以下指令:

{

PUSHPSW;標志寄存器入棧

MOVPSW,#(與寄存器組號相關(guān)的常量)

?

POPPSW;標志寄存器出棧

}

(2)usingn修飾符不能用于有返回值的函數(shù),因為C51函數(shù)的返回值是放在寄存器中的。如寄存器組改變了,返回值就會出錯。

3.6.2函數(shù)的調(diào)用與聲明

與使用變量一樣,在調(diào)用一個函數(shù)之前,必須對該函數(shù)進行聲明。函數(shù)聲明的一般格式為

[extern]函數(shù)類型函數(shù)名(形式參數(shù)列表)

函數(shù)定義時參數(shù)列表中的參數(shù)稱為形式參數(shù),簡稱形參。函數(shù)調(diào)用時所使用的替換參數(shù)是實際參數(shù),簡稱實參。定義的形參與函數(shù)調(diào)用的實參類型應(yīng)該一致,書寫順序應(yīng)該相同。

如果聲明的函數(shù)在文件內(nèi)部,則聲明時不用extern;如果聲明的函數(shù)不在文件內(nèi)部,而在另一個文件中,則聲明時須帶extern,指明使用的函數(shù)在另一個文件中。

函數(shù)調(diào)用的一般形式如下:

函數(shù)名(實參列表);

被調(diào)用的函數(shù)必須是已經(jīng)存在的函數(shù)。按照函數(shù)調(diào)用在主調(diào)函數(shù)中出現(xiàn)的位置,函數(shù)調(diào)用方式有以下三種:

(1)函數(shù)作為語句。把函數(shù)調(diào)用作為一個語句,不使用函數(shù)返回值,只是完成函數(shù)所定義的操作。例如:

refresh_led();

(2)函數(shù)作為表達式。函數(shù)調(diào)用出現(xiàn)在一個表達式中,使用函數(shù)的返回值。例如:

intk;

k=sum(a,b);

(3)函數(shù)作為一個參數(shù)。函數(shù)調(diào)用作為另一個函數(shù)的實參。例如:

intk;

k=sum(sum(a,b),c);

任務(wù)3-6用函數(shù)實現(xiàn)LED流水速度控制

任務(wù)目的設(shè)計一個函數(shù),采用單片機控制LED的流水速度,實現(xiàn)8個LED發(fā)光二極管以兩種不同的速度亮滅的流水燈效果,通過LED觀察速度切換效果。任務(wù)準備設(shè)備及軟件:萬用表、計算機、KeilμVision4軟件、Proteus軟件。

任務(wù)實施

1.任務(wù)分析

單片機P1口外接8個LED,電路原理圖如圖3-12所示。其流水燈效果的流水速度由調(diào)用的軟件延時時間來控制。通過實參傳遞形成兩個不同延時長短的延時函數(shù),在實現(xiàn)流水效果時相鄰輪次調(diào)用不同的延時函數(shù),從而控制P1口所接的8個LED以兩種不同頻率切換,通過LED觀察流水頻率切換效果。

2.軟件仿真

(1)打開Keil軟件,在軟件中輸入任務(wù)程序,并對程序進行編譯,直至沒有錯誤,并生成相應(yīng)的hex文件。

(2)打開Proteus軟件,繪制如圖3-12所示電路原理圖,導入編譯后生成的hex文件,運行程序,觀察仿真效果,如圖3-13所示。圖3-12函數(shù)實現(xiàn)LED流水速度控制的電路原理圖圖3-13函數(shù)實現(xiàn)LED流水速度控制的仿真效果圖

任務(wù)結(jié)論

單片機通過調(diào)用延時函數(shù)實現(xiàn)延時效果,給延時函數(shù)傳遞實參來控制延時的時間長短,從而控制P1口所接的8個LED以兩個頻率閃爍速度切換流水燈效果。

3.7C語言的編譯預(yù)處理

3.7.1宏定義“#define”指令宏定義的作用是用一個字符串替換另一個字符串,可以簡化程序,并且一目了然。宏定義的簡單形式是符號常量定義,復(fù)雜形式是帶參數(shù)的宏定義。

1)不帶參數(shù)的宏定義

不帶參數(shù)的宏定義又稱符號常量定義,一般格式為

#define標識符常量表達式

其中,“標識符”是定義的宏符號名(也稱宏名),其作用是在程序中以指定的標識符來代替其后的常量表達式。利用宏定義可以在C語言源程序中用一個簡單的符號名來代替一個很長的字符串,還可以使用一些有一定意義的標識符,提高程序的可讀性。

宏定義的作用范圍是整個文件,如果需在某個位置終止宏定義命令,則需使用“#undef標識符常量表達式”命令。

2)帶參數(shù)的宏定義

帶參數(shù)的宏定義與符號常量定義的不同之處在于,對于源程序中出現(xiàn)的宏符號名

溫馨提示

  • 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)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論