微型計算機單片機C語言程序設計_第1頁
微型計算機單片機C語言程序設計_第2頁
微型計算機單片機C語言程序設計_第3頁
微型計算機單片機C語言程序設計_第4頁
微型計算機單片機C語言程序設計_第5頁
已閱讀5頁,還剩109頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 單片機資源的C51編程實例 C51數(shù)據的存儲類型和存儲模式 C51的數(shù)據類型與運算 單片機C語言概述 C51程序基本結構與相關語句 51單片機系統(tǒng)開發(fā)常用工具軟件keil C51 C51的函數(shù)第10章 單片機C語言程序設計 單片機C語言概述 C51的數(shù)據類型與運算 C51數(shù)據的存儲類型和存儲模式 C51程序基本結構與相關語句 C51的函數(shù) 單片機資源的C51編程實例 51單片機系統(tǒng)開發(fā)常用工具軟件keil C51本章知識點 隨著單片機硬件性能的不斷提高和應用技術的不斷發(fā)展,開發(fā)者越來越注重目標系統(tǒng)的開發(fā)成效,而開發(fā)成效在很大程度上取決于程序本身的編寫效率。為了適應這種要求,出現(xiàn)了單片機高級語

2、言C語言。 10.1 單片機C語言概述10.1.1 C語言的特點及程序結構 單片機的C語言編譯器:德國的KEIL C51開發(fā)平臺、加拿大DAVEDUNFIELD的MICRO-C51、美國Franklin軟件公司的Franklin C51等。目前最流行的是Keil C51編譯器。一C語言的特點1語言簡潔、緊湊,使用方便、靈活。2運算符豐富。3數(shù)據結構豐富。具有現(xiàn)代化語言的各種數(shù)據結構。4可進行結構化程序設計。5可以直接對計算機硬件進行操作。6生成的目標代碼質量高,程序執(zhí)行效率高。7可移植性好。 C語言程序采用函數(shù)結構,每個C語言程序由一個或多個函數(shù)組成,在這些函數(shù)中至少應包含一個主函數(shù)main(

3、),也可以包含一個main()函數(shù)和若干個其它的功能函數(shù)。不管main()函數(shù)放于何處,程序總是從main()函數(shù)開始執(zhí)行,執(zhí)行到main()函數(shù)結束則結束。 二C語言的程序結構 用C51語言和匯編語言主要不同之處在于: 用匯編語言編寫51單片機程序必須要考慮其存儲器結構,尤其必須考慮其片內數(shù)據存儲器與特殊功能寄存器的使用以及按實際地址處理端口數(shù)據。而用C51語言編寫的51單片機應用程序,則不用具體組織、分配存儲器資源和處理端口數(shù)據。但在C51語言編程中,對數(shù)據類型與變量的定義,必須要與單片機的存儲結構相關聯(lián),否則編譯器不能正確地映射定位。10.1.2 C語言與MCS-51單片機C51語言與標

4、準C語言程序區(qū)別: (1)C51中定義的庫函數(shù)和標準C語言定義的庫函數(shù)不同。后者是按通用微型計算機來定義的,而C51中的庫函數(shù)是按MCS-51單片機相應情況來定義的; (2)數(shù)據類型有一定的區(qū)別。在C51中增加了幾種針對MCS-51單片機特有的數(shù)據類型; (3)C51中變量的存儲模式與MCS-51單片機的存儲器緊密相關; (4)C51中的輸入輸出是通過MCS-51串行口來完成的,輸入輸出指令執(zhí)行前必須要對串行口進行初始化; (5)C51中有專門的中斷函數(shù)。10.2 C51的數(shù)據類型與運算 10.2.1 C51的數(shù)據類型 分為基本數(shù)據類型和擴展(組合)數(shù)據類型?;緮?shù)據類型除了標準C中的字符型(

5、char)、整型(int)、長整型(long)、單精浮點型(float)、雙精浮點型(double)外,還有特殊功能寄存器型(sfr和sfr16兩種)和位類型(bit和sbit兩種)。擴展數(shù)據類型包括數(shù)組、指針型(*)以及結構(struct)和聯(lián)合(union)等。表10-1 KEIL C51編譯器支持的基本數(shù)據類型一字符型char signed char:用于定義帶符號字節(jié)數(shù)據,其字節(jié)的最高位為符號位,“0”表示正數(shù),“1”表示負數(shù),補碼表示,所能表示的數(shù)值范圍是-128+127; unsigned char:用于定義無符號字節(jié)數(shù)據或字符,可以存放一個字節(jié)的無符號數(shù),也可以存放西文字符,取值

6、范圍為0255。 二int整型 分singed int和unsigned int。默認為signed int。它們的長度均為兩個字節(jié),用于存放一個雙字節(jié)數(shù)據。對于signed int,用于存放兩字節(jié)帶符號數(shù),補碼表示,數(shù)的范疇為-32768+32767。對于unsigned int,用于存放兩字節(jié)無符號數(shù),數(shù)的范圍為065535。三long長整型 分singed long和unsigned long。默認為signed long。它們的長度均為四個字節(jié),用于存放一個四字節(jié)數(shù)據。對于signed long,用于存放四字節(jié)帶符號數(shù),補碼表示,數(shù)的范疇為-2147483648+2147483647。

7、對于unsigned long,用于存放四字節(jié)無符號數(shù),數(shù)的范圍為04294967295。四float浮點型 長度為四個字節(jié),包含指數(shù)和尾數(shù)兩部分。最高位為符號位,“1”表示負數(shù),“0”表示正數(shù)。單片機中使用浮點應注意以下三點: 由于單片機中沒有專門的浮點運算硬件,因此在運算時會比較慢。 由于51單片機本身是8位的,因此在計算中不可能達到太高的精度。 與單精浮點相比,雙精浮點型(double)具有更高的計算精度,但計算時間會更長,速度更慢,C51不支持雙精浮點型。 五特殊功能寄存器型 分sfr和sfr16兩種類型。 sfr:字節(jié)型特殊功能寄存器類型,占一個內存單元。利用它可以訪問MCS-51內

8、部的所有特殊功能寄存器; sfr16:雙字節(jié)型特殊功能寄存器類型,占用兩個字節(jié)單元。利用它可以訪問MCS-51內部的所有兩個字節(jié)的特殊功能寄存器,如DPTR。 頭文件reg51.h:包含了所有特殊功能寄存器和對其相應位的定義,通過在程序開頭用#include reg51.h語句包含頭文件可以很容易地進行新的擴展?!纠?0-1】特殊功能寄存器型數(shù)據定義。sfr SCON=0X98; /定義 SCONsbit SM0=0X9F; /定義 SCON 的各位sbit SM1=0X9E;sbit SM2=0X9D;sbit REN=0 x9C;sbit TB8=0X9B;sbit RB8=0X9A;sb

9、it TI=0X99;sbit RI=0X98;六位類型 功能:用于訪問MCS-51單片機中的可尋址的位單元。 bit型:定義的位變量在C51編譯器編譯時,在不同的時候位地址是可以變化的。 sbit型:定義的位變量必須與MCS-51單片機的一個可以尋址位單元或可位尋址的字節(jié)單元中的某一位聯(lián)系在一起。在C51編譯器編譯時,其對應的位地址是不可變化的。隱式轉換:出現(xiàn)在運算中數(shù)據類型不一致時,按下列轉換的優(yōu)先級順序: bitcharintlongfloat signedunsigned 例:當char型與int型進行運算時,先自動對char型擴展為int型,然后與int型進行運算,運算結果為int型

10、。 強制類型轉換符“()”:對數(shù)據類型進行人為的強制轉換。 10.2.2 關于指針型數(shù)據 指針(*)是一種特殊的數(shù)據類型,指向變量的地址,實質上指針就是存儲單元的地址。 在C51中它的長度一般為13個字節(jié)。根據所指的變量類型不同,可以是字符型指針(char *)、整型指針(int *)、長整型指針(long *)、浮點型指針(float *)及結構指針(struct *)與聯(lián)合指針(union *)。 1. 一般指針 一般指針的聲明和使用均與標準C相同,不過同時還能說明指針的存儲類型,例如: long * state; /為一個指向long型整數(shù)的指針,而state本身則依存儲模式存放。 ch

11、ar * xdata ptr; /ptr為一個指向char數(shù)據的指針,而ptr本身放于外部RAM區(qū)。 一般指針本身用3個字節(jié)存放,分別為存儲器類型、高位偏移量、低位偏移量。 2. 存儲器指針 基于存儲器的指針說明時即指定了存儲類型,例如: char data * str; /str指向data區(qū)中char型數(shù)據。 int xdata * pow; /pow指向外部RAM的int型整數(shù)。 存放時,只需一個字節(jié)或2個字節(jié)就夠了,因為只需存放偏移量。10.2.3 C51的運算符 運算符:完成某種特定運算的符號。C51常見的運算符有算術運算符、賦值運算符、關系運算符、邏輯運算符、按位運算符和聯(lián)合(復合

12、賦值)運算符。除此之外,還有一些用于完成特殊任務的運算符,如逗號運算符、條件運算符、指針與地址運算符。1. 常見的運算符1). 算術運算符 在實際編程中,為了程序的簡練,經常使用i+與+i這樣的語句。i+是先進行運算,再執(zhí)行i=i+1的操作;而+i則是先執(zhí)行i=i+1的操作,再進行運算。 例:int x=0,y=0; y=x+; /執(zhí)行后y的值仍為0 而 int x=0,y=0; y=+x; /執(zhí)行后y的值則為12). 賦值運算符“=”功能:將一個數(shù)據的值賦給一個變量,如x=10。 賦值表達式:利用賦值運算符將一個變量與一個表達式連接起來的式子稱為賦值表達式。 賦值語句:在賦值表達式的后面加一

13、個分號“;”就構成了賦值語句。一個賦值語句的格式如下: 變量=表達式; 執(zhí)行時先計算出右邊表達式的值,然后賦給左邊的變量。例如:x=8+9; /將8+9的值賦紿變量x x=y=5; /將常數(shù)5同時賦給變量x和y 在C51中,允許在一個語句中同時給多個變量賦值,賦值順序自右向左。 3). 關系運算符 C51中有6種關系運算符: 關系表達式通常用來作為判別條件構造分支或循環(huán)程序。關系表達式的一般形式如下: 表達式1 關系運算符 表達式2 關系運算的結果為邏輯量,成立為真(1),不成立為假(0)。其結果可以作為一個邏輯量參與邏輯運算。例如:53,結果為真(1),而10=100,結果為假(0)。注意:

14、關系運算符等于“=”是由兩個“=”組成。4). 邏輯運算符C51有3種邏輯運算符:| 邏輯或& 邏輯與! 邏輯非 關系運算符用于反映兩個表達式之間的大小關系,邏輯運算符則用于求條件式的邏輯值,用邏輯運算符將關系表達式或邏輯量連接起來的式子就是邏輯表達式。 邏輯與,格式: 條件式1 & 條件式2 當條件式1與條件式2都為真時結果為真(非0值),否則為假(0值)。邏輯或,格式: 條件式1 | 條件式2 當條件式1與條件式2都為假時結果為假(0值),否則為真(非0值)。邏輯非,格式: !條件式 當條件式原來為真(非0值),邏輯非后結果為假(0值)。當條件式原來為假(0值),邏輯非后結果為真(非0值)

15、。例如:若a=8,b=3,c=0,則!a為假,a & b為真,b & c為假。5). 位運算符 位運算是按位對變量進行運算,但并不改變參與運算的變量的值。如果要求按位改變變量的值,則要利用相應的賦值運算。C51中位運算符只能對整數(shù)進行操作,不能對浮點數(shù)進行操作。C51中的位運算符有:【例10-1】設a=0 x78=01111000B,b=0 x0f=00001111B,則a&b、a|b、ab、a、a2分別為多少?a&b=00001000b=0 x08;a|b=01111111B=0 x7f;ab=01110111B=0 x77;a=10000111B=0 x87;a2=00000011B=0

16、x03; 6). 聯(lián)合(復合賦值)運算符 C51語言中支持在賦值運算符“=”的前面加上其它運算符,組成聯(lián)合(復合賦值)。 聯(lián)合運算的一般格式如下: 變量 聯(lián)合運算符 表達式 處理過程:先把變量與后面的表達式進行某種運算,然后將運算的結果賦給前面的變量。例如:a+=b 相當于 a=a+b;a*=b 相當于 a=a*b;a&=b 相當于 a=a&b。7). 逗號運算符 “,”運算符將兩個或兩個以上的表達式連接起來,稱為逗號表達式。逗號表達式的一般格式為: 表達式1,表達式2,表達式n處理過程:按從左至右的順序依次計算出各個表達式的值,而整個逗號表達式的值是最右邊的表達式(表達式n)的值。 例如:x

17、=(a=3,6*3)結果x的值為18。 8). 條件運算符 條件運算符“?:”是C51語言中唯一的一個三目運算符,條件表達式的一般格式為: 邏輯表達式?表達式1:表達式2其功能是先計算邏輯表達式的值,當邏輯表達式的值為真(非0值)時,將計算的表達式1的值作為整個條件表達式的值;當邏輯表達式的值為假(0值)時,將計算的表達式2的值作為整個條件表達式的值。 例如:條件表達式max=(ab) ? a:b的執(zhí)行結果是將a和b中較大的數(shù)賦值給變量max。 9). 指針與地址運算符 變量的指針就是該變量的地址,還可以定義一個專門指向某個變量的地址的指針變量。 C51中提供了兩個專門的運算符: * 指針運算

18、符 & 取地址運算符2. C51的運算量1). 常量 常量是指在程序執(zhí)行過程中其值不能改變的量。C51支持整型常量、浮點型常量、字符型常量和字符串型常量。 整型常量 整型常量也就是整型常數(shù),根據其值范圍在計算機中分配不同的字節(jié)數(shù)來存放。十進制整數(shù)。如234、-56、0等。十六進制整數(shù)。以0 x開頭表示,如0 x12表示十六進制數(shù)12H。長整數(shù)。在存儲器中占四個字節(jié),另外,如一個整數(shù)后面加一個字母L,這個數(shù)在存儲器中也按長整型存放。如123L在存儲器中占四個字節(jié)。 浮點型常量 浮點型常量也就是實型常數(shù)。有十進制表示形式和指數(shù)表示形式。 十進制表示形式又稱定點表示形式,由數(shù)字和小數(shù)點組成。如 0.

19、123、38.645等都是十進制數(shù)表示形式的浮點型常量。 指數(shù)表示形式為: 數(shù)字 .數(shù)字 e 數(shù)字例如:123.456e-3、-3.123e2等都是指數(shù)形式的浮點型常量。 字符型常量字符型常量是用單引號引起的字符,如a、1、F等。可以是可顯示的ASCII字符,也可以是不可顯示的控制字符。對不可顯示的控制字符須在前面加上反斜杠“”組成轉義字符。利用它可以完成一些特殊功能和輸出時的格式控制。常用的轉義字符如表10-2所示。 字符串型常量 字符串型常量由雙引號“”括起的字符組成。如“D”、“1234”、“ABCD”等。一個字符串常量在內存中存放時不僅雙引號內的字符一個占一個字節(jié),而且系統(tǒng)會自動的在后

20、面加一個轉義字符“o”作為字符串結束符。不要將字符常量和字符串常量混淆,如字符常量A和字符串常量“A”是不一樣的。2). 變量 變量定義的格式如下: 存儲種類 數(shù)據類型說明符 存儲器類型 變量名1=初值,變量名2初值; 變量名由字母、數(shù)字和下劃線三種字符組成,且第一個字母必須為字母或下劃線。 變量名有兩種:普通變量名和指針變量名。它們的區(qū)別是指針變量名前面要帶“*”號。 另外,在C51中,為了增加程序的可讀性,允許用戶為系統(tǒng)固有的數(shù)據類型說明符用typedef起別名,格式如下: typedef c51固有的數(shù)據類型說明符 別名; 定義別名后,就可以用別名代替數(shù)據類型說明符對變量進行定義。別名可

21、以用大寫,也可以用小寫,為了區(qū)別一般用大寫字母表示。【例10-2】 typedef的使用。typedef unsigned int WORD;typedef unsigned char BYTE;BYTE a1=0 x12;WORD a2=0 x1234; 變量的存儲種類是指變量在程序執(zhí)行過程中的作用范圍。C51變量的存儲種類有四種,分別是自動(auto)、外部(extern)、靜態(tài)(static)和寄存器(register)。 auto 使用auto定義的變量稱為自動變量,其作用范圍在定義它的函數(shù)體或復合語句內部,自動變量一般分配在內存的堆棧空間中。定義變量時,如果省略存儲種類,則該變量默認

22、為自動(auto)變量。 extern使用extern定義的變量稱為外部變量。在一個函數(shù)體內,要使用一個已在該函數(shù)體外或別的程序中定義過的外部變量時,該變量在該函數(shù)體內要用extern說明。外部變量被定義后分配固定的內存空間,在程序整個執(zhí)行時間內都有效,直到程序結束才釋放。 static使用static定義的變量稱為靜態(tài)變量。它又分為內部靜態(tài)變量和外部靜態(tài)變量。在函數(shù)體內部定義的靜態(tài)變量為內部靜態(tài)變量,它在對應的函數(shù)體內有效;外部靜態(tài)變量是在函數(shù)外部定義的靜態(tài)變量。 register使用register定義的變量稱為寄存器變量。它定義的變量存放在CPU內部的寄存器中,處理速度快,但數(shù)目少。C5

23、1編譯器編譯時能自動識別程序中使用頻率最高的變量,并自動將其作為寄存器變量,用戶可以無需專門聲明。3). 位變量在C51中,允許用戶通過位類型符定義位變量。位類型符有兩個:bit和sbit??梢远x兩種位變量。bit位類型符用于定義一般的可位處理位變量。它的格式如下: bit 位變量名; sbit位類型符用于定義在可位尋址字節(jié)或特殊功能寄存器中的位,定義時須指明其位地址,可以是位直接地址,也可以是可位尋址變量帶位號,還可以是特殊功能寄存器名帶位號。格式如下: 格式一: sbit位變量名=特殊功能寄存器名帶位號; 例如:sbit OV=PSW2 ; / 定義OV位為PSW.2,地址為D2H sb

24、it CY=PSW7 ; / 定義CY位為PSW.7,地址為D7H 格式二:sbit位變量名= 寄存器的字節(jié)地址帶位號;例如: sbit OV=0XD02 ;/ 定義OV位地址是D0H字節(jié)中的第2位 sbit CY=0XD07 ;/ 定義CY位地址是D0H字節(jié)中的第7位格式三:sbit 位變量名= 尋址位的絕對位地址;例如: sbit OV=0XD2 ;/ 定義OV位地址為D2H sbit CY=0XD7 ;/ 定義CY位地址為D7H 特殊功能位代表了一個獨立的定義類,不能與其它位定義和位域互換。 4). 特殊功能寄存器變量 C51定義特殊功能寄存器變量的一般語法格式如下:sfr/sfr16

25、sfr-name = int constant; 或寫為: sfr(或sfr16) 特殊功能寄存器名=地址(整型常數(shù)); sfr16用于對雙字節(jié)特殊功能寄存器進行定義,特殊功能寄存器名一般用大寫字母表示。地址一般用直接地址形式,以整型常數(shù)表示,范圍必須在SFR地址范圍內,位于0 x800 xFF,不允許帶有運算符的表達式?!纠?0-3】特殊功能寄存器的定義舉例。 sfr SCON=0 x98; / 串口控制寄存器地址98H sfr TMOD=0 x89; / 定時器/計數(shù)器方式控制寄存器地址89H sfr P1=0 x90; /P1口的地址90H sfr16 DPTR=0 x82; /數(shù)據指針

26、DPTR的地址82H10.3.1 數(shù)據的存儲類型 定義變量類型時,還必須定義它的存儲類型,變量的存儲類型是用于指明變量所處的單片機的存儲器區(qū)域情況。C51編譯器能識別的存儲類型有以下幾種,如表10-3所示。 10.3 數(shù)據的存儲類型和存儲模式表10-3 C51的變量的存儲類型及其數(shù)據長度和值域 帶存儲類型的變量的定義的一般格式為: 數(shù)據類型 存儲類型 變量名 訪問內部數(shù)據存儲器(idata)比訪問外部數(shù)據存儲器(xdata)相對要快一些。因此,可將經常使用的變量置于內部數(shù)據存儲器中,而將較大及很少使用的數(shù)據變量置于外部數(shù)據存儲器中。例如定義變量x語句:data char x (等價于char

27、data x)?!纠?0-4】變量定義過程中存儲種類和存儲器類型舉例。 char data varl; /在片內RAM低128B定義用直接尋址方式訪問的字符型變量var1 int idata var2; /在片內RAM256B定義用間接尋址方式訪問的整型變量var2 unsigned int pdata sion; /在片外RAM的低256B定義無符號整型變量sion 【例10-5】 帶存儲類型的bit型變量的定義。bit data a1; /正確bit bdata a2; /正確bit pdata a3; /錯誤bit xdata a4; /錯誤 10.3.2 存儲模式 1. SMALL模式

28、: SMALL模式稱為小編譯模式。在SMALL模式下,編譯時參數(shù)及局部變量放入可直接尋址片內RAM的用戶區(qū)中(最大128字節(jié))。一般來說,如果系統(tǒng)所需要的內存數(shù)小于內部RAM 數(shù)時都應以小存儲模式進行編譯。優(yōu)點:存取速度很快缺點:供用戶使用的存儲空間小。 2. COMPACT模式: COMPACT模式稱為緊湊編譯模式。在COMPACT模式下,編譯時函數(shù)參數(shù)及局部變量被放在片外RAM的低256字節(jié)空間,通過R0或R1間接訪問,存儲器類型為pdata。 3. LARGE模式: LARGE模式稱為大編譯模式。在LARGE模式下,編譯時函數(shù)參數(shù)和局部變量被默認在片外RAM的64K字節(jié)空間,使用數(shù)據指針

29、DPTR來進行尋址,存儲器類型為xdata。用此數(shù)據指針進行訪問效率較低,尤其對兩個或多個字節(jié)的變量,這種數(shù)據類型的訪問機制直接影響代碼的長度?!纠?0-6】變量的存儲模式。#pragma small /變量的存儲模式為SMALLchar k1;int xdata m1;#pragma compact /變量的存儲模式為SMALLchar k2;int xdata m2;int func1(int x1, int y1) large /函數(shù)的存儲模式為LARGEreturn(x1+y1);int func2(int x2, int y2) /函數(shù)的存儲模式隱含為SMALL return(x2-

30、y2); C51程序與標準的C程序在以下幾個方面不同: 1C51中定義的庫函數(shù)和標準C語言定義的庫函數(shù)不同。標準的C語言定義的庫函數(shù)是按通用微型計算機來定義的,而C51中的庫函數(shù)是按MCS-51單片機相應情況來定義的; 2 C51中的數(shù)據類型與標準C的數(shù)據類型也有一定的區(qū)別。在C51中還增加了幾種針對MCS-51單片機特有的數(shù)據類型; 10.4 C51程序基本結構與相關語句 3變量的存儲模式不一樣。C51中變量的存儲模式是與MCS-51單片機的存儲器緊密相關; 4 輸入輸出處理不一樣。C51中的輸入輸出是通過MCS-51串行口來完成的,輸入輸出指令執(zhí)行前必須要對串行口進行初始化; 5 C51與

31、標準C在函數(shù)使用方面也有一定的區(qū)別,C51中有專門的中斷函數(shù)。10.4.1 C51程序基本結構 C語言程序的一般組成結構如下所示: 全局變量說明 /可被各函數(shù)引用 main( ) /主函數(shù) 局部變量說明 /只在本函數(shù)引用執(zhí)行語句(包括函數(shù)調用語句) fun1(形式參數(shù)表) /函數(shù)1 形式參數(shù)說明局部變量說明 執(zhí)行語句(包括調用其他函數(shù)語句)funn(形式參數(shù)表) /函數(shù)n形式參數(shù)說明 局部變量說明 執(zhí)行語句 1順序結構 順序結構程序是僅包含一個main( )函數(shù)的簡單程序,程序只由低地址向高地址順序執(zhí)行指令代碼,適當運用表達式語句就能設計出具有某特定功能的順序結構C51程序。雖然該程序設計方法

32、簡單,但在具體運用中的算法仍然采用自頂向下逐步求精的方法進行設計。2選擇結構 也稱為分支結構。當條件成立,即條件語句為“真”時,執(zhí)行一個分支,當條件不成立時,即條件語句為“假”時,執(zhí)行另一個分支。在C51中,實現(xiàn)選擇結構的語句為if-else,if-else-if語句。另外在C51中還支持多分支結構,多分支結構既可以通過if和else if語句嵌套實 3. 循環(huán)結構 循環(huán)結構的特點是:在給定條件成立時,反復執(zhí)行某程序段,直到條件不成立時為止。循環(huán)結構有兩種形式:當型循環(huán)和直到型循環(huán),這和其它高級語言相同,不再贅述。在C51中,可以構成循環(huán)結構的語句主要有:while、do while、for、

33、goto等。10.4.1 C51相關語句 1. if 語句 if 語句一共有3種語句形式,分別簡述如下: 1). if 語句,格式如下: if(表達式)語句; 處理機理是:如果表達式為真,則執(zhí)行語句,否則不執(zhí)行該語句。當花括號中的語句不只一條,花括號不能省。 如 if (a=b) a+; /當a等于b時,a就加1 再如if (x!=y) printf(“x=%d, y=%dn”, x, y); /如果x不等于y,則輸出x的值和y的值 2). if-else語句,格式如下: if (表達式)語句1; else語句2; 處理機理是:當條件表達式成立時,就執(zhí)行語句1,否則就執(zhí)行語句2 如: if (

34、a=b) a+; else a-; 當a等于b時,a加1,否則a-1。 3). if-else多重嵌套語句,格式如下: if (條件表達式1) 語句1 else if (條件表達式2) 語句2 else if (條件表達式3) 語句3 else if (條件表達式m) 語句n else 語句m 實現(xiàn)多方向條件分支,使用應注意if 和else的配對使用,記住else 總是與最臨近的if 相配對。 如果分支數(shù)量較多時最好選用下面將要介紹的switch開關語句。 2. switch語句 又稱開關語句,它可以從多種情況中選擇滿足條件的一種情況,是多分支選擇結構語句。 它的格式如下:switch (表達

35、式)case 常量表達式1:語句1;break; case 常量表達式2:語句2;break; case 常量表達式n:語句n;break; default:語句n+1;【例10-7】 根據flag的值設置上(up)下(down)左(left)右(right)標志位void main( ) unsigned int flag=0, up=0, down=0, left=0, right=0;switch(flag) case 1:up=1;break; /置標志case 2:down=1;break;case 3:left=1;break;case 4:right=1;break;defaul

36、t:error=1;break; 本例中輸入一個無符號整數(shù),經switch判斷后,將相應標志置1,若整數(shù)不在14的范圍內時就輸出“error”。 3. for語句 for循環(huán)控制語句的語法結構如下: f or(表達式1; 表達式2; 表達式3) 處理程序; 處理機理是:首先計算“表達式1”的值;再計算“表達式2”的值,若值為“真”則執(zhí)行循環(huán)體一次,否則跳出循環(huán);然后再計算“表達式3”的值,轉回第2步重復執(zhí)行。在整個for循環(huán)過程中,“表達式1”只計算一次,作為for的入口語句條件,“表達式2”和“表達式3”則可能計算多次。循環(huán)體也可能多次執(zhí)行,也可能一次都不執(zhí)行。例如:void main( )

37、int n, sum=0;for(n=0; n=50; n+)sum+=n;在使用for語句中有幾點要特別注意:. 循環(huán)體內的處理程序可以為空操作;. for語句的各表達式都可以省略,而分號不能省略。在省略各表達式時要特別小心分析,防止造成無限死循環(huán)。 4. while語句 實現(xiàn)當型循環(huán)結構,它的格式如下: while(表達式) 語句; /循環(huán)體 當表達式為非0(真)時,就重復執(zhí)行循環(huán)體內的語句;當表達式為0(假)時,則中止while循環(huán),程序將執(zhí)行循環(huán)結構之外的下一條語句。它的特點是: 先判斷條件,后執(zhí)行循環(huán)體。如條件第一次就不成立,則循環(huán)體一次也不執(zhí)行。 【例10-8】 下面程序是通過wh

38、ile語句實現(xiàn)計算并輸出1100的累加和。#include /包含特殊功能寄存器庫#include /包含I/O函數(shù)庫void main(void) /主函數(shù) int i, s=0; /定義整型變量x和y i=1; SCON=0 x52; /串口初始化 TMOD=0 x20; TH1=0 xf3; TR1=1; while (i=100) /累加1100之和在s中 s=s+i; i+; printf(“1+2+3+100=%dn”, s); while(1); 5. do while語句 do while語句在C51中用于實現(xiàn)直到型循環(huán)結構,它的格式如下: do 語句; /循環(huán)體 while(

39、表達式); 它的特點是:先執(zhí)行循環(huán)體中的語句,后判斷表達式。如表達式成立(真),則再執(zhí)行循環(huán)體,然后又判斷,直到有表達式不成立(假)時,退出循環(huán),執(zhí)行do while結構的下一條語句。【例10-9】 通過do while語句實現(xiàn)計算并輸出1100的累加和。#include /包含特殊功能寄存器庫#include /包含I/O函數(shù)庫void main(void) /主函數(shù) int i, s=0; /定義整型變量x和y i=1; SCON=0 x52; /串口初始化 TMOD=0 x20; TH1=0XF3; TR1=1; do /累加1100之和在s中 s=s+i; i+; while (i=1

40、00); printf(“1+2+3+100=n”, s); while(1); 6. break和continue語句 1)break語句 用break語句可以跳出switch結構,使程序繼續(xù)執(zhí)行switch結構后面的一個語句。使用break語句還可以從循環(huán)體中跳出循環(huán),提前結束循環(huán)而接著執(zhí)行循環(huán)結構下面的語句。它不能用在除了循環(huán)語句和switch語句之外的任何其它語句中。 【例10-10】用C51編程計算圓的面積,當計算到面積大于100時,由break語句跳出循環(huán)。for (r=1; r100) break; printf(“%fn”, area); 2).continue語句 conti

41、nue語句用于結束本次循環(huán),跳過循環(huán)體中continue下面尚未執(zhí)行的語句,直接進行下一次是否執(zhí)行循環(huán)的判定。 continue語句和break語句的區(qū)別在于:continue語句只是結束本次循環(huán)而不是終止整個循環(huán);break語句則是結束循環(huán),不再進行條件判斷。 【例10-11】輸出100200間不能被3整除的數(shù)。for (i=100; i=200; i+) if (i%3=0) continue; printf(“%d ” ; i ); 在程序中,當i能被3整除時,執(zhí)行continue語句,結束本次循環(huán),跳過printf()函數(shù),只有能被3整除時才執(zhí)行printf()函數(shù)。7.return語

42、句 return語句放在函數(shù)的最后位置,用于終止函數(shù)的執(zhí)行,并控制程序返回調用該函數(shù)時所處的位置。返回時還可以通過return語句帶回返回值。格式有兩種: 1).return; 2).return (表達式); 如果后面帶有表達式,則要計算表達式的值,并將表達式的值作為函數(shù)的返回值。若不帶表達式,則函數(shù)返回時將返回一個不確定的值。 8.goto語句 goto是一個無條件的轉向語句,只要執(zhí)行到這個語句,程序指針就會跳轉到goto后的標號所在的程序段。語法如下: goto 語句標號;其中的語句標號為一個帶冒號的標識符。 【例10-12】void main(void) unsigned char a

43、; start: a+; if (a=10) goto end; goto start; end:; 該程序是一個死循環(huán),只是說明一下goto的用法。這段程序的意思是在程序開始處用標識符start:標識,表示程序這是程序的開始,end:標識程序的結束,程序執(zhí)行a+,a的值加1,當a等于10時程序會跳到end標識處結束程序,否則跳回到start標識處繼續(xù)a+,直到a等于10。 函數(shù)是C51程序的基本單位,一個C51程序就是一堆函數(shù)的集合,有且只有一個名為main的函數(shù)(主函數(shù))。 C51中函數(shù)分為兩大類,一類是庫函數(shù),一類是用戶定義函數(shù)庫函數(shù):用戶在編程時只要用include預處理指令將頭文件包

44、含在用戶文件中,直接調用即可。用戶函數(shù)是用戶自己定義和調用的一類函數(shù)。 一個函數(shù)在程序中可以有三種形態(tài):函數(shù)定義、函數(shù)調用和函數(shù)說明。10.5 C51的函數(shù) 1. 函數(shù)的定義 C51函數(shù)定義的一般格式如下: 函數(shù)類型 函數(shù)名(形式參數(shù)表) reentrantinterrupt musing n 形式參數(shù)說明局部變量定義函數(shù)體 有關修飾符interrupt m和using n的介紹見10.6.3節(jié)。 2函數(shù)的調用 函數(shù)調用的一般形式如下: 函數(shù)名(實參列表); 函數(shù)調用方式有以下三種: 1). 函數(shù)語句。把被調用函數(shù)作為主調用函數(shù)的一個語句。 2). 函數(shù)表達式。函數(shù)被放在一個表達式中,以一個運

45、算對象的方式出現(xiàn)。 3). 函數(shù)參數(shù)。被調用函數(shù)作為另一個函數(shù)的參數(shù)。 3. 自定義函數(shù)的聲明 在C51中,函數(shù)原型一般形式如下: extern 函數(shù)類型 函數(shù)名(形式參數(shù)表); 函數(shù)的聲明是把函數(shù)的名字、函數(shù)類型以及形參的類型、個數(shù)和順序通知編譯系統(tǒng),以便調用函數(shù)時系統(tǒng)進行對照檢查。函數(shù)的聲明后面要加分號。 如果聲明的函數(shù)不在文件內部,聲明時須帶extern【例10-13】外部函數(shù)的使用 程序serial_initial.c#include /包含特殊功能寄存器庫#include /包含I/O函數(shù)庫void serial_initial(void) /主函數(shù) SCON=0 x52; /串口初

46、始化 TMOD=0 x20; TH1=0XF3; TR1=1; 程序x.c#include /包含特殊功能寄存器庫#include /包含I/O函數(shù)庫extern serial_initial();void main(void) int a, b; serial_initial(); scanf(“please input a, b:%d, %d”, &a, &b); printf(“n”); printf(“max is:%dn”, a=b?a:b); while(1); 上述程序x.c中,由于函數(shù)serial_initial( )不在文件內部,而在另一個文件中,因此在聲明時帶了extern

47、。10.6.1 C51程序的反匯編程序 【例10-14】用C51語言編程完成外部RAM的000EH單元和000FH單元的內容交換。 #include /該頭文件的主要功能是通過定義的宏來訪問絕對地址 main( ) char c; for( ; ; ) c=XBYTE0 x000E; XBYTE0 x000E=XBYTE0 x000F; XBYTE0 x000F=c; 10.6 單片機資源的C51編程實例 程序中為方便反復觀察,使用了死循環(huán)語句for( ; ; )只要用Ctrl+C即可退出死循環(huán)。上面程序通過編譯,生成的機器代碼和反匯編程序如下:0000 020014 LJMP 0014H 0

48、003 90000E MOV DPTR,#000EH0006 E0 MOVX A,DPTR0007 FF MOV R7,A0008 A3 INC DPTR 0009 E0 MOVX A,DPTR000A 90000E MOV DPTR,#000EH 000D F0 MOVX DPTR,A 000E A3 INC DPTR 000F EF MOV A,R70010 F0 MOVX DPTR,A 0011 80F0 SJMP 0003H 0013 22 RET 0014 787F MOV R0,#7FH 0016 E4 CLR A 0017 F6 MOV R0,A 0018 D8FD DJNZ R

49、0,0017H 001A 758107 MOV SP,#07H 001D 020003 LJMP 0003H 從本例可以看出: 1.一進入C語言程序,首先執(zhí)行初始化,將內部RAM的07FH 128個單元清零,然后置SP為07H(視變量多少不同,SP置不同值,依程序而定) 2. C語言程序設定的變量,C51自行安排寄存器或存儲器作參數(shù)傳遞區(qū),通常在R0R7(一組或兩組,視參數(shù)多少定) 3. 如果不特別指定變量的存儲類型,通常被安排在內部RAM中。 10.6.2 并行口及鍵盤、顯示器接口的C51編程【例10-15】設P1口做輸出口,接八只發(fā)光二極管,編寫程序,使發(fā)光二極管循環(huán)點亮。 說明:由準雙向

50、口結構可知當P1口用為輸入口時,必須先對它置“1”。 P1口循環(huán)點燈的C51程序如下:#include void delay( ) /定義延時函數(shù) unsigned int i; for (i=0; i20000; i+) void main() unsigned char index; unsigned char LED; while (1) LED = 1; for (index=0; index 8; index+) P1 = LED; LED = 1; /右移一位 delay( ); 【例10-16】 將AT89C51單片機的P0.0p0.7分別和一位共陰數(shù)碼管的ah的筆段相連接,數(shù)碼

51、管的公共端接地,用C51編程讓數(shù)碼管循環(huán)顯示09十個數(shù)字的功能,時間間隔0.2秒。對應的C51程序如下:#include unsigned char code table=0 x3f,0 x06,0 x5b,0 x4f,0 x66, 0 x6d,0 x7d,0 x07,0 x7f,0 x6f; /共陰極數(shù)碼管字型碼表unsigned char dispcount; void delay02s(void) /定義延時函數(shù) unsigned char i,j,k; for(i=20;i0;i-) for(j=20;j0;j-) for(k=248;k0;k-); void main(void) w

52、hile(1) for(dispcount=0;dispcount10;dispcount+) P0=tabledispcount; delay02s( ); 【例10-17】如圖10-1所示,行列式鍵盤接口中以P1.0P1.3作輸出線,以P1.4P1.7作輸入線,編寫相應的鍵盤掃描處理程序。 圖10-1 44矩陣鍵盤 C51程序清單如下:#include#define uchar unsigned char#define uint unsigned intvoid dlms (void);uchar kbscan(void); / 函數(shù)說明void main (void); uchar ke

53、y; while (1) key=kbscan( ); / 鍵盤掃描函數(shù),返回鍵碼送key保存 dlms( ); void dlms (void) / 延時 uchar i; for (i=200;i0;i- -) uchar kbscan(void) / 鍵盤掃描函數(shù) uchar sccode,recode; P1=0 xf0; /P1.0P1.3發(fā)全0,P1.4P1.7輸入 if ( (P1 & 0 xf0)! =0 xf0) /如P1口高四位不全為1有鍵按下 dlms( ); / 延時去抖動 if ( (P1 & 0 xf0) ! =0 xf0) / 在讀輸入值 sccode =0 xf

54、e / 最低位置0 while ( ( sccode & 0 x10)! =0) / 不到最后一行循環(huán) P1 =sccode; /P1口輸出掃描碼 If ( (P1 & 0 xf0)! =0 xf0) / 如P1.4P1.7不全為1,該行有鍵按下 recode = (P1 & 0 xf0; ); / 保留P1口高四位,低四位變“1”,作為列值 return( (sccode) + (recode) ); /行碼+列值=鍵編碼返回主程序 else sccode =(sccode1) | 0 x01; / 如該行無鍵按下,查下一行,行掃描值左移一位 return(0); / 無鍵按下,返回值為0

55、10.6.3 C51中斷程序的編制 中斷服務程序定義為函數(shù),函數(shù)的完整定義如下。 返回值 函數(shù)名(參數(shù))模式再入interrupt musing n 必選項 interrupt m表示將函數(shù)聲明為中斷服務函數(shù),系統(tǒng)編譯時把對應函數(shù)轉化為中斷函數(shù),自動加上程序頭段和尾段,并按MCS-51系統(tǒng)中斷的處理方式自動把它安排在程序存儲器中的相應位置。m可以是031間的整數(shù),對應的中斷情況如下:0外部中斷01定時/計數(shù)器T02外部中斷13定時/計數(shù)器T14串行口中斷5定時/計數(shù)器T2 其它值預留。 C51編譯器對中斷函數(shù)編譯時會自動在程序開始處對ACC、B、DPH、DPL和PSW入棧,結束時出棧。可選修飾

56、符using n用于指定本函數(shù)內部使用的工作寄存器組,其中n的取值為03,表示寄存器組號?!纠?0-18】編寫一個用于統(tǒng)計外中斷0的中斷次數(shù)的中斷服務程序extern int x;void int0( ) interrupt 0 using 1 x+; 本例中加入using 1后,C51在編譯時自動的在函數(shù)的開始處和結束處加入以下指令: PUSH PSW; / 標志寄存器入棧 MOV PSW,#; / 修改PSW中的工作寄存器組選擇位 POP PSW; / 標志寄存器出棧10.6.4 定時/計數(shù)器的C51編程【例10-19】 設單片機的晶體振蕩頻率fosc=6MHz,要求在P1.7腳上輸出周期

57、為4ms的方波,編寫相應的控制程序。分析:周期為4ms的方波要求定時時間隔2ms,每次時間到P1.7取反。 機器周期=12/fosc=2s 需計數(shù)次數(shù)=2000/(12/fosc)=2000/2=600 由于計數(shù)器是加1計數(shù),為得到600個計數(shù)之后的定時器溢出,必須給定時器置初值為-600(即600的補數(shù))。方法一:采用查詢式控制方式,選用定時器0,工作于方式1,編程如下: # include sbit P1_7=P17 ; void main(void) TMOD=0 x01; / 設置定時器1為非門控制方式1 TR0=1 ; / 啟動定時器/計數(shù)器T0 for( ; ; ) TH0= -(

58、600/256) ; / 裝載計數(shù)器初值 TL0= -(600%256) ; do while (!TF0) ; / 查詢等待TF0置位 P1_7=!P1_7; / 定時時間到P1.7反相 TF0=0; / 軟件清 TF0 方法二:采用中斷控制方式,仍選用用定時器0,工作于方式1。程序如下: # include sbit P1_7=P17 ; void time (void) interrupt 1 using 1 / 定時器/計數(shù)器T0中斷服務程序入口 P1_7=!P1_7 ; / P1.7取反 TH0= -(600/256); / 重新裝載計數(shù)初值 void main(void) TMOD=0 x01 ; / T0工作在定時器非門控制方式1 P1_7=0; TH0= -(600/256 ); / 預置計數(shù)初值 TL0= -(600%256) ; EA=1 ; / CPU中斷開放 ET0= 1 ; / 定時器/計數(shù)器T0中斷開放 TR0=1 ; / 啟動T0開始定時 do while(1) ; / 等待中斷 10.6.5 串行通信的C

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論