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

下載本文檔

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

文檔簡介

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

4.1項目基本技能

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

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

2.硬件電路設計

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

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

3.軟件設計

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

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

3)指令代碼

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

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

MOVP1,#11111011B可寫為

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

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

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

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

4.電路板制作

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

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

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

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

2.硬件電路設計

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

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

3.軟件設計

1)設計方法

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

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

3)指令代碼

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

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

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

{

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

P2=P1; //P1值賦給P2

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

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

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

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

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

1.P0口

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

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

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

(2)作為輸入使用。當P0口作為輸入數據使用時,分讀引腳和讀鎖存器兩種情況,為此在電路中有兩個用于讀入驅動的三態緩沖器。所謂讀引腳,就是讀芯片引腳的狀態,這時使用下方的數據緩沖器,由“讀引腳”信號把緩沖器打開,把端口引腳上的數據從緩沖器通過內部總線讀進來。讀引腳需先向電路中的鎖存器寫入“1”,使輸出級的FET截止,引腳處于懸浮狀態,變為高阻抗輸入,這就是所謂的準雙向口。讀鎖存器是指通過上面的緩沖器讀鎖存器Q端的狀態。

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

2.P1口

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

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

3.P2口

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

1)作為通用I/O口

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

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

4.P3口

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

1)作為通用I/O口

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

2)第二功能

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

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

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

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

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

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

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

2.程序的基本結構匯編語言中的基本結構有順序結構、分支結構、循環結構和子程序結構。單片機一個應用系統的匯編語言源程序,無論其系統功能的要求是簡單還是復雜,其程序結構的組成基礎總是由順序程序、分支程序、循環程序、子程序、查表程序等結構化程序塊組合而成。

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

2)分支結構程序分支結構是根據不同的條件轉移到不同分支的程序段的結構。具有分支結構的程序一般要使用轉移指令進行判斷和轉移,其程序執行流程如圖4-12所示。

圖4-12分支結構

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

圖4-13循環結構

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

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

(3)循環修改。每執行一次循環進行一次計數器值的修改,并對有關的數據及數據指針進行修改,為下一次循環做好準備。

(4)循環控制。根據循環次數計數器的現行值或其他條件來進行判斷,控制循環的繼續進行或結束。

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

4)主子程序

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

使用子程序應注意:

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

主程序調用子程序是通過安排在主程序的調用指令實現的,子程序返回主程序需執行RET返回指令。

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

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

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

ORG0000HMAIN: MOVA,R1 ;入口參數a送A ACALLSQR ;求a2 MOVR1,A ;a2送R1 MOVA,R2 ;入口參數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)子程序嵌套。子程序嵌套是指在子程序執行過程中,還可以調用另一個子程序。程序執行過程如圖4-16所示。圖4-16子程序嵌套

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

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

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

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

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

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

DELAY子程序包含兩重循環,這種結構稱為多重循環程序結構,又稱循環嵌套。多重循環程序必須注意的是各重循環不能交叉,不能從外循環跳入內循環。

知識點3C語言程序

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

1.?C語言的基本結構

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

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

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

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

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

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

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

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

語句組;

}

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

if語句中的“表達式”通常為邏輯表達式或關系表達式,也可以是任何其他的表達式或類型數據,只要表達式的值非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語句執行過程:當“表達式”的結果為“真”時,執行其后的“語句組1”,否則執行“語句組2”,執行過程如圖4-22所示。圖4-22if-else語句執行流程圖

3)?if-else-if語句

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

語句組1;

} elseif(表達式2) {

語句組2;

} …

elseif(表達式n) {

語句組n;

}else {

語句組n+1;

}

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

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

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

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

4)?switch語句

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

switch(表達式)

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

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

使用switch語句應注意:

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

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

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

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

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

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

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

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

1)?while語句

while語句用來實現“當型”循環結構,即當條件為“真”時,就執行循環體。while語句的一般形式為:

while(表達式)

{語句組;//循環體

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

使用while語句時要注意:

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

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

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

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

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

do {

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

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

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

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

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

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

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

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

{語句組;//循環體

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

for語句的執行過程如下:

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

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

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

(4)跳到上面第(2)步繼續執行。

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

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

{ 循環體語句組;

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

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

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

5)在循環體中使用break和continue語句

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

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

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

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

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

語句組1;修改循環變量;

if(表達式)break;

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

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

語句組2;

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

{

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

//執行continue語句,跳過下面求和語句,程序繼續執

//行for循環sum=sum+i;//循環;如果i不能被5整除,則執行求和語句。

}}任務3蜂鳴器的控制

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

2.硬件電路設計

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

4.3技能拓展

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

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

3.軟件設計

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

2)指令代碼

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

人耳可以聽到的振動頻率是20~20000Hz,頻率不同所產生的音調也就不同。單片機通過I/0端口的引腳產生高低電平變化,推動蜂鳴器振動發出聲音,只要改變I/O端口引腳變化的頻率,就可以控制蜂鳴器的振動頻率,產生不同的聲音。只需要改變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所示。

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

問1:任務1的程序代碼寫的很長,有沒有其他簡單的方法呢?答:有??刹捎醚h程序的設計方法實現任務1的要求,方法如下:

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

分析傳送數據排列的規律可以發現,它們之間存在著后面傳送的數據依次是前面傳送數據左移一位的結果,因此我們可以用循環程序來實現這一傳送過程。方法二:

查表程序中的兩個關鍵點:一是定義表格,二是查表指令的運用。定義表格是指在“源程序”中用偽指令定義出一串常數的起始位置和排列順序,如平方表、字型碼、鍵碼表等。在匯編時匯編程序將按照偽指令定義的位置和排列順序自動將其存放在指定的存儲單元中。所以在上面的查表程序中,用偽指令DB定義顯示模式字的排列順序和起始位置。定義格式為:

[標號:]DB字節數據表

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

MOVC A,@A+DPTR

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

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

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

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

led=_crol_(led,1);

//led循環左移1位,點亮下一個LED

} }}voiddelay(uns

溫馨提示

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

評論

0/150

提交評論