版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
項(xiàng)目二霓虹燈控制電路設(shè)計(jì)與制作
2.1C語言簡(jiǎn)介2.2STC89C51RC/RD+系列單片機(jī)的I/O口結(jié)構(gòu)2.3單片機(jī)I/O口應(yīng)用舉例2.4Keil軟件簡(jiǎn)介2.5霓虹燈控制電路的設(shè)計(jì)與制作制作指南2霓紅燈控制電路制作指南本章知識(shí)總結(jié)
學(xué)習(xí)目標(biāo)
掌握C語言基本構(gòu)成和基本語句的用法;
掌握C語言的數(shù)據(jù)類型、運(yùn)算符與表達(dá)式;
掌握C語言的for語句、if語句、函數(shù)的使用方法;
掌握單片機(jī)I/O口的功能和使用方法;
進(jìn)一步深入學(xué)習(xí)Keil和Proteus軟件的使用方法;
能利用單片機(jī)I/O口控制LED多種變化方式。
能力目標(biāo)
能夠利用在項(xiàng)目一制作完成的單片機(jī)最小系統(tǒng)的基礎(chǔ)上,利用C語言編寫程序來控制單片機(jī)I/O口的輸入和輸出操作,以實(shí)現(xiàn)對(duì)LED多種方式循環(huán)變化的設(shè)計(jì)與調(diào)試;能夠自行設(shè)計(jì)一個(gè)簡(jiǎn)易的霓虹燈控制電路。
2.1C?語?言?簡(jiǎn)?介
2.1.1概述
C語言是一種計(jì)算機(jī)程序設(shè)計(jì)語言,也是目前流行的計(jì)算機(jī)語言之一。它由美國(guó)貝爾實(shí)驗(yàn)室的丹尼斯·里奇(D.M.Ritchie)在ALGOL、BCPL和B語言的基礎(chǔ)上發(fā)展而來,并于1972年推出。1978年布賴恩·柯尼漢(BrianKerningham)和丹尼斯·里奇著作的《C語言程序設(shè)計(jì)》一書出版后,C語言很快成了最為流行的語言。C語言在發(fā)展的過程中,產(chǎn)生了多種版本,為了統(tǒng)一其標(biāo)準(zhǔn),1983年,美國(guó)國(guó)家標(biāo)準(zhǔn)局(AmericanNationalStandardsInstitate,ANSI)任命了一個(gè)技術(shù)委員會(huì)來定義C語言的標(biāo)準(zhǔn),該委員會(huì)于1989年批準(zhǔn)了一個(gè)C語言版本,1990年國(guó)際標(biāo)準(zhǔn)組織(InternationalStardardsOrganiyation,ISO)接受ANSIC為ISO的標(biāo)準(zhǔn)(ISO9899—1990)。目前流行的C語言編譯系統(tǒng)多是以ANSIC為基礎(chǔ)進(jìn)行開發(fā)的。另外需要注意的是,不同版本的C語言編譯系統(tǒng)是略有差別的。
C語言編寫程序效率高、移植性好,很適用于結(jié)構(gòu)化程序設(shè)計(jì),同時(shí),C語言的應(yīng)用范圍廣,具備很強(qiáng)的數(shù)據(jù)處理能力,因此在單片機(jī)和嵌入式系統(tǒng)開發(fā)中得到了廣泛的應(yīng)用。上面我們所介紹的是在PC中使用的標(biāo)準(zhǔn)C語言,它與我們?cè)趩纹瑱C(jī)編程中要用的C51是有差異的。例如:ANSIC支持16位字符而C51不支持16位字符,部分的ANSIC標(biāo)準(zhǔn)庫與C51庫不同。C51是由C語言產(chǎn)生的,它與C語言有著完全相同的語法規(guī)則,但是C51是一種特殊的C編譯器,針對(duì)不同的CPU,它們二者有著不同的編譯環(huán)境,也有各自的特點(diǎn)。2.1.2數(shù)據(jù)類型、運(yùn)算符與表達(dá)式
1.數(shù)據(jù)類型
數(shù)據(jù)類型是用來區(qū)分不同的數(shù)據(jù)的。由于數(shù)據(jù)在存儲(chǔ)時(shí)所需要的容量各不相同,不同的數(shù)據(jù)必須要分配不同大小的內(nèi)存空間來存儲(chǔ),所以就要將數(shù)據(jù)劃分成不同的數(shù)據(jù)類型。簡(jiǎn)單地說,就是根據(jù)需求來定義其數(shù)據(jù)類型,例如在開會(huì)的時(shí)候,可以根據(jù)人數(shù)的多少,選擇合適的會(huì)議室。
在C51中,所有要使用的變量在使用前必須為其定義數(shù)據(jù)類型。表2-1列出了常用數(shù)據(jù)類型和所分配的內(nèi)存字節(jié)長(zhǎng)度以及數(shù)值范圍。表2-1常用數(shù)據(jù)類型表
1)?char(字符類型)
Char的長(zhǎng)度是一個(gè)字節(jié),通常用于定義處理字符數(shù)據(jù)的變量或常量。char分無符號(hào)字符類型unsignedchar和有符號(hào)字符類型signedchar,默認(rèn)為signedchar類型。unsignedchar類型用字節(jié)中所有的位來表示數(shù)值,所能表達(dá)的數(shù)值范圍是0~255。signedchar類型用字節(jié)中最高位字節(jié)表示數(shù)據(jù)的符號(hào),“0”表示正數(shù),“1”表示負(fù)數(shù),負(fù)數(shù)用補(bǔ)碼表示。所能表示的數(shù)值范圍是-128~+127。unsignedchar常用于處理ASCII字符或小于等于255的整型數(shù)。
2)?int(整型)
int的長(zhǎng)度為兩個(gè)字節(jié),用于存放一個(gè)雙字節(jié)數(shù)據(jù)。int分有符號(hào)整型signedint和無符號(hào)整型unsignedint,默認(rèn)為signedint類型。signedint表示的數(shù)值范圍是-32768~+32767,字節(jié)中最高位表示數(shù)據(jù)的符號(hào),“0”表示正數(shù),“1”表示負(fù)數(shù)。unsignedint表示的數(shù)值范圍是0~65535。
3)?long(長(zhǎng)整型)
long的長(zhǎng)度為四個(gè)字節(jié),用于存放一個(gè)四字節(jié)數(shù)據(jù)。long分有符號(hào)長(zhǎng)整型signedlong和無符號(hào)長(zhǎng)整型unsignedlong,默認(rèn)為signedlong類型。signedlong表示的數(shù)值范圍是-2?147?483?648~+2?147?483?647,字節(jié)中最高位表示數(shù)據(jù)的符號(hào),“0”表示正數(shù),“1”表示負(fù)數(shù)。unsignedlon表示的數(shù)值范圍是0~4?294?967?295。
4)?float(浮點(diǎn)型)
float在十進(jìn)制中具有7位有效數(shù)字,是符合IEEE-754標(biāo)準(zhǔn)的單精度浮點(diǎn)型數(shù)據(jù),占用四個(gè)字節(jié)。因浮點(diǎn)數(shù)的結(jié)構(gòu)較復(fù)雜,故在以后的章節(jié)中再做詳細(xì)的討論。
5)?bit(位標(biāo)量)
bit是C51編譯器的一種擴(kuò)充數(shù)據(jù)類型,利用它可定義一個(gè)位標(biāo)量,但不能定義位指針,也不能定義位數(shù)組。它的值是一個(gè)二進(jìn)制位,不是0就是1,類似一些高級(jí)語言中Boolean類型的True和False。
6)?sfr(特殊功能寄存器)
sfr也是一種擴(kuò)充數(shù)據(jù)類型,占用一個(gè)內(nèi)存單元,值域?yàn)?~255。利用sfr能訪問51單片機(jī)內(nèi)部的所有特殊功能寄存器。如用sfrP1=0x90這一句定P1為P1端口在片內(nèi)的寄存器(一般用于頭文件中),在程序中可以用P1=255(對(duì)P1端口的所有引腳置高電平)之類的語句來操作特殊功能寄存器。
7)?sfr16(16位特殊功能寄存器)
sfr16占用兩個(gè)內(nèi)存單元,值域?yàn)?~65?535。sfr16和sfr一樣用于操作特殊功能寄存器,所不一樣的是sfr16用于操作占兩個(gè)字節(jié)的寄存器,如定時(shí)器T0和T1。
8)?sbit(可尋址位)
sbit同樣是單片機(jī)C語言中的一種擴(kuò)充數(shù)據(jù)類型,利用它能訪問芯片內(nèi)部RAM中的可尋址位或特殊功能寄存器中的可尋址位。
2.運(yùn)算符與表達(dá)式
完成某種運(yùn)算的符號(hào)稱之為運(yùn)算符。C語言的運(yùn)算符有算術(shù)運(yùn)算符、關(guān)系運(yùn)算符和邏輯運(yùn)算符等。表達(dá)式是由運(yùn)算符及運(yùn)算對(duì)象所組成的式子。
1)算術(shù)運(yùn)算符
算術(shù)運(yùn)算符有以下幾種:
+加或取正值運(yùn)算符
?-減或取負(fù)值運(yùn)算符
*乘運(yùn)算符
/除運(yùn)算符
%模(取余)運(yùn)算符其中“+”、“-”為單目運(yùn)算符,其余的都是雙目運(yùn)算符。單目指的是對(duì)一個(gè)操作數(shù)進(jìn)行操作,如-b是對(duì)b進(jìn)行取負(fù)操作。而雙目是指對(duì)兩個(gè)操作數(shù)進(jìn)行操作。例如:
13/3=4,“/”運(yùn)算符的結(jié)果取整數(shù),因此13/3的結(jié)果是整數(shù)4;
13%2=1,“%”運(yùn)算符的結(jié)果取余數(shù),因此13%2的結(jié)果是余數(shù)1,“%”運(yùn)算符不能用于浮點(diǎn)數(shù)。
算術(shù)表達(dá)式是用算術(shù)運(yùn)算符和括號(hào)將運(yùn)算對(duì)象連接起來并符合語法規(guī)則的式子。例如:
a*b-(d-e)/f
2)關(guān)系運(yùn)算符
關(guān)系運(yùn)算符一共有6種:
>大于
<小于
>=大于等于
<=小于等于
==測(cè)試等于
!=測(cè)試不等于
關(guān)系運(yùn)算符中,任何不為0的值解為真,否則為假。在使用關(guān)系運(yùn)算符表達(dá)式時(shí),如果表達(dá)式為真(即表達(dá)式成立),則值為1,否則,表達(dá)式為假,值為0。例如:
7>5值為1
關(guān)系表達(dá)式是用關(guān)系運(yùn)算符將兩個(gè)表達(dá)式連接起來的式子。例如:
(x=3)<=(y=5)
3)邏輯運(yùn)算符
邏輯運(yùn)算符有三種:
&&邏輯字,表達(dá)式例如:條件式1&&條件式2
||邏輯或,表達(dá)式例如:條件式1||條件式2
!邏輯非,表達(dá)式例如:!條件式
邏輯運(yùn)算符是用于求條件式的邏輯值。
邏輯與:當(dāng)條件式1與條件式2都為真時(shí),結(jié)果為真(非零值),否則為假(0值)。邏輯與中,只有條件式1為真時(shí),才去判斷條件式2,如果條件式1為假,邏輯運(yùn)算結(jié)果就為假。邏輯或:兩個(gè)條件式有一個(gè)為真時(shí),運(yùn)算的結(jié)果就為真。同樣,在運(yùn)算過程中,只有條件式1為假的時(shí)候,才去判斷條件式2,否則,運(yùn)算結(jié)果為真。
邏輯非:把運(yùn)算結(jié)果取反。
例如:a?=?1,b?=?2,c?=?3時(shí),!a為假,a&&c為真,b||c為真。
邏輯表達(dá)式的值是一個(gè)邏輯量的“真”或“假”。用數(shù)值1代表“真”,用數(shù)值0代表“假”,在進(jìn)行判斷“真”、“假”的時(shí)候,非0的為“真”,0為假。
例如:a?=?5,則!a的值為0。因?yàn)閍?=?5,是一個(gè)非0的值,所以為“真”,再對(duì)它進(jìn)行非運(yùn)算,所以結(jié)果變?yōu)椤凹佟?,值?。
4)位運(yùn)算符
C51的位運(yùn)算符與匯編語言的位操作相類似。位運(yùn)算指的是二進(jìn)制的運(yùn)算,位運(yùn)算一般表達(dá)形式如下:
變量1位運(yùn)算符變量2
C51中共有6種位運(yùn)算符:
& 按位與
| 按位或
^ 按位異或
~ 按位取反
<< 左移
>> 右移例如X?=?0x55?=?01010101B,Y?=?0x36?=?00110110B,則:
(1)?X&Y
即兩個(gè)運(yùn)算量按位與,只需將運(yùn)算量轉(zhuǎn)換成相應(yīng)的二進(jìn)制數(shù),然后逐位相與,即0*0=0,1*1=1。所以X&Y=0x14。
(2)?X|Y
即兩個(gè)運(yùn)算量按位或,只需將運(yùn)算量轉(zhuǎn)換成相應(yīng)的二進(jìn)制數(shù),然后逐位相或(加),即0?+?0?=?0,1?+?1?=?1。所以X|Y=?0x77。
(4)“~”是單目運(yùn)算符,是用來對(duì)某個(gè)數(shù)進(jìn)行按位取反操作,即0變1,1變0,因此~X?=?0xAA。
(5)“<<”左移運(yùn)算符,是對(duì)某個(gè)數(shù)全部左移若干位,如X<<2是表示將X中的二進(jìn)制數(shù)左移2位,左移之后留下的空位用0補(bǔ)齊。
X<<2=0101010100
01010101左移2位,則高兩位01將舍棄,剩下后面6位保留,并在低位補(bǔ)00。所以X<<2結(jié)果為01010100。
(6)“>>”右移運(yùn)算符,是對(duì)某個(gè)數(shù)全部右移若干位,如X>>2是表示將X中的二進(jìn)制數(shù)右移2位,右移之后留下的空位用0補(bǔ)齊。
X>>2=0001010101
01010101右移2位,則低兩位01將舍棄,剩下6位保留,并在高位補(bǔ)00。所以X>>2結(jié)果為00010101。
2.2STC89C51RC/RD+系列單片機(jī)的I/O口結(jié)構(gòu)
STC89C51RC/RD+系列單片機(jī)所有I/O口均(新增P4口)有3種工作類型:準(zhǔn)雙向口/弱上拉(標(biāo)準(zhǔn)8051輸出模式)、僅為輸入(高阻)或開漏輸出功能。STC89C51RC/RD+系列單片機(jī)的P1/P2/P3/P4上電復(fù)位后為準(zhǔn)雙向口/弱上拉(傳統(tǒng)8051的I/O口)模式,P0口上電復(fù)位后是開漏輸出模式。P0口作為總線擴(kuò)展用時(shí),不用加上拉電阻,作為I/O口用時(shí),需加4.1kΩ~10kΩ上拉電阻。
STC89C51RC/RD+的5?V單片機(jī)的P0口的灌電流最大為12?mA,其他I/O口的灌電流最大為6?mA。2.2.1準(zhǔn)雙向口輸出配置
準(zhǔn)雙向口輸出類型可用作輸出和輸入功能而不需重新配置口線輸出狀態(tài)。這是因?yàn)楫?dāng)口線輸出為1時(shí)驅(qū)動(dòng)能力很弱,允許外部裝置將其拉低。當(dāng)引腳輸出為低時(shí),它的驅(qū)動(dòng)能力很強(qiáng),可吸收相當(dāng)大的電流。準(zhǔn)雙向口有3個(gè)上拉晶體管以適應(yīng)不同的需要。準(zhǔn)雙向口輸出如圖2.1所示。
在3個(gè)上拉晶體管中,有1個(gè)上拉晶體管稱為弱上拉,當(dāng)口線鎖存器為1且引腳本身也為1時(shí)打開。此上拉提供基本驅(qū)動(dòng)電流使準(zhǔn)雙向口輸出為1。如果一個(gè)引腳輸出為1而由外部裝置下拉到低時(shí),弱上拉關(guān)閉而極弱上拉維持開狀態(tài),為了把這個(gè)引腳強(qiáng)拉為低,外部裝置必須有足夠的灌電流能力使引腳上的電壓降到門檻電壓以下。圖2.1準(zhǔn)雙向口輸出第2個(gè)上拉晶體管,稱為極弱上拉,當(dāng)口線鎖存器為1時(shí)打開。當(dāng)引腳懸空時(shí),這個(gè)極弱的上拉源產(chǎn)生很弱的上拉電流將引腳上拉為高電平。
第3個(gè)上拉晶體管稱為強(qiáng)上拉。當(dāng)口線鎖存器由0到1跳變時(shí),這個(gè)上拉用來加快準(zhǔn)雙向口由邏輯0到邏輯1轉(zhuǎn)換。當(dāng)發(fā)生這種情況時(shí),強(qiáng)上拉打開約2個(gè)時(shí)鐘以使引腳能夠迅速地上拉到高電平。2.2.2開漏輸出配置
P0口上電復(fù)位后處于開漏模式,當(dāng)P0管腳作I/O口時(shí),需外加4.7~10?kΩ的上拉電阻,當(dāng)P0管腳作為地址/數(shù)據(jù)復(fù)用總線使用時(shí),不用外加上拉電阻。
當(dāng)口線鎖存器為0時(shí),開漏輸出關(guān)閉所有上拉晶體管。當(dāng)作為一個(gè)邏輯輸出時(shí),這種配置方式必須有外部上拉,一般通過電阻外接到VCC。如果外部有上拉電阻,開漏的I/O口還可讀外部狀態(tài),即此時(shí)被配置為開漏模式的I/O口還可作為輸入I/O口。這種方式的下拉與準(zhǔn)雙向口相同。開漏輸出配置如圖2.2所示。開漏端口帶有一個(gè)干擾抑制電路。圖2.2開漏輸出
2.3單片機(jī)I/O口應(yīng)用舉例
對(duì)單片機(jī)的操作,實(shí)際上就是對(duì)I/O口的操作,都是通過對(duì)單片機(jī)I/O口置1或置0的操作,來達(dá)到控制其他外圍電路的目的,因此才能使電子系統(tǒng)按照我們的意圖來執(zhí)行“命令”。
在這里初學(xué)者一定要注意,單片機(jī)只是芯片,若沒有外圍電路,其本身無法獨(dú)立工作。因此,在學(xué)習(xí)單片機(jī)的時(shí)候,也要注意其外圍電路的學(xué)習(xí),相信有很多學(xué)習(xí)單片機(jī)的人,都會(huì)說不知道怎么編程,沒有思路,其實(shí)主要原因是在編程前沒有很好地理解硬件電路的原理,而把心思都放在了如何編程上面了。所以,進(jìn)行編程之前,先別急著直接去編程,先了解硬件電路的原理,然后再考慮編程問題,換句話說,理解硬件電路的原理,是單片機(jī)編程的前提條件。
【例2.1】
試用單片機(jī)點(diǎn)亮一個(gè)發(fā)光二極管(LED)。
解析:
(1)硬件電路。在項(xiàng)目一中,我們已經(jīng)學(xué)習(xí)了單片機(jī)最小系統(tǒng),因此無論用單片機(jī)控制什么,都不可能缺少單片機(jī)最小系統(tǒng)電路,然后才是被控制對(duì)象。根據(jù)題目要求,我們只需單片機(jī)最小系統(tǒng)電路,外加一個(gè)發(fā)光二極管和一個(gè)限流電阻,就可以設(shè)計(jì)出滿足題目要求的硬件電路。硬件電路如圖2.3所示。圖2.3點(diǎn)亮發(fā)光二極管電路
(2)原理分析。在圖2.3中,單片機(jī)左面的C1、C2、X1、R1、C3構(gòu)成了單片機(jī)的時(shí)鐘電路和復(fù)位電路。我們?cè)陧?xiàng)目一已經(jīng)做了詳細(xì)的介紹,與單片機(jī)P0口相連的是上拉電阻,因?yàn)镻0口與P1~P3口有所區(qū)別,P0口是漏極開路輸出,所以在I/O口使用時(shí),必須要接上拉電阻。VD1、R2是本例的控制元件,VD1的陰極連接到了單片機(jī)的P2.7引腳,VD1的陽極通過R2連接電源,R2是限流電阻,可以通過調(diào)整R2的大小來控制VD1的亮暗。我們通過電子技術(shù)基礎(chǔ)課程的學(xué)習(xí),很容易就可以得到結(jié)論,要想使VD1亮,與VD1陰極相連的P2.7就必須輸出低電平,如果輸出的是高電平,那么VD1就不會(huì)亮。所以在編寫程序時(shí),只需讓P2.7輸出低電平即可。
(3)程序代碼。
#include<reg52.h> //加載reg52.h頭文件
sbitLDE=P2^7; //定義位變量LED
voidmain(void) //主函數(shù),程序是在這里運(yùn)行的
{
while(1)
//進(jìn)入死循環(huán)
{
LED=0;
//LDE亮
}
}
(4)程序說明。
①“#include<reg52.h>”語句是一個(gè)“文件包含”處理,意思是將reg52.h的頭文件的內(nèi)容全部包含進(jìn)來,換句話說,如果想要使用reg52.h頭文件里面的資源,必須在程序開始處,將頭文件包含。
②“sbitLDE=P2^7;”的含義為位定義,P2^7表示單片機(jī)的P2.7引腳,從此處程序開始,后面的程序中凡是要用到P2.7引腳的都用LED來替代,符號(hào)LED還可以取其他名字,如X_Y等。
③“while(1){}”中的while為循環(huán)語句,其后面小括號(hào)內(nèi)為表達(dá)式,{}是其循環(huán)體語句(LED=0;是while語句的循環(huán)體語句),只要小括號(hào)內(nèi)的表達(dá)式為非0(即條件成立),則一直執(zhí)行循環(huán)體內(nèi)部的語句。注意循環(huán)體語句不一定只有一句,可以有很多句,但當(dāng)循環(huán)體語句只有一句時(shí),“{}”可以不寫。
④“LED=0;”使P2.7引腳輸出低電平,使二極管發(fā)光。
⑤在編程過程中,大括號(hào){}都是成對(duì)出現(xiàn)的,為了防止發(fā)生遺忘,在編程時(shí)最好成對(duì)的大括號(hào)同時(shí)敲出,以免發(fā)生遺忘,在編譯時(shí)發(fā)生錯(cuò)誤。說明:在本程序中,只需將單片機(jī)P2.7引腳輸出低電平即可實(shí)現(xiàn),除了程序中使用的語句外,還可以用另外一種方式。P2?=?0xFF,表示將P2口全部I/O口全部置1,十六進(jìn)制數(shù)0xFF轉(zhuǎn)換成二進(jìn)制數(shù)為11111111,在P2=0xFF中,這八位二進(jìn)制數(shù)分別對(duì)應(yīng)著P2口的八個(gè)I/O口,如表2-2所示。表2-2P2?=?0xFF各位對(duì)應(yīng)狀態(tài)
從表中可知,在例2.1中,想讓P2.7為0,對(duì)應(yīng)的二進(jìn)制數(shù)就為01111111,與其對(duì)應(yīng)的十六進(jìn)制數(shù)就為0X7F。因此例1的程序也可以修改為
#include<reg52.h> //加載reg52.h頭文件
voidmain(void) //主函數(shù),程序是在這里運(yùn)行的
{
while(1)
//進(jìn)入死循環(huán)
{
P2=0x7F; //LDE亮
}
}
【例2.2】控制1個(gè)LED閃爍,LED亮500ms、熄500ms循環(huán)。
解析:
(1)硬件電路。由于題目要求仍然是控制1個(gè)LED閃爍,只是在顯示方式上變?yōu)?亮1熄,因此電路原理圖可以和例2.1使用相同的電路。
(2)原理分析。要想使D1亮、滅各500?ms,只需要使單片機(jī)P2.7口循環(huán)輸出500?ms低電平、500?ms高電平即可實(shí)現(xiàn)。
(3)程序流程。程序流程見圖2.4所示。圖2.4流程圖
(4)程序代碼。程序中讓LED亮、滅,我們根據(jù)例2.1就可以知道,只需將單片機(jī)P2.7置0然后再讓P2.7置1即可。難點(diǎn)在于如何讓LED燈亮的時(shí)間保持500?ms,以及在燈滅的時(shí)候保持500?ms,當(dāng)然這兩個(gè)500?ms可以使用同樣的程序。
#include<reg52.h> //加載reg52.h頭文件
sbitLDE=P2^7; //定義位變量LED
voidmain(void) //主函數(shù),程序是在這里運(yùn)行的
{
while(1)
//進(jìn)入死循環(huán)
{
LED=0; //LDE亮
500ms延時(shí); //延時(shí)
LED=1; //LDE滅
500ms延時(shí);//延時(shí)
}
}下面介紹延時(shí)(軟件延時(shí))程序是如何編寫的。
軟件延時(shí)的基本原理就是讓單片機(jī)執(zhí)行一些空指令來達(dá)到延時(shí)目的,因?yàn)閱纹瑱C(jī)在執(zhí)行每一條程序時(shí)都需要時(shí)間,我們只需要知道單片機(jī)每執(zhí)行一條指令所需要的時(shí)間,就可以較容易地實(shí)現(xiàn)延時(shí)。軟件延時(shí)一般應(yīng)用在對(duì)延時(shí)要求不高的場(chǎng)合中,對(duì)于要求延時(shí)準(zhǔn)確的應(yīng)用場(chǎng)合,可使用定時(shí)器。
在寫延時(shí)程序時(shí),通常使用循環(huán)語句來編寫延時(shí)程序,例如for語句、while語句,但大多以for語句為主。
(1)?for語句的使用方法。
①?for語句形式如下:
for(表達(dá)式1;表達(dá)式2;表達(dá)式3)
{循環(huán)體語句}
②?for語句執(zhí)行過程如下:
(a)先執(zhí)行表達(dá)式1,對(duì)表達(dá)式1賦初值。
(b)判斷表達(dá)式2是否滿足給定條件,若不滿足循環(huán)條件,則跳過循環(huán)體語句,執(zhí)行for語句下面的語句;若滿足循環(huán)條件,則執(zhí)行循環(huán)體內(nèi)語句,然后執(zhí)行表達(dá)式3。再判別表達(dá)式2是否滿足循環(huán)條件,若滿足則繼續(xù)執(zhí)行循環(huán)體語句,如此循環(huán),直到表達(dá)式2不滿足條件,就終止for循環(huán),執(zhí)行循環(huán)體外語句。③應(yīng)用舉例。
for(i=1;
i<=10;
i++)
sum=sum+i;
先給i賦初值1,判斷i是否小于等于10,若是則執(zhí)行語句(由于循環(huán)體語句只有一句,因此“{}”可以省略),之后值增加1。再重新判斷,直到條件為假,即i>10時(shí),結(jié)束循環(huán)。
(2)延時(shí)程序的寫法及時(shí)間的計(jì)算。根據(jù)之前所述,可以利用for語句多次循環(huán),來實(shí)現(xiàn)延時(shí)的目的。
for(i=0;i<125;i++)
for(j=0;j<125;j++)程序說明:語句中使用了for語句的嵌套(for語句中又包含了for語句),第一個(gè)for語句一共執(zhí)行125次,而第二個(gè)for語句與第一個(gè)for語句的執(zhí)行次數(shù)不一樣,如果沒有第一個(gè)for語句,第二個(gè)for語句同樣執(zhí)行125次,但是在上面程序?qū)懛ㄖ?,?dāng)?shù)谝粋€(gè)for語句執(zhí)行1次時(shí),第二個(gè)for語句就要執(zhí)行125次,也就是說第一個(gè)for語句每執(zhí)行1次,第二個(gè)for語句就要執(zhí)行125次,因此程序一共將執(zhí)行125?×?125?=?15?625次。如果我們知道了語句執(zhí)行1次所需的時(shí)間,那么就會(huì)知道這段程序運(yùn)行所需的時(shí)間,也就可以通過調(diào)整執(zhí)行次數(shù),來得到我們需要延時(shí)時(shí)間。在實(shí)際調(diào)試中,我們可以借助Keil軟件來觀察程序的執(zhí)行時(shí)間,具體方法如下:
(a)打開Keil軟件,新建一個(gè)工程并添加一個(gè)C文件(步驟在項(xiàng)目一中有介紹)。
(b)在編程區(qū)輸入例2.2的程序代碼,500?ms延時(shí)的程序,我們就暫時(shí)用以下語句來替代。
for(i=0;i<125;i++)
for(j=0;j<125;j++)
需要注意的是,在程序中由于for語句中使用了變量i和j,因此在程序中要對(duì)兩個(gè)變量進(jìn)行定義。程序代碼如下:
#include<reg52.h>
sbitLED=P2^7;
voidmain(void)
{
unsignedinti,j;
while(1)
{
LED=0;
for(i=0;i<125;i++)
?for(j=0;j<125;j++);
LED=1;
for(i=0;i<125;i++)
?for(j=0;j<125;j++);
}
}注意:此時(shí)的程序代碼中的for語句的執(zhí)行時(shí)間是未知的。
(c)點(diǎn)擊按鈕,再單擊,對(duì)程序進(jìn)行編譯。
(d)單擊按鈕,會(huì)彈出對(duì)話框,將紅色框的晶振參數(shù)24.0修改為我們所使用的11.0592,如圖2.5所示。然后單擊“Output”選項(xiàng)卡,選中“CreateHEXFile”項(xiàng),如圖2.6所示,選擇后單擊“OK”按鈕,返回程序界面。圖2.5晶振參數(shù)修改窗口圖2.6輸出文件設(shè)置窗口
(e)單擊按鈕,將會(huì)進(jìn)入到調(diào)試界面,如圖2.7所示。
注意圖中左邊所框部分的變化,進(jìn)入調(diào)試界面后,有一項(xiàng)“sec”,表示程序執(zhí)行時(shí)間。箭頭表示程序執(zhí)行到哪里。那么現(xiàn)在“sec”中的0.00042209,表示的是程序執(zhí)行到“LED=0”時(shí),所用的時(shí)間。圖2.7程序調(diào)試界面
(f)觀察兩個(gè)for語句的執(zhí)行時(shí)間,即程序執(zhí)行到“LED=1;”時(shí),“sec”顯示的時(shí)間再減去初始時(shí)間,就是for語句延時(shí)的時(shí)間。進(jìn)入調(diào)試界面后,我們按“F10”(F10為單步執(zhí)行)鍵就可以讓程序執(zhí)行下一步,但是兩個(gè)for語句執(zhí)行次數(shù)較多,單步執(zhí)行很慢,所以可以在語句“LED=1;”加入斷點(diǎn)(將鼠標(biāo)移至“LED=1;”前,并雙擊左鍵,會(huì)發(fā)現(xiàn)語句前出現(xiàn)紅色的標(biāo)識(shí),如圖2.8和圖2.9所示),然后單擊左上方
按鈕,如圖2.10所示,會(huì)發(fā)現(xiàn)箭頭就停在了所設(shè)置的斷點(diǎn)處,如圖2.11所示,這時(shí)再觀察“sec”項(xiàng),上面的時(shí)間就已經(jīng)發(fā)生了變化,如圖2.12所示。圖2.8設(shè)置斷點(diǎn)前狀態(tài)圖2.9設(shè)置斷點(diǎn)后狀態(tài)圖2.10單擊全速運(yùn)行圖2.11執(zhí)行到斷點(diǎn)處圖2.12觀察時(shí)間通過剛才的操作,我們會(huì)發(fā)現(xiàn)時(shí)間已經(jīng)發(fā)生了變化,當(dāng)程序執(zhí)行到“LED=1;”時(shí),所用的時(shí)間為0.137?552?08,我們?cè)贉p去初始時(shí)間0.000?422?09,就是for語句所延時(shí)的時(shí)間,即0.137?552?08?-?0.000?422?09?=?0.137?129?99?s,初始時(shí)間較短,可以忽略。由此可知,當(dāng)2個(gè)for語句都為125時(shí),只能延時(shí)0.137?129?99?s,所以我們還需要調(diào)整i和j的取值,通常情況下,我們使變量i不變,然后調(diào)整j的取值,依然是按照之前所示的步驟,直到調(diào)整到我們所需的時(shí)間。通過調(diào)整,我們可讓i取125,j取671,這時(shí)的“sec”為0.500?643?45,再減去初始時(shí)間即0.500?643?45?-?0.000?422?09?=?0.500?221?36?s,接近500?ms。在這里需要說明的是,i和j的值不是唯一的,取其他的數(shù)值依然可以得到500?ms延時(shí)。所以程序代碼就可以修改為
#include<reg52.h>
sbitLED=P2^7;
voidmain(void)
{
unsignedinti,j;
while(1)
{
LED=0;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
LED=1;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
}
}
(g)將生成的HEX文件,加載到例2.1所用的仿真文件中,我們就可以看到,二極管一閃一閃的發(fā)光了。
【例2.3】試用單片機(jī)P2口,設(shè)計(jì)一個(gè)控制8位LED依次點(diǎn)亮(第1個(gè)LED亮,第2個(gè)LED亮的同時(shí)第1個(gè)LED滅,即每次只有一個(gè)LED亮)且時(shí)間間隔為500?ms的電路,并編寫程序。
方案一:
(1)硬件電路。由P2口控制8位LED循環(huán)點(diǎn)亮,電路上只需在例2.1電路圖的基礎(chǔ)上,再加上7位LED即可,如圖2.14所示。圖2.14方案一電路原理圖
(2)原理分析。題目要求是使8位LED循環(huán)點(diǎn)亮,我們只需要使每次只有一個(gè)LED亮即可,時(shí)間間隔為500?ms。由于LED的陰極接到單片機(jī)P2口,所以只有在P2口輸出低電平0時(shí),LED才能發(fā)光。
(3)程序流程如下:
第一步:VD1亮,延時(shí)500?ms,即P2?=?0xfe;
第二步:VD2亮,延時(shí)500?ms,即P2?=?0xfd;
第三步:VD3亮,延時(shí)500?ms,即P2?=?0xfb;
第四步:VD4亮,延時(shí)500?ms,即P2?=?0xf7;
第五步:VD5亮,延時(shí)500?ms,即P2?=?0xef;
第六步:VD6亮,延時(shí)500?ms,即P2?=?0xdf;
第七步:VD7亮,延時(shí)500?ms,即P2?=?0xbf;
第八步:VD8亮,延時(shí)500?ms,即P2?=?0x7f;
返回第一步,重復(fù)執(zhí)行。
(4)程序代碼如下:
#include<reg52.h>
/*500ms延時(shí)*/
voiddelay()
{
unsignedinti,j;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
}
voidmain(void)
{
while(1) //死循環(huán) {
P2=0xfe; //VD1亮
delay();
P2=0xfd;
//VD2亮
delay();
P2=0xfb; //VD3亮
delay();
P2=0xf7; //VD4亮
delay();
P2=0xef; //VD5亮
delay();
P2=0xdf; //VD6亮 delay();
P2=0xbf; //VD7亮
delay();
P2=0x7f; //VD8亮
delay();
}
}
該程序較長(zhǎng),能不能對(duì)程序進(jìn)行優(yōu)化,使程序看著更加簡(jiǎn)潔?答案是肯定的。首先,通過觀察可以發(fā)現(xiàn),程序是執(zhí)行8次之后(VD1~VD8逐個(gè)點(diǎn)亮),再次循環(huán),因此可以利用一個(gè)循環(huán)語句來控制其次數(shù)。其次,通過對(duì)P2口數(shù)據(jù)的觀察,會(huì)發(fā)現(xiàn)規(guī)律如表2-3所示。表2-3例2.3方案一規(guī)律表由表可見,哪個(gè)LED發(fā)光,與之對(duì)應(yīng)的I/O口就為低電平,由于是依次點(diǎn)亮,相當(dāng)于“0”,因此從P2.0左移至P2.7,就可以實(shí)現(xiàn)題目要求。前面學(xué)習(xí)過左移、右移運(yùn)算符,可以用在本例,但值得考慮的一個(gè)問題是,當(dāng)P2?=?0xfe時(shí),如果有語句“P2?=?P2<<1;”,那么P2會(huì)為什么?顯然P2?=?0xfc,即P2.0和P2.1都為低電平,這樣會(huì)使2個(gè)LED都發(fā)光,所以直接用左移,是沒有辦法達(dá)到要求的。但是,如果令“P2?=?0x01;P2?=?P2<<1;”,那么P2?=?0x02,我們會(huì)發(fā)現(xiàn),“1”是可以逐個(gè)左移的,它與想要0左移,正好是相反的,因此就可以借助一個(gè)中間變量,將“1”左移的結(jié)果取反,再送到P2就可以了,即設(shè)中間變量為temp:
temp=0x01;
P2=~temp; //temp=0x01取反為“P2=temp=0xfe;”D1燈亮
temp=temp<<1;//請(qǐng)注意,雖然在上條語句中有~temp,但是temp的值并沒有發(fā)生改變,temp左移1位之后“temp=0x02;”
P2=~temp; //0x02取反,即0xfd,D2燈亮
以此類推,所以程序可以優(yōu)化為
#include<reg52.h>
voiddelay()
{
unsignedinti,j;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
}
voidmain(void)
{
unsignedcharw,temp;
while(1)
{
temp=0x01;
for(w=0;w<8;w++)
//控制循環(huán)次數(shù)
{
P2=~temp;
delay();
temp=temp<<1;
}
}
}在這里肯定會(huì)有同學(xué)問,為什么非要用LED的陰極接在單片機(jī)的I/O引腳上,而不是將LED的陽極接到單片機(jī)的I/O引腳上,這樣編程時(shí),就不用像上面一樣,借助中間變量實(shí)現(xiàn)LED依次點(diǎn)亮了,程序就更簡(jiǎn)單了?其原因就在于單片機(jī)I/O口驅(qū)動(dòng)能力有限,沒有辦法驅(qū)動(dòng)電流較大的器件,因此,如果想要用單片機(jī)I/O口直接去驅(qū)動(dòng)器件,就必須借助其他器件增大其驅(qū)動(dòng)能力,才能達(dá)到要求。下面介紹單片機(jī)直接驅(qū)動(dòng)LED的方法。方案二:
(1)硬件電路。利用單片機(jī)I/O口直接驅(qū)動(dòng)LED或者其他器件,需要借助驅(qū)動(dòng)能力較大的器件,如74LS245、74HC573等。
74LS245是8路同相三態(tài)雙向數(shù)據(jù)總線驅(qū)動(dòng)芯片,可雙向傳輸數(shù)據(jù),它還具有雙向三態(tài)功能,既可以輸出,也可以輸入數(shù)據(jù)。當(dāng)片選端/CE低電平有效時(shí),DIR=“0”,信號(hào)由B向A傳輸(接收);DIR=“1”,信號(hào)由A向B傳輸(發(fā)送)。當(dāng)CE為高電平時(shí),A、B均為高阻態(tài)。
74LS245的內(nèi)部結(jié)構(gòu)如圖2.15所示。圖2.1574LS245內(nèi)部結(jié)構(gòu)
74LS245的功能如表2-4所示。
74HC573是8路三態(tài)同相鎖存器,當(dāng)鎖存使能端LE為高時(shí),輸出數(shù)據(jù)與輸入數(shù)據(jù)相等。當(dāng)鎖存使能變低時(shí),無論輸入數(shù)據(jù)如何變化,將不會(huì)影響輸出數(shù)據(jù),輸出數(shù)據(jù)將保持原來狀態(tài)不變。74HC573的邏輯框圖如圖2.16所示,功能如表2-5所示。表2-474LS245功能表
圖2.1674HC573邏輯框圖表2-574HC573功能表
從74HC573功能表可以看出,74HC573可以輸出高電平、低電平、保持和高阻四種狀態(tài),但是需要對(duì)“輸出使能”和“鎖存使能”進(jìn)行控制。
①?74HC573要想輸出高電平,需滿足輸出使能=L,鎖存使能=H,D(輸入數(shù)據(jù))=H的條件。
②?74HC573要想輸出低電平,需滿足輸出使能=L,鎖存使能=H,D(輸入數(shù)據(jù))=L的條件。
③?74HC573要想保持輸出狀態(tài)不變,需滿足輸出使能=L,鎖存使能=L,D(輸入數(shù)據(jù))=X(任意)的條件。
④?74HC573要想輸出高阻,需滿足輸出使能=H,鎖存使能=X,D(輸入數(shù)據(jù))=X(任意)的條件。通過以上分析可知:
當(dāng)滿足輸出使能=L,鎖存使能=H條件時(shí),輸出與輸入相同,即直通狀態(tài);
當(dāng)滿足輸出使能=L,鎖存使能=L條件時(shí),無論輸入信號(hào)是高電平還是低電平,輸出都保持不變;
當(dāng)滿足輸出使能=H條件時(shí),輸出就為高阻狀態(tài)。
由于只需單片機(jī)輸出數(shù)據(jù),因此只需使用74HC573即可,如果需要將數(shù)據(jù)讀回,則可以使用74LS245。因此,方案二的電路原理如圖2.17所示。
由于只需使單片機(jī)I/O口輸出高低電平就可以達(dá)到題目要求,所以74HC573只需接到直通狀態(tài)即可,即LE為高,
為低。圖2.17方案二電路原理圖
(2)原理分析。題目要求是使8位LED循環(huán)點(diǎn)亮,即只需要使每次只有一個(gè)LED亮即可,時(shí)間間隔為500ms。由于LED的陽極通過74HC573極接到單片機(jī)P2口,所以只要在P2口輸出高電平1時(shí),LED就能發(fā)光。
(3)程序流程如下:
第一步:VD1亮,延時(shí)500?ms,即P2?=?0x01;
第二步:VD2亮,延時(shí)500?ms,即P2?=?0x02;
第三步:VD3亮,延時(shí)500?ms,即P2?=?0x04;
第四步:VD4亮,延時(shí)500?ms,即P2?=?0x08;
第五步:VD5亮,延時(shí)500?ms,即P2?=?0x10;
第六步:VD6亮,延時(shí)500?ms,即P2?=?0x20;
第七步:VD7亮,延時(shí)500?ms,即P2?=?0x40;
第八步:VD8亮,延時(shí)500?ms,即P2?=?0x80;
然后返回第一步,重復(fù)執(zhí)行。
(4)程序代碼如下:
#include<reg52.h>
voiddelay()
{
unsignedinti,j;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
}
voidmain(void)
{
unsignedcharw,temp;
while(1)
{
temp=0x01;
for(w=0;w<8;w++) //控制循環(huán)次數(shù)
{
P2=temp;
delay();
temp=temp<<1;
}
}
}
【例2.4】在例2.3方案二電路的基礎(chǔ)上,試編寫2位LED循環(huán)往復(fù)點(diǎn)亮,即2個(gè)LED循環(huán)點(diǎn)亮(狀態(tài)如表2-6所示)的程序,時(shí)間間隔500?ms。
解析:
(1)原理分析。
結(jié)合例2.3方案二電路,通過狀態(tài)表可知,每次有2個(gè)LED發(fā)光,并依次左移,待P2.7和P2.6所控制的LED亮?xí)r,則依次右移,直到恢復(fù)到初始狀態(tài)(P2.0和P2.1為“1”)完成一次執(zhí)行。因此在程序中需要對(duì)左移或右移的次數(shù)進(jìn)行控制。表2-62位LED循環(huán)狀態(tài)表
(2)程序代碼如下:
#include<reg52.h>
voiddelay()
{
unsignedinti,j;
for(i=0;i<125;i++)
for(j=0;j<671;j++);
}
voidmain(void)
{
unsignedcharw;
while(1)
{
P2=0x03;
delay();
/*控制左移次數(shù)*/
for(w=0;w<6;w++)
{
P2=P2<<1;
delay();
}
/*控制右移次數(shù),比上一個(gè)for少一次,是因?yàn)槿绻乙?次后,P2的值為0x03,再執(zhí)行while死循環(huán)中的P2=0x03,將會(huì)執(zhí)行兩次,在實(shí)驗(yàn)現(xiàn)象中有一個(gè)明顯的停頓*/
for(w=0;w<5;w++)
{
P2=P2>>1;
delay();
}
}
}
【例2.5】通過開關(guān),控制8位LED循環(huán)速度。開關(guān)每變換一次,LED速度與之發(fā)生改變,當(dāng)開關(guān)置于P1.0時(shí),速度為800?ms;當(dāng)開關(guān)置于P1.1時(shí),速度為500?ms;當(dāng)開關(guān)置于P1.2時(shí),速度為300?ms;當(dāng)開關(guān)置于P1.3時(shí),速度為100?ms。實(shí)驗(yàn)現(xiàn)象同例2.4。
解析:
(1)硬件電路。由于用開關(guān)控制LED的速度,所以需要在P1.0~P1.3處加入開關(guān),其他電路圖可以借鑒圖2.17。因此,硬件電路如圖2.18所示。圖2.18開關(guān)控制LED循環(huán)速度原理圖
(2)原理分析。從題目要求可知,其實(shí)驗(yàn)現(xiàn)象與例2.4一致,只是在開關(guān)處于不同位置時(shí),執(zhí)行的速度不同而已,其程序代碼可以部分使用例2.4程序,再配上不同延時(shí)函數(shù)即可。按照之前我們所學(xué)習(xí)的延時(shí)函數(shù)的編寫,在本程序中,就需要4個(gè)延時(shí)函數(shù),比較繁瑣,那么我們能不能只寫一個(gè)延時(shí)函數(shù),而使它的延時(shí)時(shí)間根據(jù)需要而改變呢?那么如何判斷開關(guān)是處于哪個(gè)位置呢?答案就是我們只需要編寫一個(gè)帶參數(shù)的延時(shí)函數(shù)和一個(gè)判斷開關(guān)位置的語句即可實(shí)現(xiàn)知識(shí)引入。
【知識(shí)引入】
①有參函數(shù)定義形式:
[函數(shù)類型]函數(shù)名(形參列表)
{
[聲明部分]
[語句]
}
有參函數(shù)執(zhí)行過程如圖2.19所示。圖2.19有參函數(shù)執(zhí)行過程說明如下:
(a)形參(形式參數(shù)):定義函數(shù)時(shí)函數(shù)名后面括號(hào)中的變量,如exp(intx,inty)中的x和y就是形參。
(b)實(shí)參(實(shí)際參數(shù)):調(diào)用函數(shù)時(shí)函數(shù)名后面括號(hào)內(nèi)的數(shù)值或表達(dá)式,如c=exp(3,4)中的3和4就是實(shí)參。
(c)實(shí)參與形參的數(shù)據(jù)類型要保持一致。
(d)函數(shù)exp中return(z),是返回語句,其形式為
return(表達(dá)式);
或return表達(dá)式;
或return;有參函數(shù)的功能是程序控制從被調(diào)用函數(shù)返回到調(diào)用函數(shù)中,同時(shí)把返回值帶給調(diào)用函數(shù)。
②?if語句:用來進(jìn)行判斷的,它能夠判斷是否滿足某個(gè)條件,然后執(zhí)行相應(yīng)的動(dòng)作。
if語句的三種形式如下:
(a)?if(表達(dá)式)語句
如:
if(x>y)printf(“%d”,x);//只要x>y成立,就執(zhí)行printf語句,否則就不執(zhí)行
(b)?if(表達(dá)式)語句1else語句2
如:
if(x>y)x-y;
elsex+y;
//如果x>y成立,就執(zhí)行x-y;否則就執(zhí)行x+y(包括x<y和x=y)
(c)?if(表達(dá)式1)語句1
elseif(表達(dá)式2)語句2
elseif(表達(dá)式3)語句3
…
elseif(表達(dá)式m)語句m
else語句n如:
if(result==10)
{printf(“Right!!!”);}
elseif(result<10)
{printf(“Smaller”);}
elseif(result>10)
{printf(“Bigger”);}
else
{printf(“Wrong”);}
//如果result==10成立,就執(zhí)行其后面的語句,執(zhí)行完成后跳出if語句,后面的都不執(zhí)行,如果不成立,則順序進(jìn)行判斷,如果所有的條件都不成立,就執(zhí)行最后一條語句在本程序中,由于需要4種不同的延時(shí)時(shí)間,因此可采用編寫一個(gè)帶參數(shù)的時(shí)間函數(shù)的方法,通過改變實(shí)參值的大小,來改變總的延時(shí)時(shí)間。這里編寫一個(gè)執(zhí)行1次延時(shí)時(shí)間為10?ms的函數(shù),這樣如果需要100?ms,就讓實(shí)參為10,300?ms就讓實(shí)參為30,即實(shí)參參數(shù)等于想要延時(shí)的時(shí)間除以基本時(shí)間(10?ms)。通過之前講述的方法,可以得到以下程序:
voiddelay_10ms(unsignedintz)
{unsignedintx,y;
for(x=z;x>0;x--)
for(y=1150;y>0;y--);
}
通過Keil軟件的觀察可知,當(dāng)z=1時(shí),延時(shí)函數(shù)delay)10?ms延時(shí)時(shí)間為10?ms。
(3)程序代碼如下:
#include<reg52.h>
sbits1=P1^0;
sbits2=P1^1;
sbits3=P1^2;
sbits4=P1^3;
voiddelay_10ms(unsignedintz) //10ms延時(shí)函數(shù)
{
unsignedintx,y;
for(x=z;x>0;x--)
for(y=1150;y>0;y--);
}
voidmain()
{
unsignedcharw;
while(1)
{
//判斷P2.0是否為0,如果是則延時(shí)800?ms
if(s1==0)
{
P2=0x03;
delay_10ms(80);
for(w=0;w<6;w++)
{P2=P2<<1;
delay_10ms(80);
} for(w=0;w<5;w++)
{?P2=P2>>1;
delay_10ms(80);
}
}
//判斷P2.1是否為0,如果是則延時(shí)500?ms if(s2==0)
{ P2=0x03;
delay_10ms(50);
for(w=0;w<6;w++)
{
P2=P2<<1;
delay_10ms(50);
} for(w=0;w<5;w++)
{
P2=P2>>1;
delay_10ms(50);
}
}
//判斷P2.2是否為0,如果是則延時(shí)300?ms
if(s3==0)
{
P2=0x03;
delay_10ms(30);
for(w=0;w<6;w++) {
P2=P2<<1;
delay_10ms(30);
}
for(w=0;w<5;w++)
{
P2=P2>>1;
delay_10ms(30);
}
}
//判斷P2.3是否為0,如果是則延時(shí)100ms
if(s4==0)
{
P2=0x03;
delay_10ms(10);
for(w=0;w<6;w++)
{
P2=P2<<1;
delay_10ms(10);
} for(w=0;w<5;w++)
{
P2=P2>>1;
delay_10ms(10);
}
}
}
}
(4)程序說明如下:
①“=”和“==”的區(qū)別:“=”是賦值,例如“a=3;”,意思是將3賦給變量a;“==”是判斷左右是否相等,例如:“a==3;”,意思是判斷變量a是否等于3。所以在上述程序中,判斷P2.0~P2.3是否為0,不能用“=”,應(yīng)該用“==”。
②在編寫帶參數(shù)10?ms延時(shí)函數(shù)時(shí),應(yīng)該反復(fù)多次觀察,特別是帶參數(shù)進(jìn)行驗(yàn)證,有時(shí)確定10?ms延時(shí)后,當(dāng)代入?yún)?shù)后(特別是大參數(shù)),有較大的誤差,應(yīng)盡量避免這種情況的出現(xiàn)。
③在使用Keil軟件進(jìn)行觀察時(shí),如果關(guān)閉后再打開軟件,需要對(duì)晶振頻率重新設(shè)置,否則延時(shí)時(shí)間不準(zhǔn)確?!居布R(shí)補(bǔ)充:發(fā)光二極管與限流電阻】
發(fā)光二極管(Light-EmittingDiode)簡(jiǎn)寫為L(zhǎng)ED,其兩根引線中較長(zhǎng)的一根為正極,應(yīng)接電源正極,有的發(fā)光二極管的兩根引線一樣長(zhǎng),但管殼上有一凸起的小舌,靠近小舌的引線是正極。
發(fā)光二極管的反向擊穿電壓約5?V。它的正向伏安特性曲線很陡,使用時(shí)必須串聯(lián)限流電阻以控制通過管子的電流。限流電阻R可用下式計(jì)算:
R?=?(VCC?-?VD)/IF
其中,VCC為電源電壓;VD為二極管正向壓降;IF為流過二極管的電流。發(fā)光二極管正向壓降約為1.6?V~2.1?V,而發(fā)光二極管正向工作電流為5~20?mA。
因此,在單片機(jī)電路中,我們用的電源電壓為5?V,發(fā)光二極管正向壓降我們?nèi)??V,工作電流取10?mA,就可以計(jì)算出我們所需要的限流電阻,即
R?=?(5?-?2)/10?=?300?Ω
實(shí)際應(yīng)用中,可以選擇阻值比計(jì)算值略大一些的電阻。同時(shí)需要注意的是,顏色不同,發(fā)光二極管的參數(shù)有所區(qū)別。
擴(kuò)展:在例2.4電路的基礎(chǔ)上,你能不能自己設(shè)計(jì)出其他樣式LED的變化呢?
2.4Keil軟件簡(jiǎn)介
在前面的章節(jié)中,我們已經(jīng)介紹了Keil軟件工程的建立與基本設(shè)置、編譯鏈接等基本使用方法,下面介紹一下Keil軟件的其他一些常用方法,方便調(diào)試。
1.常用工具欄
菜單欄提供了項(xiàng)目操作、編輯操作、編譯調(diào)試以及幫助等各種常用操作,見圖2.20。
文件操作工具欄如圖2.21所示。
編譯工具欄提供編譯項(xiàng)目和文件的各種操作,如圖2.22所示。
調(diào)試工具欄提供項(xiàng)目仿真和調(diào)試過程中經(jīng)常使用的命令,如圖2.23所示。圖2.20菜單欄圖2.21文件操作工具欄圖2.22編譯工具欄圖2.23調(diào)試工具欄
2.常用快捷鍵
1)文件操作
文件操作的快捷鍵如下:
(1)?Ctrl+O:打開已經(jīng)存在的文件;
(2)?Ctrl+N:創(chuàng)建新文件;
(3)?Ctrl+S:保存當(dāng)前文件。
2)源代碼編輯
源代碼編輯的快捷鍵如下:
(1)?Ctrl+Z:取消上次操作;
(2)?Ctrl+Shift+Z:重復(fù)上次操作;
(3)?Ctrl+X:剪切所選文本;
(4)?Ctrl+Y:剪切當(dāng)前行的所有文本;
(5)?Ctrl+C:復(fù)制所選文本;
(6)?Ctrl+V:粘貼;
(7)?Ctrl+F2:設(shè)置/取消當(dāng)前行的標(biāo)簽;
(8)?F2:移動(dòng)光標(biāo)到下一個(gè)標(biāo)簽處;
(9)?Shift+F2:移動(dòng)光標(biāo)到上一個(gè)標(biāo)簽處;
(10)?Ctrl+F:在當(dāng)前文件中查找文本。
3)調(diào)試
調(diào)試程序時(shí)會(huì)用到如下一些快捷鍵:
(1)?Ctrl+F5:開始/停止調(diào)試模式;
(2)?F5:運(yùn)行程序,直到遇到一個(gè)中斷;
(3)?Fll:?jiǎn)尾綀?zhí)行程序,遇到子程序則進(jìn)入;
(4)?FlO:?jiǎn)尾綀?zhí)行程序,跳過子程序;
(5)?Ctrl+Fll:執(zhí)行到當(dāng)前函數(shù)的結(jié)束;
(6)?ESC:停止程序運(yùn)行。
3.常用調(diào)試命令
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- GB 12158-2024防止靜電事故通用要求
- 二零二五年度地質(zhì)災(zāi)害防治安全承包合同范本2篇
- 2025年度老舊廠房拆除重建項(xiàng)目轉(zhuǎn)讓合同3篇
- 二零二五版UPS不間斷電源系統(tǒng)在數(shù)據(jù)中心節(jié)能改造中的應(yīng)用合同3篇
- 二零二五年度食品安全樣本檢驗(yàn)合同2篇
- 2025年度物業(yè)管理委托合同(住宅小區(qū))3篇
- 三方監(jiān)理服務(wù)協(xié)議:2024年度工程監(jiān)管協(xié)議版B版
- 二零二五版公司銷售業(yè)務(wù)員合同協(xié)議書含虛擬貨幣交易業(yè)務(wù)合作3篇
- 2024年轎車物流服務(wù)協(xié)議模板版B版
- 2024煙花爆竹行業(yè)信用風(fēng)險(xiǎn)防范購(gòu)銷合同管理3篇
- 2025年山東光明電力服務(wù)公司招聘筆試參考題庫含答案解析
- 《神經(jīng)發(fā)展障礙 兒童社交溝通障礙康復(fù)規(guī)范》
- 詩詞接龍(飛花令)PPT
- 子宮內(nèi)膜癌(課堂PPT)
- 澳大利亞公司法1-30
- 海上試油測(cè)試技術(shù)0327
- 中國(guó)地圖標(biāo)準(zhǔn)版(可編輯顏色)
- 瑪氏銷售常用術(shù)語中英對(duì)照
- (完整)貓咪上門喂養(yǎng)服務(wù)協(xié)議書
- 上海牛津版三年級(jí)英語3B期末試卷及答案(共5頁)
- 行為疼痛量表BPS
評(píng)論
0/150
提交評(píng)論