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

下載本文檔

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

文檔簡介

項目四單片機輸入輸出控制

4.1項目基本技能

4.2項目基本知識4.3技能拓展4.4互動環(huán)節(jié)4.5習題任務1霓虹燈控制

1.任務要求單片機控制8個LED燈,依次點亮每一個LED燈,實現(xiàn)霓虹燈的效果。

2.硬件電路設計

1)電路圖電路圖參見項目二任務3的圖2-41。4.1項目基本技能

2)電路圖說明從圖2-41可以看出,當P1.0~P1.7中某個引腳輸出低電平“0”時,則發(fā)光二極管上有電流流過,發(fā)光二極管發(fā)光;當對應引腳為高電平“1”時,發(fā)光二極管上無電流流過,發(fā)光二極管熄滅。

3.軟件設計

1)設計方法根據(jù)圖2-41,若每次點亮一個LED燈,則對應的P1口各引腳的狀態(tài)有8種,如表4-1所示。表4-1P1口的狀態(tài)

2)流程圖用流程圖表示指令的執(zhí)行過程,如圖4-1所示。圖4-1霓虹燈控制流程圖

3)指令代碼

(1)編寫匯編語言代碼。用匯編語言編寫的指令代碼如下:

偽指令ORG、END不是單片機的可執(zhí)行指令,ORG指定程序存放的位置,END表示程序編寫完成,要放在程序的最后面。匯編指令中的立即數(shù)既可以用二進制表示,也可以用十六進制、十進制表示,如:

MOVP1,#11111011B可寫為

MOVP1,#0FBH或MOVP1,#251子程序是指能完成明確任務、具有獨立功能且能被其他程序反復調(diào)用的程序段。調(diào)用子程序的源程序稱為主程序。子程序的首地址必須要用標號,該標號就是這個子程序的名稱。如DELAY子程序,子程序的最后要設置一條返回指令RET。(2)編寫C語言代碼。用C語言編寫的指令代碼如下:

單片機的P0、P1、P2、P3口,在頭文件reg51.h中對它們進行了定義。程序開始包含了頭文件reg51.h,所以直接對P0、P1、P2、P3進行操作。語句P1=0xfe;在C語言中表示給變量P1賦值0xfe;P1又是單片機的輸出端口,但這里是輸出到單片機的引腳控制燈的亮滅。

C語言中,函數(shù)遵循先聲明后調(diào)用的原則。如果源程序中包括很多函數(shù),通常在主函數(shù)的前面集中聲明,然后再在主函數(shù)后面一一進行定義,這樣編寫的C語言源代碼可讀性好,條理清晰,易于理解。例如delay函數(shù)的聲明與調(diào)用。

在delay子函數(shù)中,包含兩重for(?)循環(huán)語句,for(k=0;k<i;k++)為外循環(huán),表達式1為“k=0”,執(zhí)行一次,當滿足表達式2“k<i”時,執(zhí)行內(nèi)循環(huán)體“for(j=0;j<255;j++);”。內(nèi)循環(huán)體的執(zhí)行過程是:j=0執(zhí)行一次,然后進行判斷是否滿足表達式2“j<255”,滿足則執(zhí)行空語句“;”,之后執(zhí)行表達式3“j++”,結(jié)果j=1,重復執(zhí)行上述過程,直到不滿足表達式2,退出內(nèi)循環(huán),這樣空語句執(zhí)行了255次。然后執(zhí)行外循環(huán)語句表達式3“k++”,結(jié)果k=1,再重新判斷,直到不滿足“k<i”時結(jié)束循環(huán)。從以上語句執(zhí)行過程可計算出空語句執(zhí)行了255×i次,實現(xiàn)了延時的作用。在主函數(shù)中,通過改變實參的值可調(diào)整延時時間的長短,本程序?qū)崊⑷≈禐?00。

4.電路板制作

1)準備器件參照項目二任務3。

2)用面包板連接電路參照項目二任務3。

3)調(diào)試運行在Keil環(huán)境中,對源程序A4_1.ASM或C4_1.C進行編輯、匯編或編譯,生成機器代碼并下載到芯片里,接通電路板電源,可觀察到霓虹燈的顯示效果。任務2開關(guān)輸入控制

1.任務要求用8位指撥開關(guān)作為輸入設備,控制輸出端口連接的8個LED燈。當開關(guān)為ON時,則相應的LED燈就會被點亮。

2.硬件電路設計

1)電路圖開關(guān)控制電路如圖4-2所示。圖4-2開關(guān)控制電路圖

2)電路圖說明單片機P1口作為輸入端口接有一組8個撥動開關(guān),開關(guān)的另一端接地。當開關(guān)向右撥動(ON)時,P1端口對應的引腳與地相接,此時引腳為低電平;當開關(guān)向左撥動(OFF)時,P1端口對應的引腳與地斷開,此時引腳為高電平。單片機P2口作為輸出端口接有8個LED燈,若引腳輸出低電平,與之相連接的LED燈被點亮;若引腳輸出高電平,與之相連接的LED燈熄滅。

3.軟件設計

1)設計方法

P1口作為輸入端口,它的值就是開關(guān)的狀態(tài),它的值與開關(guān)狀態(tài)的對應關(guān)系如表4-2所示,P1口的值送給P2,由P2口輸出控制燈。表4-2P1口的值與開關(guān)狀態(tài)的對應關(guān)系

2)流程圖指令的執(zhí)行過程如圖4-3所示。圖4-3開關(guān)輸入控制流程圖

3)指令代碼

(1)編寫匯編語言代碼。用匯編語言編寫的指令代碼如下:

匯編語言規(guī)定,當立即數(shù)第一位數(shù)為字母時,前面要加0,如指令MOVP1,#0FFH中的立即數(shù)FFH前的“0”。

(2)編寫C語言代碼。用C語言編寫的指令代碼如下:※※※※※※※※※※※※※※※※※※※※※※※※//程序名:C4_2.C//功能:輸入到P1口的狀態(tài)送給P2口輸出顯示#include<reg51.h>voidmain() //主函數(shù){ while(1) //無限循環(huán)執(zhí)行下面括號中的語句

{

P1=0xff; //設置P1為輸入口

P2=P1; //P1值賦給P2

}}※※※※※※※※※※※※※※※※※※※※※※※※

語句While(1){循環(huán)體},表示無限循環(huán)執(zhí)行花括號中的循環(huán)體語句。若花括號中的循環(huán)體為一條空語句,如while(1)表示循環(huán)執(zhí)行空語句,即為死循環(huán),通常把該語句作為停機語句使用。4.電路板制作(1)準備器件。按表4-3準備元器件。表4-3開關(guān)輸入控制電路元器件清單

(2)編譯或匯編源程序C4_2.C或A4_2.ASM,生成目標代碼文件,將目標代碼燒錄到芯片中,參照圖4-2,用面包板搭接的電路板如圖4-4所示。

接通電源,將撥碼開關(guān)對應位置撥到“ON”位置,相應的LED燈點亮。圖4-4開關(guān)輸入控制電路板知識點1單片機的輸入輸出口

任務1中,電路板通電后,發(fā)光二極管隨著程序的運行,有規(guī)律地閃動,那么,單片機是怎樣將程序中運行的結(jié)果送給發(fā)光二極管的呢?4.2項目基本知識原來,單片機上有4組8位輸入輸出I/O口:P0、P1、P2和P3口,P1、P2和P3為準雙向口,P0口則為雙向三態(tài)輸入輸出口,它們在單片機中,主要承擔了和單片機外部設備打交道的任務,下面分別來介紹。

1.P0口

P0口的一位引腳邏輯電路如圖4-5所示。它由一個輸出鎖存器、兩個三態(tài)輸入緩沖器和輸出驅(qū)動電路及控制電路組成。從圖中可以看出,P0口既可以作為通用I/O用,也可以作為地址/數(shù)據(jù)線用。圖4-5P0口某個引腳邏輯電路

1)作為通用I/O口使用

(1)作為輸出使用。CPU發(fā)出控制電平“0”封鎖“與”門,將輸出上拉場效應管T1截止,同時使用多路開關(guān)MUX把鎖存器與輸出驅(qū)動場效應管T2的柵極接通,故內(nèi)部總線與P0口同相。由于輸出驅(qū)動級是漏極開路電路,若驅(qū)動NMOS或其他拉流負載時,需要外接上拉電阻。P0口的輸出級可驅(qū)動8個LSTTL負載。

(2)作為輸入使用。當P0口作為輸入數(shù)據(jù)使用時,分讀引腳和讀鎖存器兩種情況,為此在電路中有兩個用于讀入驅(qū)動的三態(tài)緩沖器。所謂讀引腳,就是讀芯片引腳的狀態(tài),這時使用下方的數(shù)據(jù)緩沖器,由“讀引腳”信號把緩沖器打開,把端口引腳上的數(shù)據(jù)從緩沖器通過內(nèi)部總線讀進來。讀引腳需先向電路中的鎖存器寫入“1”,使輸出級的FET截止,引腳處于懸浮狀態(tài),變?yōu)楦咦杩馆斎耄@就是所謂的準雙向口。讀鎖存器是指通過上面的緩沖器讀鎖存器Q端的狀態(tài)。

2)作為地址/數(shù)據(jù)線使用除了I/O功能以外,在進行單片機系統(tǒng)擴展時,P0口是作為單片機系統(tǒng)的地址/數(shù)據(jù)線使用的,一般稱為地址/數(shù)據(jù)分時復用引腳。當輸出地址或數(shù)據(jù)時,由內(nèi)部發(fā)出控制信號,使“控制”端為高電平,打開與門,并使多路開關(guān)MUX處于內(nèi)部地址/數(shù)據(jù)線與驅(qū)動場效應管柵極反相接通狀態(tài)。此時,輸出驅(qū)動電路由于兩個FET處于反相,形成推拉式電路結(jié)構(gòu),使負載能力大為提高。輸入數(shù)據(jù)時,數(shù)據(jù)信號直接從引腳通過輸入緩沖器進入內(nèi)部總線。P0作為地址/數(shù)據(jù)總線是真正的雙向口。

2.P1口

P1口的一位引腳邏輯電路如圖4-6所示。它由一個輸出鎖存器、兩個三態(tài)輸入緩沖器和輸出驅(qū)動電路組成準雙向口。圖4-6P1口某個引腳邏輯電路

P1口作為輸出口使用時,可以向外提供推拉電流負載,無需再外接上拉電阻;P1口作為輸入口使用時,同樣也需先向鎖存器寫“1”,使輸出驅(qū)動電路的FET截止,處于高阻態(tài),然后通過緩沖器進行輸入操作。

3.P2口

P2口的一位引腳邏輯電路如圖4-7所示。它由一個輸出鎖存器、兩個三態(tài)輸入緩沖器、一個輸出驅(qū)動電路和一個輸出控制電路構(gòu)成。其中,輸出驅(qū)動電路與P0不同,上拉電阻代替了P0中的場效應管。圖4-7P2口某個引腳邏輯電路

1)作為通用I/O口

CPU發(fā)出控制電平“0”,使多路開關(guān)MUX倒向鎖存器的輸出Q端,構(gòu)成一個準雙向口,其功能與P1相同。

2)作為地址總線在系統(tǒng)擴展片外程序存儲器擴展數(shù)據(jù)存儲器且容量超過256B時,CPU發(fā)出控制電平“1”,使多路開關(guān)MUX倒向內(nèi)部地址線。此時,P2輸出高8位地址。

4.P3口

P3口的一位引腳邏輯電路如圖4-8所示。它由一個輸出鎖存器、兩個三態(tài)緩沖器、一個輸出驅(qū)動電路和一個“與非”門構(gòu)成。圖4-8P3口某個引腳邏輯電路

1)作為通用I/O口

P3作為通用的輸入輸出并行接口,其功能與P1相同。

2)第二功能

P3口的八個引腳的第二功能如表4-4所示,需要說明的是,當P3中的引腳作為第二功能時,就不能再作為輸入輸出口使用了。表4-4P3引腳第二功能

5.輸出口的輸出能力當使用P0、P1、P2、P3口作為輸出接口時,需要考慮它的帶載能力。P1、P2、P3口的每一位可以直接驅(qū)動4個LSTTL負載;P0可以驅(qū)動8個LSTTL負載,但P0與P1、P2、P3不同,由于在它的內(nèi)部沒有上拉電阻,所以用它作為輸出接口時需要外接上拉電阻,上拉電阻R的阻值一般取5.1kΩ左右,上拉電阻的接法如圖4-9所示。圖4-9P0.0作為輸出接口時上拉電阻的接法知識點2匯編語言

1.匯編語言程序設計的基本步驟匯編語言程序設計就是針對實際應用問題,使用MCS-51系列單片機指令系統(tǒng)中的指令和偽指令,編制程序的過程。在程序設計過程中,應該在保證實現(xiàn)程序功能的前提下,使程序占用空間小,執(zhí)行速度快。匯編語言程序設計的基本步驟如下。

1)分析問題明確系統(tǒng)的功能要求與設計目標,確定算法和思路。

2)畫流程圖根據(jù)算法和思路畫出程序流程框圖。流程圖符號說明如圖4-10所示。圖4-10流程圖符號

3)分配存儲單元確定原始數(shù)據(jù)、中間數(shù)據(jù)、結(jié)果和程序在數(shù)據(jù)存儲器和程序存儲器中存放的位置。

4)編寫源程序使用集成開發(fā)環(huán)境(如Keil)在計算機上輸入程序,對程序進行匯編和運行調(diào)試,找出程序的錯誤并進行更正,再調(diào)試,直到程序通過。

2.程序的基本結(jié)構(gòu)匯編語言中的基本結(jié)構(gòu)有順序結(jié)構(gòu)、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu)和子程序結(jié)構(gòu)。單片機一個應用系統(tǒng)的匯編語言源程序,無論其系統(tǒng)功能的要求是簡單還是復雜,其程序結(jié)構(gòu)的組成基礎(chǔ)總是由順序程序、分支程序、循環(huán)程序、子程序、查表程序等結(jié)構(gòu)化程序塊組合而成。

1)順序結(jié)構(gòu)程序順序結(jié)構(gòu)程序是指程序按編寫的順序依次往下執(zhí)行每一條指令,直到最后一條,它能夠解決一些簡單的問題或作為復雜程序的一部分,其程序執(zhí)行流程如圖4-11所示。圖4-11順序結(jié)構(gòu)

2)分支結(jié)構(gòu)程序分支結(jié)構(gòu)是根據(jù)不同的條件轉(zhuǎn)移到不同分支的程序段的結(jié)構(gòu)。具有分支結(jié)構(gòu)的程序一般要使用轉(zhuǎn)移指令進行判斷和轉(zhuǎn)移,其程序執(zhí)行流程如圖4-12所示。

圖4-12分支結(jié)構(gòu)

3)循環(huán)結(jié)構(gòu)程序在實際應用中會遇到需要多次重復做的事情,如任務1中的延時,處理這種情況的程序可采用循環(huán)結(jié)構(gòu),其程序執(zhí)行流程如圖4-13所示。循環(huán)結(jié)構(gòu)的程序一般由下面四部分組成。

圖4-13循環(huán)結(jié)構(gòu)

(1)循環(huán)初始化。位于循環(huán)程序開頭,用于做好循環(huán)前的準備工作,如設置各工作單元的初始值、數(shù)據(jù)指針以及循環(huán)次數(shù)計數(shù)器的初值。

(2)循環(huán)體。循環(huán)程序的主體,位于循環(huán)體之內(nèi),是循環(huán)程序的工作程序,在執(zhí)行中會被多次重復執(zhí)行。要求編寫得盡可能簡練,以提高程序的執(zhí)行速度。

(3)循環(huán)修改。每執(zhí)行一次循環(huán)進行一次計數(shù)器值的修改,并對有關(guān)的數(shù)據(jù)及數(shù)據(jù)指針進行修改,為下一次循環(huán)做好準備。

(4)循環(huán)控制。根據(jù)循環(huán)次數(shù)計數(shù)器的現(xiàn)行值或其他條件來進行判斷,控制循環(huán)的繼續(xù)進行或結(jié)束。

具體的循環(huán)結(jié)構(gòu)又分為“先執(zhí)行后判斷”和“先判斷后執(zhí)行”兩種方式,“先執(zhí)行后判斷”方式是先進入循環(huán)體進行處理和循環(huán)修改,然后再進行循環(huán)控制判斷;“先判斷后執(zhí)行”是將循環(huán)控制判斷放在循環(huán)的入口處,如果循環(huán)條件成立則進入循環(huán)體進行處理和循環(huán)修改,循環(huán)條件不成立則退出循環(huán)。這兩種循環(huán)方式的處理流程如圖4-14所示。圖4-14循環(huán)結(jié)構(gòu)處理流程

4)主子程序

(1)子程序。子程序是指具有一定功能的獨立程序段,例如延時子程序。當需要時,可以調(diào)用這些獨立的子程序。調(diào)用程序稱為主程序,被調(diào)用的程序稱為子程序。調(diào)用程序執(zhí)行流程如圖4-15所示,主程序在指令N與指令N+1中間有一條調(diào)用指令ACALL或LCALL,當指令N執(zhí)行后,程序轉(zhuǎn)向執(zhí)行子程序,執(zhí)行完子程序的指令后,返回到主程序執(zhí)行指令N+1接著順序執(zhí)行下去,指令M+1一般為返回指令RET。圖4-15主子結(jié)構(gòu)

使用子程序應注意:

子程序的第一條指令地址稱為子程序的入口地址。該指令必須有標號,標號應以子程序的任務定名,以便一看就一目了然。

主程序調(diào)用子程序是通過安排在主程序的調(diào)用指令實現(xiàn)的,子程序返回主程序需執(zhí)行RET返回指令。

主程序調(diào)用子程序和子程序返回主程序時,計算機能自動保護和恢復主程序的斷點地址(PC值)。但對于各工作寄存器、特殊功能寄存器和內(nèi)存單元中的內(nèi)容,如果需要保護和恢復必須在子程序的開頭和末尾(RET指令前)安排一些能夠保護和恢復它們的指令。

為使所編子程序可以放在64KB內(nèi)存的任何子域并能為主程序所調(diào)用,子程序內(nèi)部必須使用相對轉(zhuǎn)移指令而不使用其他指令,以便匯編時生成浮動代碼。

子程序參數(shù)可分入口和出口參數(shù)兩類:入口參數(shù)是指子程序需要的原始參數(shù),由調(diào)用它的主程序通過約定的工作寄存器R0~R7、特殊功能寄存器SFR、內(nèi)存單元或堆棧等預先傳給子程序使用;出口參數(shù)是由子程序根據(jù)入口參數(shù)執(zhí)行程序后獲得的結(jié)果參數(shù),應由子程序通過約定的工作寄存器R0~R7、特殊功能寄存器SFR、內(nèi)存單元或堆棧等預先傳給主程序。例設R1和R2內(nèi)有兩數(shù)a和b,編寫程序求c?=?a2?+?b2并把c送入R3,a、b為小于10的整數(shù)。解:等式中a、b均求平方,因此將求平方編寫為子程序。

ORG0000HMAIN: MOVA,R1 ;入口參數(shù)a送A ACALLSQR ;求a2 MOVR1,A ;a2送R1 MOVA,R2 ;入口參數(shù)b送A ACALLSQR ;求b2

ADDA,R1 ;a2?+?b2送A

MOVR3,A ;和存入R3

SJMP$SQR: MOVDPTR,#TAB ;設置查表首地址

MOVCA,@A+DPTR ;查平方表

RET ;返回TAB: DB0,1,4,9,16,25,36,49,64,81

(2)子程序嵌套。子程序嵌套是指在子程序執(zhí)行過程中,還可以調(diào)用另一個子程序。程序執(zhí)行過程如圖4-16所示。圖4-16子程序嵌套

3.延時程序在單片機的實時控制系統(tǒng)中,常常需要用到延時操作。一般情況下,通過編寫一個延時子程序來實現(xiàn)延時操作,稱為軟件延時。延時子程序就是一個延時模塊,不僅可以在一個程序中多次調(diào)用,也可以在其他程序需要延時的地方使用,避免重復勞動。

1)延時的基本原理單片機的讀、寫操作都需要消耗一定的時間,一般用機器周期數(shù)來表示。所謂機器周期是指單片機完成一個基本操作所用的時間。機器周期等于12倍的晶振周期,若晶振頻率為12MHz,一個機器周期為12?×(1/12)MHz?=?1μs。例如:NOP空操作指令,執(zhí)行時間為一個機器周期,即1μs,DJNZ執(zhí)行時間為兩個機器周期,即需要2μs。

2)計算DELAY子程序的延時時間首先分析下面的程序段: 源程序機器周期數(shù)執(zhí)行時間MOVR0,#250 11μsDE0: NOP 11μs NOP 11μs DJNZR0,DE022μs

如圖4-17所示流程圖,程序采用循環(huán)結(jié)構(gòu)的設計方法,R0為計數(shù)器,循環(huán)體包括NOP指令、DJNZ指令。首先R0賦值250,這條指令需要1μs時間,接著執(zhí)行空操作,一個空操作耗時1μs,兩個空操作耗時2μs,接著執(zhí)行DJNZ指令耗時2μs,其作用是將R0寄存器的值減1,減1以后的值再存放在R0中,若減1之后值不為0,繼續(xù)執(zhí)行空操作,循環(huán)往復,直到R0的值為0,循環(huán)停止,這樣循環(huán)體指令執(zhí)行了250次,可計算出上述程序段的執(zhí)行時間為

[1?+?(1?+?1?+?2)?×?250]μs?=?1001μs?≈?1ms圖4-17延時1ms程序段流程圖

將1ms的程序段作為循環(huán)體,再循環(huán)200次,可實現(xiàn)延時200ms,程序流程圖如圖4-18所示,其中R1為計數(shù)器,計數(shù)200次。圖4-18DELAY子程序流程圖

DELAY子程序包含兩重循環(huán),這種結(jié)構(gòu)稱為多重循環(huán)程序結(jié)構(gòu),又稱循環(huán)嵌套。多重循環(huán)程序必須注意的是各重循環(huán)不能交叉,不能從外循環(huán)跳入內(nèi)循環(huán)。

知識點3C語言程序

C語言是一種高級程序設計語言,它提供了十分完備的規(guī)范化流程控制結(jié)構(gòu)。因此采用C51語言設計單片機應用系統(tǒng)程序時,首先要盡可能地采用結(jié)構(gòu)化的程序設計方法,這樣可使整個應用系統(tǒng)程序結(jié)構(gòu)清晰,易于調(diào)試和維護。對于一個較大的程序,可將整個程序按功能分成若干個模塊,不同的模塊完成不同的功能。對于不同的功能模塊,分別指定相應的入口參數(shù)和出口參數(shù),而經(jīng)常使用的一些程序最好編成函數(shù),這樣既不會引起整個程序管理的混亂,還可增強可讀性,移植性也好。

1.?C語言的基本結(jié)構(gòu)

C語言程序以函數(shù)形式組織程序結(jié)構(gòu),C程序中的函數(shù)與其他語言中所描述的“子程序”或“過程”的概念是一樣的。C程序基本結(jié)構(gòu)如圖4-19所示。圖4-19C程序基本結(jié)構(gòu)

一個C語言源程序是由一個或若干個函數(shù)組成,每一個函數(shù)完成相對獨立的功能。每個C程序都必須有(且僅有)一個主函數(shù)main(?),程序的執(zhí)行總是從主函數(shù)開始,調(diào)用其他函數(shù)后返回主函數(shù)main(),不管函數(shù)的排列順序如何,最后都是在主函數(shù)中結(jié)束整個程序。C語言程序的執(zhí)行部分由語句組成。C語言提供了豐富的程序控制語句,按照結(jié)構(gòu)化程序設計的基本結(jié)構(gòu):順序結(jié)構(gòu)、選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu),組成各種復雜程序,如圖4-20所示的這些語句主要包括表達式語句、復合語句、選擇語句和循環(huán)語句等。圖4-20C語言程序結(jié)構(gòu)

2.表達式語句和復合語句

1)表達式語句表達式語句是最基本的C語言語句,它由表達式加上分號“;”組成。

2)復合語句把多個語句用大括號{}括起來,組合在一起形成具有一定功能的模塊,這種由若干條語句組合而成的語句塊稱為復合語句。在程序中應把復合語句看成是單條語句,而不是多條語句。復合語句在程序運行時,{}中的各行單語句是依次順序執(zhí)行的。在C語言的函數(shù)中,函數(shù)體就是一個復合語句。

復合語句內(nèi)的各條語句都必須以分號“;”結(jié)尾,復合語句之間用{}分隔,在括號“}”外不能加分號。復合語句不僅可由可執(zhí)行語句組成,還可由變量定義語句組成。在復合語句中所定義的變量,稱為局部變量,也就是指它的有效范圍只在復合語句中。函數(shù)體是復合語句,所以函數(shù)體內(nèi)定義的變量,其有效范圍也只在函數(shù)內(nèi)部。

3.選擇語句在C語言中,選擇結(jié)構(gòu)程序設計一般用if語句或switch語句來實現(xiàn)。if語句又有if、if-else和if-else-if三種不同的形式,下面分別進行介紹。

1)基本if語句基本if語句的格式如下:if(表達式){

語句組;

}

if語句執(zhí)行過程:當“表達式”的結(jié)果為“真”時,執(zhí)行其后的“語句組”,否則跳過該語句組,繼續(xù)執(zhí)行下面的語句。如“if(P3_0==0)P1_0=0;”,當P3_0等于0時,P1_0就賦值0,執(zhí)行過程如圖4-21所示。圖4-21if語句執(zhí)行流程圖使用if語句應注意:

if語句中的“表達式”通常為邏輯表達式或關(guān)系表達式,也可以是任何其他的表達式或類型數(shù)據(jù),只要表達式的值非0即為“真”。以下語句都是合法的:

if(3){……}

if(x=8){……}

if(P3_0){……}

在if語句中,“表達式”必須用括號括起來。

在if語句中,花括號“{}”里面的語句組如果只有一條語句,可以省略花括號。如“if(P3_0==0)P1_0=0;”語句,但是為了提高程序的可讀性和防止程序書寫錯誤,建議讀者在任何情況下,都加上花括號。

2)?if-else語句

if-else語句的一般格式如下:

if(表達式) {

語句組1;

} else{

語句組2;

}

if-else語句執(zhí)行過程:當“表達式”的結(jié)果為“真”時,執(zhí)行其后的“語句組1”,否則執(zhí)行“語句組2”,執(zhí)行過程如圖4-22所示。圖4-22if-else語句執(zhí)行流程圖

3)?if-else-if語句

if-else-if語句是由ifelse語句組成的嵌套,用來實現(xiàn)多個條件分支的選擇,其一般格式如下:if(表達式1) {

語句組1;

} elseif(表達式2) {

語句組2;

} …

elseif(表達式n) {

語句組n;

}else {

語句組n+1;

}

執(zhí)行該語句時,依次判斷“表達式i”的值,當“表達式i”的值為“真”時,執(zhí)行其對應的“語句組i”,跳過剩余的if語句組,繼續(xù)執(zhí)行該語句下面一個語句。如果所有表達式的值均為“假”,則執(zhí)行最后一個else后的“語句組n+1”,然后再繼續(xù)執(zhí)行其下面一個語句,執(zhí)行過程如圖4-23所示。圖4-23if-else-if語句執(zhí)行流程圖

使用if-else-if語句應注意:

else語句是if語句的子句,它是if語句的一部分,不能單獨使用。

else語句總是與在它上面、跟它最近的if語句相配對。

4)?switch語句

if語句一般用作單一條件或分支數(shù)目較少的場合,如果使用if語句來編寫超過三個以上分支的程序,就會降低程序的可讀性。C語言提供了一種用于多分支選擇的switch語句,其一般形式如下:

switch(表達式)

{ case常量表達式1:語句組1;break; case常量表達式2:語句組2;break; …… case常量表達式n:語句組n;break; default:語句組n+1;}

該語句的執(zhí)行過程是:首先計算表達式的值,并逐個與case后的常量表達式的值相比較,當表達式的值與某個常量表達式的值相等時,則執(zhí)行對應該常量表達式后的語句組,再執(zhí)行break語句,跳出switch語句的執(zhí)行,繼續(xù)執(zhí)行下一條語句。如果表達式的值與所有case后的常量表達式均不相同,則執(zhí)行default后的語句組。

使用switch語句應注意:

在case后的各常量表達式的值不能相同,否則會出現(xiàn)同一個條件有多種執(zhí)行方案的矛盾。

在case語句后,允許有多個語句,可以不用{}括起來。例如:

case0:P1_0=1;P1_1=0;break;

case和default語句的先后順序可以改變,不會影響程序執(zhí)行結(jié)果。

“case常量表達式”只相當于一個語句標號,表達式的值和某標號相等則轉(zhuǎn)向該標號執(zhí)行,但在執(zhí)行完該標號后的語句之后,不會自動跳出整個switch語句,而是繼續(xù)執(zhí)行后面的case語句。因此,使用switch語句時,要在每一個case語句之后,加break語句,使得執(zhí)行完該case語句后可以跳出整個switch語句的執(zhí)行。

default語句是在不滿足case語句情況下的一個默認執(zhí)行語句。如果default語句后面是空語句,表示不做任何處理,可以省略。

4.循環(huán)語句在結(jié)構(gòu)化程序設計中,循環(huán)程序結(jié)構(gòu)是一種很重要的程序結(jié)構(gòu),幾乎所有的應用程序都包含循環(huán)結(jié)構(gòu)。循環(huán)的作用是對給定的條件進行判斷,當給定的條件成立時,重復執(zhí)行給定程序段,直到條件不成立時為止。給定的條件稱為循環(huán)條件,需要重復執(zhí)行的程序段稱為循環(huán)體。

前面介紹的delay()函數(shù)中使用了雙重for循環(huán),其循環(huán)體為空語句,用來消耗CPU時間,產(chǎn)生延時效果,這種延時方法稱為軟件延時。軟件延時的缺點是占用CPU時間,使得CPU在延時過程中不能做其他事情,解決的方法是使用單片機中的硬件定時器實現(xiàn)延時功能。在C語言中,可以用下面三個語句來實現(xiàn)循環(huán)程序結(jié)構(gòu):while語句、do-while語句和for語句,下面分別對它們加以介紹。

1)?while語句

while語句用來實現(xiàn)“當型”循環(huán)結(jié)構(gòu),即當條件為“真”時,就執(zhí)行循環(huán)體。while語句的一般形式為:

while(表達式)

{語句組;//循環(huán)體

}其中,“表達式”通常是邏輯表達式或關(guān)系表達式,為循環(huán)條件,“語句組”是循環(huán)體,即被重復執(zhí)行的程序段。該語句的執(zhí)行過程是:首先計算“表達式”的值,當值為“真”(非0)時,執(zhí)行循環(huán)體“語句組”,流程圖如圖4-24所示。

使用while語句時要注意:

當表達式的值為“真”時,執(zhí)行循環(huán)體,循環(huán)體執(zhí)行一次完成后,再次回到while,進行循環(huán)條件判斷,如果仍然為“真”,則重復執(zhí)行循環(huán)體,為“假”則退出整個while循環(huán)語句。

如果循環(huán)條件一開始就為假,那么while后面的循環(huán)體一次都不會被執(zhí)行。如果循環(huán)條件總為真,例如:while(1);表達式為常量“1”,非0即為“真”,循環(huán)條件永遠成立,則為無限循環(huán),即死循環(huán)。在單片機C語言程序設計中,無限循環(huán)是一個非常有用的語句。在本章所有程序示例中都使用了該語句。

除非特殊應用的情況,在使用while語句進行循環(huán)程序設計時,通常循環(huán)體內(nèi)包含有修改循環(huán)條件的語句,以使循環(huán)逐漸趨于結(jié)束,避免出現(xiàn)死循環(huán)。

在循環(huán)程序設計中,要特別注意循環(huán)的邊界問題,即循環(huán)的初值和終值要非常明確。

2)?do-while語句前面所述的while語句是在執(zhí)行循環(huán)體之前判斷循環(huán)條件,如果條件不成立,則該循環(huán)不會被執(zhí)行。實際情況往往需要先執(zhí)行一次循環(huán)體后,再進行循環(huán)條件的判斷,“直到型”do-while語句可以滿足這種要求。do-while語句一般格式如下:

do {

語句組;//循環(huán)體}while(表達式);

該語句的執(zhí)行過程是:先執(zhí)行循環(huán)體“語句組”一次,再計算“表達式”的值,如果“表達式”的值為“真”(非0),繼續(xù)執(zhí)行循環(huán)體“語句組”,直到表達式為“假”(0)為止。dowhile語句流程圖如圖4-25所示。圖4-25do-while語句執(zhí)行流程圖

同樣一個問題,既可以用while語句,也可以用do-while語句來實現(xiàn),二者的循環(huán)體“語句組”部分相同,運行結(jié)果也相同。區(qū)別在于:do-while語句是先執(zhí)行后判斷,而while語句是先判斷后執(zhí)行。如果條件一開始就不滿足,do-while語句至少要執(zhí)行一次循環(huán)體,而while語句的循環(huán)體則一次也不執(zhí)行。

使用do-while語句時應注意:

在使用if語句、while語句時,表達式括號后面都不能加分號“;”,但在do-while語句的表達式括號后面必須加分號。

do-while語句與while語句相比,更適用于處理不論條件是否成立,都需先執(zhí)行一次循環(huán)體的情況。

3)?for語句在函數(shù)delay()中,使用兩個for語句,實現(xiàn)了雙重循環(huán),重復執(zhí)行若干次空語句循環(huán)體,以達到延時的目的。在C語言中,當循環(huán)次數(shù)明確的時候,使用for語句比while和do-while語句更為方便。for語句一般格式如下:

for(循環(huán)變量賦初值;循環(huán)條件;修改循環(huán)變量)

{語句組;//循環(huán)體

}關(guān)鍵字for后面的圓括號內(nèi)通常包括三個表達式:循環(huán)變量賦初值、循環(huán)條件和修改循環(huán)變量,三個表達式之間用“;”隔開。大括號內(nèi)是循環(huán)體“語句組”。

for語句的執(zhí)行過程如下:

(1)先執(zhí)行第一個表達式,給循環(huán)變量賦初值,通常這里是一個賦值表達式。

(2)利用第二個表達式判斷循環(huán)條件是否滿足,通常是關(guān)系表達式或邏輯表達式,若其值為“真”(非0),則執(zhí)行循環(huán)體“語句組”一次,再執(zhí)行下面第(3)步;若其值為“假”(0),則轉(zhuǎn)到第(5)步循環(huán)結(jié)束。

(3)計算第三個表達式,修改循環(huán)控制變量,一般也是賦值語句。

(4)跳到上面第(2)步繼續(xù)執(zhí)行。

(5)循環(huán)結(jié)束,執(zhí)行for語句下面的一個語句。以上過程用流程圖表示如圖4-26所示。圖4-26for語句執(zhí)行流程圖

進行C51單片機應用程序設計時,無限循環(huán)也可以采用如下的for語句實現(xiàn):for(;;)

{ 循環(huán)體語句組;

}此時,for語句的小括號內(nèi)只有兩個分號,三個表達式全部為空語句,意味著沒有設初值,不判斷循環(huán)的條件,循環(huán)變量不改變,其作用相當于while(1),構(gòu)成一個無限循環(huán)過程。

while、do-while和for語句都可以用來處理相同的問題,一般可以互相代替。for語句主要用于給定循環(huán)變量初值、循環(huán)次數(shù)明確的循環(huán)結(jié)構(gòu),而要在循環(huán)過程中才能確定循環(huán)次數(shù)及循環(huán)控制條件的問題用while、do-while語句更加方便。

4)循環(huán)的嵌套循環(huán)嵌套是指一個循環(huán)(稱為“外循環(huán)”)的循環(huán)體內(nèi)包含另一個循環(huán)(稱為“內(nèi)循環(huán)”)。內(nèi)循環(huán)的循環(huán)體內(nèi)還可以包含循環(huán),形成多層循環(huán)。while、do-while和for三種循環(huán)結(jié)構(gòu)可以互相嵌套。例如,延時函數(shù)delay()中使用的雙重for循環(huán)語句,外循環(huán)的循環(huán)變量是k,其循環(huán)體又是以j為循環(huán)變量的for語句,這個for語句就是內(nèi)循環(huán),內(nèi)循環(huán)體是一條空語句。

5)在循環(huán)體中使用break和continue語句

(1)?break語句。break語句通常用在循環(huán)語句和switch語句中。在switch語句中使用break時,程序跳出switch語句,繼續(xù)執(zhí)行其后面的語句。當break語句用于while、do-while、for循環(huán)語句中時,不論循環(huán)條件是否滿足,可使程序立即終止整個循環(huán)而執(zhí)行后面的語句。通常break語句總是與if語句一起使用,即滿足if語句中給出的條件時便跳出循環(huán)。例如執(zhí)行如下的程序段:voidmain(){inti=0,sum;sum=0;for(i=1;;i++) //設置for循環(huán)

{if(i>10)break; //判斷循環(huán)是否結(jié)束,如果滿足則退出循環(huán)sum=sum+i;}}

在循環(huán)結(jié)構(gòu)程序中,既可以通過循環(huán)語句中的表達式來控制循環(huán)程序是否結(jié)束,還可以通過break語句強行退出循環(huán)結(jié)構(gòu)。在循環(huán)嵌套中,一個break語句只能向外跳一層。

(2)?continue語句。continue語句的作用是跳過循環(huán)體中剩余的語句,結(jié)束本次循環(huán),強行執(zhí)行下一次循環(huán)。它與break語句的不同之處是:break語句是直接結(jié)束整個循環(huán)語句,而continue則是停止當前循環(huán)體的執(zhí)行,跳過循環(huán)體中余下的語句,再次進入循環(huán)條件判斷,準備繼續(xù)開始下一次循環(huán)體的執(zhí)行。

continue語句只能用在for、while、do-while等循環(huán)體中,通常與if條件語句一起使用,用來加速循環(huán)結(jié)束。continue語句與break語句的區(qū)別及其執(zhí)行過程如圖4-27所示。圖4-27continue和break語句的執(zhí)行過程比較循環(huán)變量賦初值;while(循環(huán)條件){……

語句組1;修改循環(huán)變量;

if(表達式)break;

語句組2;}循環(huán)變量賦初值;while(循環(huán)條件){……

語句組1;修改循環(huán)變量;if(表達式)continue;

語句組2;

下面的程序段將求出1~20之間所有不能被5整除的整數(shù)之和。voidmain(){inti=0,sum;sum=0;for(i=1;i<=20;i++)//設置for循環(huán)

{

if(i%5==0)continue;//若i對5取余運算,若結(jié)果為0,即i能整除5,

//執(zhí)行continue語句,跳過下面求和語句,程序繼續(xù)執(zhí)

//行for循環(huán)sum=sum+i;//循環(huán);如果i不能被5整除,則執(zhí)行求和語句。

}}任務3蜂鳴器的控制

1.任務要求使用單片機的輸出口控制蜂鳴器發(fā)聲。

2.硬件電路設計

9013是一個NPN的三極管,如圖4-28所示1管腳為發(fā)射極,2管腳為基極,3管腳為集電極。圖4-29為蜂鳴器實物圖。

4.3技能拓展

圖4-289013三極管圖4-29蜂鳴器

由圖4-30所示的電路原理可知,蜂鳴器的正極接電源,蜂鳴器的負極與NPN型三極管的集電極連接,三極管的基極通過電阻與單片機的P2.3引腳相連,當P2.3輸出高電平時,三極管導通,蜂鳴器中有電流;當P2.3輸出低電平時,三極管截止,蜂鳴器中沒有電流。通過P2.3反復輸出高低電平,高低電平之間延時一段時間,就能產(chǎn)生一定頻率的方波,使蜂鳴器發(fā)聲。圖4-30蜂鳴器控制電路

3.軟件設計

1)流程圖蜂鳴器控制流程圖如圖4-31所示。圖4-31蜂鳴器控制流程圖

2)指令代碼

(1)編寫匯編語言代碼。用匯編語言編寫的指令代碼如下:

人耳可以聽到的振動頻率是20~20000Hz,頻率不同所產(chǎn)生的音調(diào)也就不同。單片機通過I/0端口的引腳產(chǎn)生高低電平變化,推動蜂鳴器振動發(fā)出聲音,只要改變I/O端口引腳變化的頻率,就可以控制蜂鳴器的振動頻率,產(chǎn)生不同的聲音。只需要改變DELAY子程序的延時時間,就可以改變引腳高低變化的頻率。

(2)編寫C語言代碼。用C語言編寫的指令代碼如下:

在C語言中,不可以直接寫P2.3,因為這樣的變量名不合法,我們用P2^3代替P2.3。如果要單獨對某位進行操作,可在程序的開頭加上位寄存器定義,例如:

sbitP2.3=P2^3;//定義位變量P2.3為P2口的第3位

sbitP1.0=P1^0;//定義位變量P1.0為P1口的第0位

sbitP2.1=P2^1;//定義位變量P2.1為P2口的第1位

sbita=P3^1; //定義位變量a為P3口的第1位

在隨后的程序中即可對這些位進行訪問。例如:

P2.3=1; //P2.3引腳為1 P1.0=1; //P1.0引腳為1 P2.1=0; //P2.1引腳為0 a=1; //P3.1引腳為1假如P0、P1、P2、P3口的某些位是連接到外部電路的指定引腳的,可將這些引腳名作為位名,例:假如打印機的BUSY引腳和P1.0相連,可以這樣進行定義:

sbitBUSY=P1^0;這樣增加了程序的可讀性。

4.電路板制作

(1)準備器件。按表4-5準備元器件。表4-5蜂鳴器控制電路元器件清單

(2)編譯或匯編源程序C4_3.C或A4_3.ASM,生成目標代碼文件,將目標代碼燒錄到芯片,參照圖4-30所示,用面包板搭接電路板如圖4-32所示。

接通電源,驗證功能,實現(xiàn)任務3的要求。圖4-32蜂鳴器控制電路板

問1:任務1的程序代碼寫的很長,有沒有其他簡單的方法呢?答:有。可采用循環(huán)程序的設計方法實現(xiàn)任務1的要求,方法如下:

(1)用匯編語言編寫的指令代碼。方法一:4.4互動環(huán)節(jié)

分析傳送數(shù)據(jù)排列的規(guī)律可以發(fā)現(xiàn),它們之間存在著后面?zhèn)魉偷臄?shù)據(jù)依次是前面?zhèn)魉蛿?shù)據(jù)左移一位的結(jié)果,因此我們可以用循環(huán)程序來實現(xiàn)這一傳送過程。方法二:

查表程序中的兩個關(guān)鍵點:一是定義表格,二是查表指令的運用。定義表格是指在“源程序”中用偽指令定義出一串常數(shù)的起始位置和排列順序,如平方表、字型碼、鍵碼表等。在匯編時匯編程序?qū)凑諅沃噶疃x的位置和排列順序自動將其存放在指定的存儲單元中。所以在上面的查表程序中,用偽指令DB定義顯示模式字的排列順序和起始位置。定義格式為:

[標號:]DB字節(jié)數(shù)據(jù)表

字節(jié)數(shù)據(jù)表可以由多個8位二進制字節(jié)數(shù)據(jù)組成,也可以是字符串或表達式。DB表示將字節(jié)數(shù)據(jù)表中的數(shù)據(jù)從左到右依次存放在由符號地址TABLE起始的地址單元中。指令表中提供了兩條專門用于查表操作的查表指令

MOVC A,@A+DPTR

MOVC A,@A+PC 其中,DPTR直接用來存放表首地址,累加器A中的內(nèi)容則用于修訂每次的查表地址;PC中存放該查表指令下一條指令的地址。采用哪條指令可以自行選擇,若采用后者要考慮對表首地址的修訂。(2)用C語言編寫的指令代碼。方法一:

比較程序C4_1.C和C4_5.C可以看出,順序結(jié)構(gòu)程序思路直觀,簡單易讀,是初學者最容易實現(xiàn)的程序設計方法。但程序代碼較長,如下類似的程序段重復出現(xiàn)了八次:

P1=0xfe; //點亮第1個發(fā)光二極管

delay(200); //延時每次重復時,只是送到P1口的值不同,因此可以考慮采用循環(huán)程序結(jié)構(gòu)來實現(xiàn)。方法二:※※※※※※※※※※※※※※※※※※※※※//程序名為:C4_6.C#include<reg51.h> //包含頭文件reg51.h#include<intrins.h> //包含頭文件intrins.hvoiddelay(unsignedchari); //延時函數(shù)聲明voidmain() //主函數(shù){unsignedchari,led; while(1){led=0xFE; //信號燈顯示字初值為FEH for(i=0;i<8;i++){ P1=led; //顯示字送P1口delay(200); //延時

led=_crol_(led,1);

//led循環(huán)左移1位,點亮下一個LED

} }}voiddelay(uns

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 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

提交評論