版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第10章目錄10.1C51程序設(shè)計基礎(chǔ)10.1.1C51中的基本數(shù)據(jù)類型10.1.2C51中擴充的數(shù)據(jù)類型10.1.3C51中的運算符10.1.4C51中的語句及程序結(jié)構(gòu)10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序10.2.3單個中斷系統(tǒng)設(shè)計舉例10.2.4定時器程序設(shè)計舉例10.2.5串行通信程序設(shè)計舉例10.1C51程序設(shè)計基礎(chǔ)10.1.1C51中的基本數(shù)據(jù)類型C語言中的數(shù)據(jù)有常量和變量之分,當(dāng)我們在編寫單片機程序時,用到的相關(guān)變量在單片機的內(nèi)存中都要占據(jù)一定的存儲空間,變量大小不同,所占據(jù)的空間就不同,所以,“變量”數(shù)據(jù)的大小是有限制的,我們不能隨意給一個變量賦任意大小的值。為了合理利用內(nèi)存空間,我們在編程時就要選擇大小合適的數(shù)據(jù),不同的數(shù)據(jù)類型也就代表了不同大小的數(shù)據(jù),所以,我們在使用變量之前,首先要聲明這個變量的類型,以便讓編譯器提前從內(nèi)存中為其分配空間。表10-1列出了C51的基本數(shù)據(jù)類型。10.1C51程序設(shè)計基礎(chǔ)10.1.1C51中的基本數(shù)據(jù)類型表10-1C51的基本數(shù)據(jù)類型數(shù)據(jù)類型關(guān)鍵字長度取值范圍字符型字符型char1字節(jié)-128~+127無符號字符型usignedchar1字節(jié)0~255有符號字符型signedchar1字節(jié)-128~+127整型基本型無符號usignedint2字節(jié)0~65535有符號[signed]int2字節(jié)-32768~+32767短整型無符號usignedshort[int]2字節(jié)0~65535有符號[signed]short[int]2字節(jié)-32768~+32767長整型無符號usignedlong[int]4字節(jié)0~4294967295有符號[signed]long[int]4字節(jié)-2147483648~+2147483647浮點型單精度float4字節(jié)-3.4×10-38~3.4×1038雙精度double8字節(jié)-1.7×10-308~1.7×10308長雙精度longdouble16字節(jié)-1.2×10-4932~1.7×104932位類型bit1位0~110.1C51程序設(shè)計基礎(chǔ)10.1.1C51中的基本數(shù)據(jù)類型說明:(1)在單片機中,所有的數(shù)據(jù)都是以二進(jìn)制的形式存儲在存儲器中的,其中,1個字節(jié)=8位二進(jìn)制(即1Byte=8bit)。(2)在C語言中:shortint即為int,longint即為long。(3)前面若無unsigned則一律認(rèn)為是signed型。(4)一般情況下,float型數(shù)據(jù)只能提供7位有效數(shù)字,double型數(shù)據(jù)能夠提供15~16位有效數(shù)字,但是這個精度還和編譯器有關(guān)系,并不是所有的編譯器都遵守這條原則。10.1C51程序設(shè)計基礎(chǔ)10.1.1C51中的基本數(shù)據(jù)類型例如:floatx;x=32.45678912;由于float類型的有效數(shù)字是7位,故x=32.45679,若將x改成double類型的則能將32.45678912全部存放在x中,所以,在聲明變量時應(yīng)根據(jù)其使用情況來為其選擇類型。例如:inti=9;在內(nèi)存中占16位(即2個字節(jié)的存儲單元)。10.1C51程序設(shè)計基礎(chǔ)10.1.2C51中擴充的數(shù)據(jù)類型在C51中除以上基本數(shù)據(jù)類型外,為了適應(yīng)單片機程序開發(fā)的需要又?jǐn)U充了如下的數(shù)據(jù)類型。位變量聲明bit:聲明一個位變量。8位寄存器聲明sfr:聲明一個8位寄存器。16位寄存器聲明sfr16:聲明一個16位寄存器。特殊功能位聲明sbit:聲明特殊功能寄存器中的某一位。10.1C51程序設(shè)計基礎(chǔ)10.1.2C51中擴充的數(shù)據(jù)類型bitflag;
說明:聲明了一個變量名為flag的位變量。sfrTCON=0x88H;
說明:單片機內(nèi)部有很多特殊功能寄存器(sfr),每個sfr在單片機內(nèi)部都分配有唯一的一個地址,當(dāng)我們在程序中使用sfr時,我們一般通過聲明將相應(yīng)的地址編號賦給一個名稱,以后通過該名稱來使用相應(yīng)sfr,其中這些聲明絕大多數(shù)都包含在相應(yīng)的頭文件(如:reg51.h)中。本例中TCON是單片機的定時器/計數(shù)器控制寄存器,它在單片機內(nèi)存中的地址為0x88H,經(jīng)過該語句聲明以后,如在后面的程序中使用該寄存器則只需使用其名稱TCON即可,當(dāng)程序進(jìn)行編譯時,編譯器也知道實際要操作的是單片機內(nèi)部0x88地址處的這個寄存器,而TCON僅僅是這個地址的一個代號或名稱而已,當(dāng)然,我們也可以聲明成其他的名稱。10.1C51程序設(shè)計基礎(chǔ)10.1.2C51中擴充的數(shù)據(jù)類型sfr16T1=0x8BH;
說明:
聲明了一個16位SFR,起始地址為0x8BH,道理與上例相同不再重復(fù)解釋。sbitTR0=TCON^4;說明:
首先應(yīng)該有sfrTCON=0x88H;這句的聲明后,我們才知道TCON是定時器/計數(shù)器控制寄存器的名稱,它是一個8位的寄存器,其中,TCON^0為最低位,TCON^7為最高位,通過本例的聲明,以后當(dāng)我們使用TCON^4時,直接操作TR0即可,當(dāng)然,我們也可以將TCON^4聲明成其他的名稱。10.1C51程序設(shè)計基礎(chǔ)10.1.3C51中的運算符絕大多數(shù)的程序都需要對數(shù)據(jù)進(jìn)行加工處理,即進(jìn)行運算,要進(jìn)行運算就得規(guī)定可以使用的運算符,C51中的運算符與C語言基本相同,在單片機程序開發(fā)過程中最常用的主要有算術(shù)運算符、關(guān)系運算符、邏輯運算符和位運算符等。10.1C51程序設(shè)計基礎(chǔ)10.1.3C51中的運算符說明:(1)“==”表示測試兩數(shù)是否相等,如a==b,測試a和b中的值是否相等。(2)“!=”表示測試兩數(shù)是否不相等,如a!=b,測試a和b中的值是否不相等。10.1C51程序設(shè)計基礎(chǔ)10.1.3C51中的運算符說明:(1)右移,操作符為“>>”,每執(zhí)行一次右移指令,被操作數(shù)的各位依次向右移動一位,其中,最高位補0,最低位移入PSW寄存器CY位,CY位中原來的數(shù)被覆蓋。如圖10-1所示。(2)左移,操作符為“<<”,每執(zhí)行一次左移指令,被操作數(shù)的各位依次向左移動一位,其中,最高位移入PSW寄存器CY位,CY位中原來的數(shù)被覆蓋,最低位補0,如圖10-2所示。10.1C51程序設(shè)計基礎(chǔ)10.1.3C51中的運算符其他運算符賦值運算符:=條件運算符:?:逗號運算符:,指針運算符:*和&求字節(jié)運算符:sizeof強制類型轉(zhuǎn)換運算符:(類型)成員運算符:.—>下標(biāo)運算符:[]其他10.1C51程序設(shè)計基礎(chǔ)10.1.4C51中的語句及程序結(jié)構(gòu)1、語句
C51程序是由語句組成的,其中,語句可分為以下幾類:(1)表達(dá)式語句:
由一個表達(dá)式(賦值表達(dá)式、算術(shù)運算表達(dá)式、關(guān)系表達(dá)式、邏輯表達(dá)式等)加上一個分號構(gòu)成,最典型的就是賦值表達(dá)式構(gòu)成的賦值語句。例如:x=3.6;(2)函數(shù)調(diào)用語句:由一個函數(shù)調(diào)用加上一個分號構(gòu)成。例如:printf(“Helloeveryone!”);說明:在屏幕上輸出顯示Helloeveryone!10.1C51程序設(shè)計基礎(chǔ)10.1.4C51中的語句及程序結(jié)構(gòu)(3)控制語句:條件語句:if、switch。循環(huán)語句:for、while、dowhile??刂妻D(zhuǎn)移語句:break、continue、return、goto。(4)復(fù)合語句:
用{}把一些語句和聲明括起來就構(gòu)成了復(fù)合語句。{floatx=3,y=9,z;z=x+y;printf(“z=%f”,z);}(5)空語句:只有一個分號;什么也不做,可以作為程序流程的轉(zhuǎn)向點,也可用作循環(huán)語句的循環(huán)體(循環(huán)體是空語句)。10.1C51程序設(shè)計基礎(chǔ)10.1.4C51中的語句及程序結(jié)構(gòu)2、程序結(jié)構(gòu)由以上語句可以構(gòu)成C程序的三大結(jié)構(gòu),即順序結(jié)構(gòu)、選擇結(jié)構(gòu)(分支結(jié)構(gòu))、循環(huán)結(jié)構(gòu)。(1)順序結(jié)構(gòu):僅僅是簡單的一個語句一個語句的執(zhí)行。(2)選擇結(jié)構(gòu):主要由條件語句構(gòu)成。(3)循環(huán)結(jié)構(gòu):主要由循環(huán)語句構(gòu)成,與標(biāo)準(zhǔn)C語言一樣,循環(huán)結(jié)構(gòu)中可以使用break、continue、return、goto。10.1C51程序設(shè)計基礎(chǔ)10.1.5C51中的頭文件C51中已定義的常用的頭文件主要有如下類別:absacc.h---包含允許直接訪問8051不同存儲區(qū)的宏定義。assert.h---文件定義assert宏,可以用來建立程序的測試條件。ctype.h---字符轉(zhuǎn)換和分類程序。math.h---數(shù)學(xué)函數(shù)程序。reg51.h---51的特殊寄存器聲明。reg52.h---52的特殊寄存器聲明。setjmp.h---定義jmp_buf類型和setjmp和longjmp程序的原型。stdarg.h---可變長度參數(shù)列表程序。stdlib.h---存儲器分配程序。stdio.h---流輸入和輸出程序。string.h---字符轉(zhuǎn)操作程序,緩沖區(qū)操作程序。10.1C51程序設(shè)計基礎(chǔ)10.1.5C51中的頭文件
在單片機程序中,經(jīng)常使用的頭文件主要有math.h、reg51.h或reg52.h、stdio.h等。1、頭文件math.h頭文件math.h是數(shù)學(xué)函數(shù)庫,各種數(shù)學(xué)計算函數(shù)的具體實現(xiàn)就放在文件math.h里,比如,平方根函數(shù)sqrt、絕對值函數(shù)fabs、指數(shù)函數(shù)exp、正弦函數(shù)sin、余弦函數(shù)cos等,當(dāng)我們需要使用時可以直接調(diào)用這些函數(shù)。2、頭文件reg51.h和reg52.h頭文件reg51.h或reg52.h是聲明51單片機或52單片機特殊功能寄存器和位寄存器的,這兩個頭文件中大部分內(nèi)容是一樣的,51單片機比52單片機少一個定時/計數(shù)器T2,因此,reg51.h中也就比reg52.h中少了幾行對寄存器T2聲明的內(nèi)容。10.1C51程序設(shè)計基礎(chǔ)10.1.5C51中的頭文件
在單片機程序中,經(jīng)常使用的頭文件主要有math.h、reg51.h或reg52.h、stdio.h等。⒊、頭文件stdio.h包含了與標(biāo)準(zhǔn)輸入輸出庫有關(guān)的變量定義和宏定義以及對函數(shù)的聲明,標(biāo)準(zhǔn)輸入輸出函數(shù)主要有printf、scanf、putchar、getchar等。除以上已定義的頭文件外,用戶也可以根據(jù)自己的需要定義擴展名為.h的頭文件,存放到指定的目錄下,在編程中可以直接使用。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例【例10-1】在8051單片機中,利用定時器T0產(chǎn)生50ms的定時時間。通過本例我們將對頭文件、主函數(shù)main()、注釋等三個方面的知識點做講解。程序代碼如下:#include<reg51.h>//包含頭文件voidmain() {TMOD=0x01;
//設(shè)置定時器0為方式1、定時模式TH0=(65536-45872)/256//裝初值TL0=(65536-45872)%256; TR0=1; //啟動定時器0while(1)//程序停止}10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例說明:(1)按照定時/計數(shù)器的初始化流程,首先設(shè)置TMOD=0x01,置T0工作于方式1、定時模式,給TH0和TL0裝入初值,之后啟動定時器開始計時,獲得50ms的時間。(2)下面說一下初值的計算。晶振頻率為fosc=11.0592Mhz機器周期T=12*1/fosc=12*1/11.0592Mhz=1.09μs計數(shù)值=50×10-3/(1.09×10-6)=45872因單片機的定時器是加法計數(shù)器,如果想獲得50ms的定時時間,我們就要給TH0和TL0裝入計數(shù)初值X,在這個初值的基礎(chǔ)上計45872個數(shù)至65536(方式1的溢出值216),定時器溢出,此時剛好50ms。因此,計數(shù)初值X=65536-45872=19664。在編寫程序時要將計數(shù)值轉(zhuǎn)換成16進(jìn)制的,我們采用下面的方法轉(zhuǎn)換,把19664對256求模,即19664/256裝入THO中,把19664對256求余,即19664%256裝入TLO中。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例1、頭文件(1)頭文件包含的書寫方法:兩種當(dāng)使用#include<reg51.h>時(即本例中所使用的方法),編譯器先進(jìn)入到軟件安裝文件夾(Keil\C51\INC)處開始搜索這個頭文件,如果這個文件夾下沒有引用的頭文件,編譯器將會報錯。當(dāng)使用#include“reg51.h”時,編譯器先進(jìn)入到當(dāng)前工程所在文件夾處開始搜索該頭文件,如果當(dāng)前工程所在文件夾下沒有該頭文件,編譯器將繼續(xù)回到軟件安裝文件夾處搜索這個頭文件,若仍然找不到該頭文件,編譯器將報錯。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例1、頭文件(2)頭文件中的內(nèi)容:
在安裝好Keiluvision3編譯軟件后,我們可以到Keil\C51\INC這個文件夾下找到頭文件reg51.h或者在Keil中編輯程序時鼠標(biāo)移動到reg51.h上,單擊右鍵選擇Opendocument<reg51.h>也可以打開,打開之后其具體內(nèi)容參考教材。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例1、頭文件說明:在該頭文件中聲明了51系列單片機內(nèi)部的21個特殊功能寄存器的名稱和可以進(jìn)行位操作的特殊功能寄存器中的各個位的名稱。在這里主要用到了前面講到的sfr和sbit這兩個關(guān)鍵字。例如:sfrTMOD=0x89;把單片機內(nèi)部地址0x89處的這個寄存器重新命名為TMOD,以后在程序中使用該寄存器時直接使用TMOD即可,如上例所示。其實,對單片機而言它只知道它的內(nèi)部地址0x89是什么,而并不知道TMOD是什么,現(xiàn)在通過sfrTMOD=0x89;這條語句,單片機就清楚了程序中的TMOD具體指什么了。因此,以后凡是編寫5l內(nèi)核單片機程序時,我們在源代碼的前面都應(yīng)寫上#include<reg51.h>或#include“reg51.h”。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例1、頭文件例如:sbitEA=IE^7;或sbitEA=0xAF;(有一些頭文件也這樣書寫,0xAF是IE寄存器中的最高位的地址,與IE^7的寫法作用相同)把IE這個寄存器中的最高位重新命名為EA,以后單獨操作EA即可。本例中的TMOD、TH0、TL0、TR0四個名稱之所以能在程序中代表相關(guān)寄存器來使用,就是因為它們已經(jīng)在頭文件中進(jìn)行了聲明。注意:在應(yīng)用時,如果將大寫的TMOD或EA寫成小寫的tmod或ea,編譯程序時將會出錯,找不到tmod或ea,因為在頭文件中定義的是“sfrTMOD=0x89;”“sbitEA=IE^7;”都是大寫的,這也是大多數(shù)初學(xué)者開始編寫程序時容易犯的錯誤。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例2、主函數(shù)main()一個沒有返回值,沒有參數(shù)的函數(shù)。格式:voidmain()或voidmain(void)說明:(1)任何一個C程序中可以包含一個或多個函數(shù),其中必須包含main函數(shù)(且只能有一個),本例中只有一個函數(shù)main(),它是整個程序開始執(zhí)行的入口,所有的單片機在運行程序時,總是從主函數(shù)開始運行的。(2)無返回值的函數(shù):main()是一個無返回值的函數(shù),其前面的void表示無返回值的意思(void可省略不寫),該函數(shù)執(zhí)行完后不返回任何值。(3)無參數(shù)的函數(shù):main()是一個無參數(shù)的函數(shù),表示該函數(shù)不帶任何參數(shù),即main后面的括號中沒有任何參數(shù),括號中是空的或void。(4)在main()之后有兩個大括號{},程序中所有的代碼都寫在兩個大括號內(nèi),代碼中的每條語句后都要加上分號,語句與語句之間可以用空格或回車隔開。10.2C51程序設(shè)計10.2.1定時/計數(shù)器初始化程序設(shè)計舉例3、注釋注釋有兩種寫法:(1)∥……只能注釋一行,當(dāng)換行時,需要在新行上重新寫兩個斜扛進(jìn)行注釋。(2)/*…*/可以注釋任意行,即斜扛星號與星號斜扛之間的所有文字都作為注釋。所有注釋都不參與程序編譯,編譯器在編譯過程中會自動刪除注釋,一般在編寫較大的程序時都應(yīng)加上注釋,這樣,以后當(dāng)我們再次讀程序時,因為有了注釋,其代碼的意義便一目了然了。若無注釋,我們不得不將程序重新閱讀一遍方可知道代碼含義。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序?qū)崿F(xiàn)流水燈,可以用移位操作來實現(xiàn),也可以用C51自帶的函數(shù)來實現(xiàn)。1、循環(huán)移位操作在10.1節(jié)中我們介紹了移位運算符,這里我們來學(xué)習(xí)循環(huán)移位操作。(1)循環(huán)右移被操作數(shù)的各位依次向右移動一位,其中,最低位移入最高位。C語言中沒有專門的循環(huán)右移位運算符,我們可以利用右移位運算符編寫程序?qū)崿F(xiàn)循環(huán)右移位,或直接利用C51中自帶的庫函數(shù)_cror_來實現(xiàn)。循環(huán)右移位操作,如圖10-3所示。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序【例10-2】編寫程序?qū)崿F(xiàn)如下功能,使變量t中的值循環(huán)右移位。#include<reg51.h>//包含頭文件unsignedchart;//定義無符號字符類型變量tvoidmain()//主函數(shù){t=0x66;//給t賦初始值while(1)//循環(huán)程序,每次循環(huán)使t中的當(dāng)前值左移1位{t=t>>1;}}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序(2)循環(huán)左移
被操作數(shù)的各位依次向左移動一位,其中,最高位移入最低位。C語言中沒有專門的循環(huán)左移位運算符,我們可以利用左移位運算符編寫程序?qū)崿F(xiàn)循環(huán)左移,或直接利用C51庫中自帶的函數(shù)_crol_來實現(xiàn)。循環(huán)左移位操作,如圖10-4所示。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序【例10-3】編寫程序?qū)崿F(xiàn)如下功能,使變量t中的值循環(huán)左移位。#include<reg51h>//包含頭文件unsignedchart;//定義無符號字符類型變量tvoidmain()//主函數(shù){t=0x55;//給t賦初始值while(1)//循環(huán)程序,每次循環(huán)使t中的當(dāng)前值左移1位{t=t<<1;}}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序2、移位函數(shù)_crol_介紹大家打開Keil軟件安裝文件夾,定位到Keil\C51\HLP文件夾,打開此文件夾下的C51lib文件,這是C51自帶庫函數(shù)幫助文件。在索引欄我們找到_crol_函數(shù),雙擊打開它的介紹,內(nèi)容如下:#include<intrins.h>unsignedchar_crol_(unsignedcharc,/*charactertorotateleft*/unsignedcharb);/*bitpositionstorotate*/10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序2、移位函數(shù)_crol_介紹大家打開Keil軟件安裝文件夾,定位到Keil\C51\HLP文件夾,打開此文件夾下的C51lib文件,這是C51自帶庫函數(shù)幫助文件。在索引欄我們找到_crol_函數(shù),雙擊打開它的介紹,內(nèi)容如下:#include<intrins.h>unsignedchar_crol_(unsignedcharc,/*charactertorotateleft*/unsignedcharb);/*bitpositionstorotate*/函數(shù)_crol_是C51自帶的內(nèi)部庫函數(shù),在使用這個函數(shù)之前,需要在程序開頭包含它所在的頭文件(即#include<intrins.h>)。_crol_是一個有返回值、帶參數(shù)的函數(shù),其功能是將字符c循環(huán)左移b位同時將左移之后的值返回。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序【例10-4】編程實現(xiàn)如下功能,將變量a中的二進(jìn)制值向左移3位。#include<intrins.h>//包含頭文件voidmain(){chara;//定義字符類型的變量acharb;//定義字符類型的變量ba=0xA5;//給a賦初始值b=_crol_(a,3);/*移位后的值返回給b故b=0x2D*/}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序3、流水燈程序的實現(xiàn)【例10-5】參考第二章的圖2-12,利用C51自帶的庫函數(shù)_crol_,每隔300ms依次點亮發(fā)光二級管,實現(xiàn)流水燈的程序。通過本例我們將對#define宏定義、循環(huán)語句for和while、自定義子函數(shù)等三個方面知識進(jìn)行講解。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序3、流水燈程序的實現(xiàn)程序代碼如下所示:#include<reg51.h> //包含頭文件#include<intrins.h>#defineucharunsignedchar//宏定義#defineuintunsignedint voiddelay(uint); //聲明子函數(shù)uchart;10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序3、流水燈程序的實現(xiàn)程序代碼如下所示:voidmain() //主函數(shù){t=0xfe; //給t賦初值11111110while(1) //循環(huán)點亮發(fā)光二級管{P1=t;delay(300);//延時300毫秒t=_crol_(t,1);//將t循環(huán)左移1位后再賦給t} }voiddelay(uintx)//延時1ms子函數(shù){uinti,j;for(i=x;i>0;i--) for(j=110;j>0;j--);}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序3、流水燈程序的實現(xiàn)對于程序中“t=_crol_(t,1);”語句,因為_crol_是一個帶返回值的函數(shù),本句在執(zhí)行時,先執(zhí)行等號右邊的表達(dá)式,即將t的值循環(huán)左移一位,然后將結(jié)果再重新賦給t,如t初值為0xfe,二進(jìn)制為11111110,執(zhí)行此函數(shù)后值為11111101,即0xfd,然后再將0xfd重新賦給t變量,點亮第2個發(fā)光二級管,依次循環(huán)點亮后面的發(fā)光二極管。除這種方法實現(xiàn)流水燈外,利用左移、右移指令與邏輯運算指令也可以實現(xiàn)循環(huán)移位,大家若感興趣可以自己編寫這方面的程序。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序4、#define宏定義(1)格式:#define新名稱原名稱注意后面沒有分號,#define命令可以解釋為給“原名稱”重新起一個比較簡單的“新名禰”,方便以后在程序中直接使用簡短的新名稱,而不必每次都寫煩瑣的原名稱。(2)本例中我們使用宏定義的目的就是將unsignedint用uint代替,在上面的程序中可以看到,當(dāng)我們需要定義unsignedint型變量時,并沒有寫“unsignedinti,j;”,取而代之的是“uinti,j;”,在一個程序代碼中,只要宏定義過一次,那么在整個代碼中都可以直接使用它的“新名稱”。注意,對同一個內(nèi)容,宏定義只能定義一次,若定義兩次,將會出現(xiàn)重復(fù)定義的錯誤提示。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while(1)for語句格式:for(表達(dá)式1;表達(dá)式2;表達(dá)式3){語句}說明:對于{語句}大括號中的語句如果沒有,可以為空或不寫大括號。三個表達(dá)式之間必須用分號分隔。for語句執(zhí)行步驟:第1步:求解一次表達(dá)式1,設(shè)置初始條件,可以為0個、1個或多個變量賦初值。第2步,求解循環(huán)條件表達(dá)式2,若其值為真(非0即為真),則執(zhí)行for中語句,然后執(zhí)行第3步;否則結(jié)束for語句,直接跳出,不再執(zhí)行第3步。第3步,求解表達(dá)式3。第4步,跳到第2步重復(fù)執(zhí)行。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while延時時間:
for循環(huán)在本例題中的應(yīng)用是利用for語句(或while語句)經(jīng)過若干次循環(huán)以后,可以獲得所需的延時時間,下面就是用for語句來寫的一個簡單的延時程序段。unsignedintj;for(j=1;j<=200;j++);看上面這兩句,首先定義一個無符號整型變量j,之后,進(jìn)入for循環(huán),單片機在執(zhí)行for語句的時候是需要時間的,上面的延時程序段for語句重復(fù)執(zhí)行了200次,從而可以獲得一個延時時間,因此,我們就可以利用單片機執(zhí)行for循環(huán)(或其他循環(huán)語句)來獲得延時時間。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while在語句for(j=1;j<=200;j++);中如果我們將j<=200改為j<=65536想獲得更大的延時時間,那么程序運行時將會出現(xiàn)問題,為什么呢?因為j是一個無符號整數(shù)其最大的值為65535,所以,程序運行后就會出現(xiàn)問題,將達(dá)不到我們所需要的時間。這是很多初學(xué)者最容易犯的錯誤。因此我們尤其要注意,在使用變量時首先要考慮變量類型,然后根據(jù)變量類型賦一個合理的值。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while那么,怎樣才能通過for語句寫出更長的延時時間呢?在下例中所使用的兩層嵌套for語句即可獲得。uinti,j;for(i=x;i>0;i--) for(j=100;j>0;j--);第一個for后面沒有分號,那么編譯器默認(rèn)第二個for語句就是第一個for語句的內(nèi)部語句,而第二個for語句內(nèi)部語句為空,程序在執(zhí)行時,第一個for語句中的i每減一次,第二個for語句便執(zhí)行100次,因此上面這個例子便相當(dāng)于共執(zhí)行了110×x次for語句。通過這種嵌套我們便可以獲得較長的時間延時,我們還可以進(jìn)行更多層的嵌套來增加延時時間,或是改變變量類型等來增加執(zhí)行時間。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while在C語言中這種延時語句不好算出它的精確時間,如果需要非常精確的延時時間,我們在前面講到利用單片機內(nèi)部的定時器來延時,它的精度非常高,可以精確到微秒級。而一般的簡單延時語句實際上我們并不需要太精確。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序5、循環(huán)語句for和while(2)while語句介紹格式:while(表達(dá)式){語句}特點:先判斷表達(dá)式,后執(zhí)行內(nèi)部語句。原則:若表達(dá)式為真,那么執(zhí)行內(nèi)部語句。否則跳出while語句,執(zhí)行后面的語句。需要注意如下的三點:在C語言中我們一般把“0”認(rèn)為是“假”,“非0”認(rèn)為是“真”,也就是說,只要不是0就是真,所以,非0的數(shù)都是真。{語句}中的語句部分可以是語句塊,也可以為空,就是說“while(1){};”或“while(1);”也正確,但分號“;”一定不能少,否則while()會把跟在它后面第一個分號前的語句認(rèn)為是它的內(nèi)部語句;10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序例如:while(1)P0=11;P1=22;…上面這個例子中,while()會把“P0=11;”當(dāng)做它的語句,即使這條語句并沒有加大括號。因此,以后在寫程序時,如果while()內(nèi)部只有一條語句,我們就可以省去大括號,而直接將這條語句跟在它的后面。例如:while(1)P0=11;10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序表達(dá)式可以是一個常數(shù)、一個運算或一個帶返回值的函數(shù)。在本例中使用while語句我們將不停地循環(huán)點亮發(fā)光二級管,因為在語句while(1)中的條件是1,非0即為真,條件永遠(yuǎn)為真,因此只要程序運行,發(fā)光二級管將不停地被依次循環(huán)點亮。初學(xué)者可能會這樣想,我讓單片機把發(fā)光二極管點亮后,就讓它停止工作,不再執(zhí)行別的指令,這樣不是更好嗎?請大家注意,單片機是不能停止工作的,只要它有電,有晶振在起振,它就不會停止工作,每過一個機器周期,它內(nèi)部的程序指針就要加1,程序指針就指向下一條要執(zhí)行的指令。想讓它停止工作的辦法就是把電斷掉.不過這樣發(fā)光二極管也就不會亮了。不過我們可以將單片機設(shè)置為休眠狀態(tài)或掉電模式,這樣可以最大限度地降低它的功耗。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序6、自定義子函數(shù)在C語言中,除了系統(tǒng)自帶的庫函數(shù)比如求平方根函數(shù)sqrt、求絕對值函數(shù)fabs以及上例中用到的移位函數(shù)_crol_等外,用戶也可以根據(jù)編程需要自定義一些子函數(shù),比如有一些程序段不止一次要被用到,為了不重復(fù)編寫相同代碼,我們就可以把這樣的程序段寫成一個子函數(shù),當(dāng)在主函數(shù)或其他函數(shù)中需要用到這個程序段時,直接調(diào)用這個子函數(shù)就可以了。C語言中的自定義子函數(shù)(從帶參數(shù)與否的角度)主要分為有兩種:不帶參數(shù)的自定義子函數(shù)帶參數(shù)的自定義子函數(shù)。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序6、自定義子函數(shù)(1)不帶參數(shù)子函數(shù)的定義、聲明及調(diào)用不帶參數(shù)子函數(shù)的定義:我們以下面這個程序為例:voiddelay(){for(i=100;i>0;i--)for(j=200;j>0;j--);}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序其中,void表示這個函數(shù)執(zhí)行完后不返回任何數(shù)據(jù),即它是一個無返回值的函數(shù)。delay是函數(shù)名,這個名字只要符合C語言標(biāo)識符的命名規(guī)則即可,但是注意不要和C語言中的關(guān)鍵字相同。一般我們寫成方便記憶或讀懂的名字,也就是一看到函數(shù)名就知道此函數(shù)實現(xiàn)的內(nèi)容是什么。在這里寫成delay這個函數(shù)是一個延時子函數(shù)。緊跟函數(shù)名后面的是一個括號,這個括號里沒有任何數(shù)據(jù)或符號(即C語言當(dāng)中的“參數(shù)”),因此,這個函數(shù)是一個無參數(shù)的函數(shù)。接下來兩個大括號中包含著其他要實現(xiàn)的語句。以上講解的是一個無返回值、不帶參數(shù)的函數(shù)的定義。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序不帶參數(shù)子函數(shù)的聲明:聲明子函數(shù)的目的是為了編譯器在編譯主程序的時候,當(dāng)它遇到一個子函數(shù)時知道有這樣一個子函數(shù)存在,并且知道它的類型和帶參情況等信息,以方便為這個子函數(shù)分配必要的存儲空間。子函數(shù)可以寫在調(diào)用函數(shù)(比如main()函數(shù))的前面或后面。當(dāng)寫在main()函數(shù)后面時,必須要在調(diào)用函數(shù)之前聲明子函數(shù),聲明方法如下:將返回值特性、函數(shù)名及后面的小括號完全復(fù)制,無參函數(shù),則小括號內(nèi)為空。最后在小括號的后面必須加上分號“;”。當(dāng)寫在main()函數(shù)前面時,不需要聲明,因為寫函數(shù)體的同時就已經(jīng)相當(dāng)于聲明了函數(shù)本身。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序不帶參數(shù)子函數(shù)的調(diào)用:函數(shù)名();10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序【例10-6】編程實現(xiàn)在主函數(shù)中調(diào)用延時子程序,從而獲得一定的延時時間。#include<reg51.h>//包含頭文件#defineuintunsignedint//宏定義voiddelay();//子函數(shù)聲明voidmain(){…delay();//子函數(shù)調(diào)用
…
}voiddelay()//延時子函數(shù)定義 {uinti,j;for(i=500;i>0;i--) for(j=110;j>0;j--);}10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序本例中,我們注意到“uinti,j;”語句,i和j兩個變量的定義放到了子函數(shù)里,而沒有寫在所有函數(shù)的最外面。在函數(shù)外面定義的變量叫做全局變量;在某個函數(shù)內(nèi)部定義的變量叫做局部變量,這里i和j就是局部變量。注意:局部變量只在當(dāng)前函數(shù)中有效,程序一旦執(zhí)行完當(dāng)前函數(shù),在它內(nèi)部定義的所有變量都將自動銷毀,當(dāng)下次再調(diào)用該函數(shù)時,編譯器重新為其分配內(nèi)存空間。我們要知道.在一個程序中,每個全局變量都占據(jù)著單片機內(nèi)固定的RAM單元,局部變量是用時隨時分配,不用時立即銷毀。一個單片機的RAM是有限的,如8051只有128B的RAM,如果要定義unsignedchar型變量的話,我們最多只能定義128個。很多時候,當(dāng)寫一個比較大的程序時,經(jīng)常會遇到內(nèi)存不夠用的情況,因此我們從一開始寫程序時就要堅持能用局部變量就不用全局變量的原則,以節(jié)省內(nèi)存空間。10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序(2)帶參數(shù)子函數(shù)的定義、聲明及調(diào)用帶參數(shù)子函數(shù)的定義:【例10-5】中voiddelay(uintx)是延時1ms的帶參數(shù)子函數(shù),其定義如程序中所示。帶參數(shù)子函數(shù)的聲明:因delay寫在了被調(diào)用函數(shù)main()的后面,所以,需在前面進(jìn)行函數(shù)聲明。聲明時必須將參數(shù)類型帶上,如果有多個參數(shù),多個參數(shù)類型都要寫上,類型后面可以不跟變量名.也可以寫上變量名。帶參數(shù)子函數(shù)的調(diào)用:10.2C51程序設(shè)計10.2.2點亮發(fā)光二極管實現(xiàn)流水燈程序(2)帶參數(shù)子函數(shù)的定義、聲明及調(diào)用本例中delay后面的括號中多了一句“uintx”,x就是這個子函數(shù)所帶的參數(shù),它是一個unsignedint型變量,又叫做這個函數(shù)的形參,當(dāng)進(jìn)行函數(shù)調(diào)用時我們用一個具體真實的數(shù)據(jù)代替這個形參,這個真實數(shù)據(jù)被稱為實參,形參被實參代替之后,在子函數(shù)內(nèi)部所有和形參名相同的變量將都被實參代替。有了這種帶參函數(shù),我們要調(diào)用一個延時300ms的函數(shù)就可以寫成“delay(300);”,要延時200ms可以寫成“delay(200);”,十分方便。10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例【例10-7】用C51編程實現(xiàn)【例5-3】的功能程序代碼如下所示:#include<reg51.h>//包含頭文件sbitCINT0=P3^0; //聲明清除中斷的引腳voiddelay(unsignedinti);//delay函數(shù)聲明unsignedchararr[100];//聲明數(shù)組用于存儲外設(shè)數(shù)據(jù),容量為100,可變unsignedinta;//定義無符號整型變量a10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例voidmain(void){CINT0=0;//清除INT0時提供負(fù)脈沖IT0=0;//低電平觸發(fā)外部中斷0EX0=1; //允許外部中斷0EA=1;//CPU開中斷a=0;while(1){
…}10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例//INT0中斷服務(wù)程序voidcounter0(void)interrupt0{CINT0=1;//不清除INT0時提供負(fù)脈沖delay(100);//調(diào)用延時子程序CINT0=0;//清除INT0時提供負(fù)脈沖arr[a]=P1;//將數(shù)據(jù)存入數(shù)組delay(100);//調(diào)用延時子程序a++;}10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例voiddelay(unsignedinti)//定義延時子程序{charj;for(i;i>0;i--)for(j=200;j>0;j--);}10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例說明:C51的中斷函數(shù)格式如下:void函數(shù)名()interrupt中斷號[using工作組]{中斷服務(wù)程序代碼}其中:函數(shù)名前有void,中斷函數(shù)不返回任何值。函數(shù)名按C語言標(biāo)識符來起,但不要與C語言中的關(guān)鍵字相同。函數(shù)名后面的括號是空的,中斷函數(shù)不帶任何的參數(shù)。10.2C51程序設(shè)計10.2.3單個中斷系統(tǒng)設(shè)計舉例中斷號是指單片機的幾個中斷源的序號,如下表所示10-5,本例中所使用的是外部中斷0所以中斷號為0。using工作組,可選,確定中斷函數(shù)使用單片機內(nèi)存中4組工作寄存器中的哪一組,C51編譯器在編譯程序時會自動分配工作組,因此,可以省略不寫。10.2C51程序設(shè)計10.2.4定時器程序設(shè)計舉例【例10-8】用C51編程實現(xiàn)【例6-4】的功能。程序代碼如下:#include<reg51.h>//包含頭文件sbitWORK=P1^0;//WORK為1時包裝機工作/*系統(tǒng)初始化子函數(shù)*/voidsystem_Ini(){TMOD=0x06;//置T0工作于計數(shù)模式2TH0=0xE8; //裝入計數(shù)初值TL0=0xE8; ET0=1;//T0開中斷EA=1; //CPU開中斷TR0=1; //啟動T0}10.2C51程序設(shè)計10.2.4定時器程序設(shè)計舉例/*延時子函數(shù)*/voiddelay(unsignedinti){charj;for(i;i>0;i--)for(j=200;j>0;j--);}/*主函數(shù)*/voidmain(){system_Ini() ;//系統(tǒng)初始化while(1){
….}}10.2C51程序設(shè)計10.2.4定時器程序設(shè)計舉例/*定時計數(shù)器0的中斷函數(shù)*/voidT0zd(void)interrupt1{TH0=0xE8;//給定時器T0賦初始值TL0=0xE8;WORK=1; //包裝機工作delay(100);//延時WORK=0;//包裝機停止工作}10.2C51程序設(shè)計10.2.4定時器程序設(shè)計舉例說明:(1)voiddelay(unsignedinti)的定義出現(xiàn)在了被調(diào)用函數(shù)voidT0zd(void)interrupt1的前面,所以不需要聲明,同樣,voidsystem_Ini()的定義在main前面,所以也不需要聲明。(2)voidT0zd(void)interrupt1,序號為1即定時器0的中斷服務(wù)程序。10.2C51程序設(shè)計10.2.5串行通信程序設(shè)計舉例【例10-9】用C51編程實現(xiàn)【例7-2】的功能程序代碼如下:#include<reg51.h>//包含頭文件#include<intrins.h>#defineucharunsignedchar#defineuintunsignedintsbitSTB=P1^0;uchar
溫馨提示
- 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)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 旅游業(yè)務(wù)賦能增長
- 旅游業(yè)績超越預(yù)期
- 2025年智能制造園區(qū)廠房拆遷補償及產(chǎn)業(yè)布局協(xié)議4篇
- 個人投資企業(yè)資產(chǎn)轉(zhuǎn)讓協(xié)議版A版
- 2025柴油終端零售居間合作協(xié)議書4篇
- 2025年度茶葉產(chǎn)品研發(fā)與技術(shù)轉(zhuǎn)移合同4篇
- 2025年度海上風(fēng)電場建設(shè)分包工程合同4篇
- 2025年度教育培訓(xùn)課程定制合同書4篇
- 專業(yè)服裝面料供應(yīng)協(xié)議范本版B版
- 二零二四二手設(shè)備購買與維修合同2篇
- 2024-2025學(xué)年成都高新區(qū)七上數(shù)學(xué)期末考試試卷【含答案】
- 定額〔2025〕1號文-關(guān)于發(fā)布2018版電力建設(shè)工程概預(yù)算定額2024年度價格水平調(diào)整的通知
- 2025年浙江杭州市西湖區(qū)專職社區(qū)招聘85人歷年高頻重點提升(共500題)附帶答案詳解
- 《數(shù)學(xué)廣角-優(yōu)化》說課稿-2024-2025學(xué)年四年級上冊數(shù)學(xué)人教版
- “懂你”(原題+解題+范文+話題+技巧+閱讀類素材)-2025年中考語文一輪復(fù)習(xí)之寫作
- 2025年景觀照明項目可行性分析報告
- 2025年江蘇南京地鐵集團招聘筆試參考題庫含答案解析
- 2025年度愛讀書學(xué)長參與的讀書項目投資合同
- 電力系統(tǒng)分析答案(吳俊勇)(已修訂)
- 化學(xué)-河北省金太陽質(zhì)檢聯(lián)盟2024-2025學(xué)年高三上學(xué)期12月第三次聯(lián)考試題和答案
- 期末復(fù)習(xí)試題(試題)-2024-2025學(xué)年四年級上冊數(shù)學(xué) 北師大版
評論
0/150
提交評論