日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

《中學(xué)生C51單片機(jī)易學(xué)實(shí)戰(zhàn)入門教程》第二課

 岐岐feng 2018-03-26

《中學(xué)生C51單片機(jī)易學(xué)實(shí)戰(zhàn)入門教程》

第二課 讓LED閃起來(lái)

實(shí)驗(yàn)準(zhǔn)備:使用第一課已裝配好的實(shí)驗(yàn)板

課程內(nèi)容

一、分析LED接線原理圖:

《中學(xué)生C51單片機(jī)易學(xué)實(shí)戰(zhàn)入門教程》第二課

著重左上角的 LED電路部分。《中學(xué)生C51單片機(jī)易學(xué)實(shí)戰(zhàn)入門教程》第二課

LED正極接電源5V,現(xiàn)程序控制 LED負(fù)極(原理圖中管腳P1^0)為0V,LED兩端正向有電壓差,于是LED導(dǎo)通,發(fā)光。

那如何控制讓 LED燈 不發(fā)光呢?

只要LED兩端沒(méi)有電壓差就可以了,現(xiàn)在LED正極通過(guò)電阻已接上5V電壓,只要LED負(fù)極也是5V電壓,LED就不會(huì)導(dǎo)通,不發(fā)光了。

上一課中,控制LED負(fù)極電壓的代碼是:

P10 = 0;

表示控制管腳 P1^0的電壓為 0V,現(xiàn)在要改成控制管腳 P1^0的電壓為 5V,這塊單片機(jī)芯片只認(rèn)識(shí)兩個(gè)數(shù)字0與1,0代表0V,1代表5V。于是讓LED燈不發(fā)光,只須改成以下程序代碼:

P10 = 1;

相當(dāng)簡(jiǎn)單。

動(dòng)手改程序,編譯,下載到實(shí)驗(yàn)板中觀察運(yùn)行結(jié)果。

實(shí)驗(yàn)板沒(méi)反應(yīng)?不會(huì)壞了吧。

當(dāng)然不是壞,分析下電路原理吧。

在沒(méi)有加電的時(shí)候,LED燈兩端電壓為0,沒(méi)電的狀態(tài)下肯定不會(huì)發(fā)光。

當(dāng)下載程序后,實(shí)驗(yàn)板加上電了,LED正極接上了5V電壓,LED負(fù)極讓程序控制了,也是5V電壓,兩端沒(méi)有產(chǎn)生能讓LED導(dǎo)通的電壓差,于是LED不發(fā)光。

修改控制LED的代碼改為 P10 = 0; 下載實(shí)驗(yàn)板,LED燈又發(fā)光了。

再修改控制LED的代碼改為 P10 = 1; 下載實(shí)驗(yàn)板,LED燈又不發(fā)光了。

再修改控制LED的代碼改為 P10 = 0; 下載實(shí)驗(yàn)板,LED燈又發(fā)光了。

… …

我想讓LED 像星星一樣閃啊閃,而這樣的只能是不發(fā)光或只發(fā)光的狀態(tài)不合要求。

二、如何才能實(shí)現(xiàn)閃的效果?

那就是 先控制LED 發(fā)光一段時(shí)間,然后再控制LED不發(fā)光一段時(shí)間,如此重復(fù)下去。

單片機(jī)的工作狀態(tài)是:只要給它加電,它就永不停息的工作,不斷執(zhí)行設(shè)定的程序,直到斷電或燒壞。

所以,單片機(jī)是不會(huì)自己暫停一小段時(shí)間來(lái)讓LED轉(zhuǎn)狀態(tài)的,必須由程序來(lái)控制。那單片機(jī)既然是永不停息的工作,又如何讓編程序控制單片機(jī)暫停一小段時(shí)間呢?方法很簡(jiǎn)單,就是讓它空跑,做無(wú)用的工作,達(dá)到消耗時(shí)間的目的,也就是浪費(fèi)一下它的時(shí)間,實(shí)現(xiàn)延時(shí)效果。

開發(fā)單片機(jī)的前輩已設(shè)計(jì)好這個(gè)消耗時(shí)間的程序,稱為延時(shí)函數(shù),如下:

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

{

for(i=0;i<>

{

}

}

}

先不管這代碼是如何設(shè)計(jì),先把這段代碼輸入到上一課的程序中,并控制LED燈的狀態(tài)切換。

#include 'reg52.h'

#define uint unsigned int

#define uchar unsigned char

sbit P10= P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

{

for(i=0;i<>

{

;

}

}

}

void main()

{

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

}

要注意,輸入延時(shí)函數(shù)時(shí),兩行#define和整個(gè)延時(shí)函數(shù)代碼要放在主程序段 void main()之前。因?yàn)橐懊嫦扔写a功能,后面才可能拿來(lái)使用,也就是調(diào)用延時(shí)功能。

代碼量增加了,要注意按花括號(hào)分層級(jí)縮進(jìn)代碼,方便以后分析程序。

代碼量增加了,這時(shí)可能編譯時(shí)又會(huì)報(bào)錯(cuò),必須要花時(shí)間去排除錯(cuò)誤,這就叫查BUG和修復(fù)BUG。編代碼,查BUG,修復(fù)BUG,測(cè)試,這幾步重重復(fù)復(fù),就是編程序的工作過(guò)程。

編譯正確,下載到實(shí)驗(yàn)板上,可以看到達(dá)到了讓LED閃的效果,可是閃得很慢,一秒才閃一下。

想改快點(diǎn),也很簡(jiǎn)單,代碼中的

mDelay(1000);

括號(hào)中的數(shù)據(jù)稱為參數(shù),給不同的數(shù)據(jù),延時(shí)函數(shù)就有不同的工作效果??梢苑謩e把1000改成500、100、20等做實(shí)驗(yàn)檢驗(yàn)下效果,實(shí)踐是檢驗(yàn)真理的唯一方法,必須動(dòng)手做實(shí)驗(yàn)。

三、程序分析

雖然實(shí)驗(yàn)有了效果,但是我們卻仍然不知道為何能有這正確的結(jié)果。

我們來(lái)分塊分析。

首先,主程序 main()里面的代碼,容易理解,只要知道代碼

mDelay(1000);

能延時(shí)一秒就行了。

然后再看mDelay 延時(shí)函數(shù)內(nèi)部代碼及相關(guān)代碼,這回多了兩行代碼,這兩行稱為預(yù)編譯定義:

#define uint unsigned int //用 uint 代表unsigned int

#define uchar unsigned char //用uchar 代碼unsigned char

以后的程序中所有的uint 和uchar 在代碼編譯時(shí)會(huì)自動(dòng)換成unsigned int和unsigned char,也就是就輸入代碼量減少了,但結(jié)效果不變,省時(shí)省力。

這兩行基本代碼以后的程序中都會(huì)出現(xiàn)。

void mDelay(uint Delay) //功能模塊:延時(shí)函數(shù),帶控制參數(shù)

{

uint i; //后面要用到的臨時(shí)變量,使用前要先定義

for(;Delay>0;Delay--) //不斷重復(fù)運(yùn)行括號(hào)的代碼,直到Delay減到0

{

for(i=0;i<124;i++)>

//直到i加到124才停止

{

; // 僅分號(hào),沒(méi)命令,效果是運(yùn)行一次就空轉(zhuǎn)一次

}

}

}

要點(diǎn):其中 for()這行括號(hào)里面,第一位置放的是初始值,留空的話表示不用管初始值,中間位置放置控制結(jié)束的條件,條件符合就繼續(xù)工作,條件不符合時(shí)就退出,第三位置放置的是每完成一次工作后要做的小小改變,達(dá)到控制程序的目的。

這個(gè)for()命令,稱為循環(huán)結(jié)構(gòu),用于重復(fù)做一段相同的工作。

四、程序優(yōu)化

優(yōu)化程序,能讓編程素質(zhì)提高。

細(xì)心的同學(xué)可能會(huì)發(fā)現(xiàn),在main()程序段中

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

先控制了LED發(fā)光,然后延時(shí)1秒,再控制LED不發(fā)光,然后延時(shí)1秒,然后 … … 沒(méi)有然后了,程序結(jié)束了。但是為何程序卻能按原意重復(fù)一閃一閃?

沒(méi)錯(cuò),程序的確是結(jié)束了。

于是LED不發(fā)光了。

但是,由于單片機(jī)加電之后是永不停息的工作,于是它重新回到初始加電狀態(tài),于是又從頭再次執(zhí)行了 main()代碼,于是LED又閃了。

也就是說(shuō),這個(gè)LED不停閃動(dòng)。并不是我們的程序控制,而是單片機(jī)需要不停工作。

這可不行,這方式中有部分時(shí)間不是由程序控制,也就是不可控。這是編程大忌,絕不能讓程序編著編著變成不由我控制了。

那個(gè)不停的工作也必須由代碼控制。

剛好,剛學(xué)會(huì)使用的 for()循環(huán)結(jié)構(gòu)派上用場(chǎng)了。

給LED燈加上永遠(yuǎn)循環(huán)的控制,main()主程序變成:

void main()

{

for(;;)

{

P10=0;

mDelay(1000);

P10=1;

mDelay(1000);

}

}

也就是不用管初始條件,不用管是否結(jié)束,只要做下去就是了。

繼續(xù)優(yōu)化。

功能增加了,代碼也增加了,單片機(jī)做的工作也多了,這樣工作時(shí)間就花多了,于是工作效率就下降了。

為提高效率,程序可以修改成如下:

#include 'reg52.h'

#define uint unsigned int

#define uchar unsigned char

sbit P10= P1^0;

void mDelay(uint Delay)

{

uint i;

for(;Delay>0;Delay--)

for(i=0;i<>

}

void main()

{

P10=!P10;

mDelay(1000);

}

可以看到,程序長(zhǎng)度一下子少了一半,這是因?yàn)?C語(yǔ)言中,如果控制的命令只有一行,那么可以省去配對(duì)的花括號(hào)。

主程序main()中,命令由原來(lái)的4行變成2行,只因一個(gè)嘆號(hào)!

符號(hào)!是C語(yǔ)言的一個(gè)運(yùn)算符,就像數(shù)學(xué)課中的 +(加) –(減)一樣,它的作用是取反,單片機(jī)只認(rèn)識(shí)0與1兩個(gè)數(shù),0取反就是1,1取反就是0 。

P10=!P10;

這代碼就實(shí)現(xiàn)了每次循環(huán)讓P10在0與1之間改變,達(dá)到控制閃的目的。

五、增補(bǔ)C語(yǔ)言注釋功能

為增加程序可讀性,可以在代碼行后面使用//符號(hào),并加入文字說(shuō)明,幫助理解這段代碼的功能,還可以使用 /* 說(shuō)明文字 */ 方式注釋,其中說(shuō)明文字部分可以分多行。

附記:

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多