第五課 LED數(shù)碼管,蜂鳴器實驗準備:使用前一課已裝配好的實驗板 共陽極單位數(shù)碼管1只 共陰極4位數(shù)碼管2只 蜂鳴器模塊一件 電阻:10k 8只 或排阻(用于P0上拉) 138譯碼器:74LS138 一只 (或直接使用完整的開發(fā)板) 課程內(nèi)容:一、 共陽極LED數(shù)碼管對比下這兩個原理圖,應(yīng)該很容易發(fā)現(xiàn)差不多相同的abcdefg和dp分別對應(yīng) 8 LED 的D1—D8,那么控制數(shù)碼管顯示數(shù)字是不是與8 LED一樣控制發(fā)光與不發(fā)光呢,例如顯示0,只需要讓g和dp不發(fā)光,其他發(fā)光,給這8位數(shù)的信號是 11000000。光說不行,必須做實驗。實踐是檢驗真理的唯一標準。 這一課開始,我們用上P0端口,這P0端口與其他的P1、P2、P3有點不同,它每個管腳需要增加一只電阻接上電源5V,這稱為上拉,讓管腳先獲得默認值1,如果沒有這上拉電阻,管腳狀態(tài)稱為浮空,不能確定數(shù)據(jù)是0還是1。 把P0的線接上這只共陽級單位數(shù)碼管,然后按剛才的想法,修改程序。 void main() { P0=0xC0; // 11000000 } 編譯、下載、觀看效果。果然0顯示出來了。 其他的數(shù)字呢,同樣,可以計算出來。 我們利用前一課LED點陣課程中數(shù)組的方式,把這一組數(shù)先存放好,其中還包括AbcdEFPHLy-這幾個常用的字符的顯示數(shù)據(jù)。 uchar code light[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x8C,0x89,0xC7,0x91,0xBF,0xFF}; 放入function.h頭文件中,方便以后隨時使用。 void main() { P0= light[3]; // 顯示數(shù)組中第4個數(shù),注意C語言順序是從0開始 } 繼續(xù),我們讓數(shù)字也動起來,讓數(shù)碼管從0到8一個一個按順序顯示,這得要用上前面課程中的循環(huán)與延時功能了。 void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=0;i<> { P0= light[i]; // 顯示數(shù)組中第i個數(shù),注意C語言順序是從0開始 mDelay(1000); } } 編譯,下載到實驗板,可以看到數(shù)字變化起來了。 再繼續(xù),來換成倒數(shù)方式,程序改動一點點。 void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>0;i--) { P0= light[i]; // 顯示數(shù)組中第i個數(shù),注意C語言順序是從0開始 mDelay(1000); } } 編譯,下載實驗板檢驗,倒數(shù)出來了,但是少了0的顯示。 看那判斷循環(huán)條件,i>0時才做循環(huán),所以0時沒進入循環(huán)內(nèi),改為i>=0試下; void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>=0;i--) { P0= light[i]; // 顯示數(shù)組中第i個數(shù),注意C語言順序是從0開始 mDelay(1000); } } 編譯,下載實驗板,終于可以倒數(shù)到0了。 但感覺有不對勁的地方,沒改>=0之前可以不斷變數(shù)字,而現(xiàn)在數(shù)到0就停了?。?/p> 二、 BUG 的分析與排除搞開發(fā)總是免不了BUG,但有錯必改,關(guān)鍵是如何工出BUG點,然后修復。 分析開始: 代碼中當 i=0,符合條件 i>=0,所以進入循環(huán)體內(nèi)顯示0,之后執(zhí)行i--,這時,問題來了。 Main()內(nèi)的第一行命令 uint i; 是定義一個循環(huán)變量,用于控制循環(huán),這個i是uint 型,表示正整型數(shù)(即是數(shù)學上的正數(shù)、整數(shù))。 而當 i=0之后再減1時,i就變成負數(shù),與定義的正整型數(shù)不符合,程序中止。 修復: 修復BUG的方法有多種,這里提供一種,其他方法可以自己試下改代碼實踐下。 既然 i 必須是正整數(shù),那么必須讓i>0做循環(huán)條件,而不是i>=0,同時循環(huán)體內(nèi)的數(shù)組顯示改為P0= light[i-1];也就是顯示前一位置的數(shù),來達到顯示0的效果。 void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>0;i--) { P0= light[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 mDelay(1000); } } 編譯,下載實驗板,這回效果終于正確了,這就是查BUG與修復,學習開發(fā)中必須要學會的。 三、蜂鳴器看那倒數(shù)的程序,與火箭發(fā)射倒計時很像,每顯示一數(shù)加個『嘀』就行了。 這需要用到蜂鳴器模塊。 從蜂鳴器原理圖看到,把它接在P1的第5腳 ,然后給這管腳一個信號0,就可以讓它響了。 首先,在function.h 頭文件中 增加 這管腳的定義sbit P15=P1^5; 然后,修改主程序main(),如下: void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>0;i--) { P0= light[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 P15=0; // 給信號0,讓蜂鳴器在顯示數(shù)字同時響 mDelay(1000); //延時1秒,可以調(diào)節(jié) P15=1; //響1秒,夠了,靜音 mDelay(1000);//延時,否則直接進入下一個循環(huán)立即又響,沒停了 } } 編譯,下載實驗板,效果有了。 不過,倒數(shù)到0后,又回去從頭開始倒數(shù),火箭都跑了,還數(shù)什么呢,而且『嘀』聲不斷也挺煩人,這不符合火箭發(fā)射倒數(shù)要求,必須在倒數(shù)到0后,就停在0處。 單片機是永不停息工作的,除非程序出BUG,想讓它停,也真不容易。既然它喜歡工作,那就讓它在某處繞圈子,做沒用的工作,實現(xiàn)停在某處的效果。 怎樣不停的讓它做沒用的工作,這就要用于之前學的 for 循環(huán),讓單片機做空命令循環(huán),把這空循環(huán)代碼放程序結(jié)束之前就行了。 void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>0;i--) { P0= light[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 P15=0; // 給信號0,讓蜂鳴器在顯示數(shù)字同時響 mDelay(1000); //延時1秒,可以調(diào)節(jié) P15=1; //響1秒,夠了,靜音 mDelay(1000);//延時,否則直接進入下一個循環(huán)立即又響,沒停了 } for(;;); //讓程序停在這 不斷做空體循環(huán) } 編譯,下載實驗板,要想的效果出來了,也就是程序正確了。 四、 共陰極數(shù)碼管從原理圖可以看到 共陰極數(shù)碼管是把LED 的負極接在一起,由COM來控制,給COM來個0,然后傳 個8位的數(shù)據(jù),就會有顯示了。 共陰極LED數(shù)碼管要顯示數(shù)字,對應(yīng)的位的信號剛好與共陽極的相反,例如,數(shù)字0,這里對應(yīng)的數(shù)據(jù)變成00111111。按前面的方法,可以計算出共陰極數(shù)碼管顯示數(shù)據(jù)。 uchar code Elight[] ={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x73,0x76,0x38,0x6E,0x40,0x00}; 同樣,放進 function.h內(nèi),方便以后調(diào)用。 從原理圖中看到2個4位數(shù)碼管各COM控制線剛好組成8位,那么我們用P2 來連接這個控制線。 void main() { uint i; //循環(huán)變量,用于控制循環(huán) for(i=9;i>0;i--) { P0= Elight[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 P15=0; // 給信號0,讓蜂鳴器在顯示數(shù)字同時響 mDelay(1000); //延時1秒,可以調(diào)節(jié) P15=1; //響1秒,夠了,靜音 mDelay(1000);//延時,否則直接進入下一個循環(huán)立即又響,沒停了 } for(;;); //讓程序停在這 不斷做空體循環(huán) } 也就是僅僅是把顯示數(shù)組換成 Elight 。 編譯,下載實驗板檢驗,怎么沒反應(yīng)的? 分析下,原來控制口COM接上了P2,P2內(nèi)部有上拉信號,也就是就各管腳默認值是1,而這是共陰極數(shù)碼管,只有給0才顯示,所以信號是1時就不顯示了。 那么代碼中加 P2 =0x00;代碼: void main() { uint i; //循環(huán)變量,用于控制循環(huán) P2 =0x00; //控制數(shù)碼管顯示 for(i=9;i>0;i--) { P0= Elight[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 P15=0; // 給信號0,讓蜂鳴器在顯示數(shù)字同時響 mDelay(1000); //延時1秒,可以調(diào)節(jié) P15=1; //響1秒,夠了,靜音 mDelay(1000);//延時,否則直接進入下一個循環(huán)立即又響,沒停了 } for(;;); //讓程序停在這 不斷做空體循環(huán) } 編譯,下載實驗板檢驗,8個管同時倒數(shù),挺壯觀的。 把P2 =0x00; 換成 P2=0xAA ;即10101010,編譯,下載實驗板檢驗,可以看出你想哪個管顯示,那么就給哪個管COM信號0。 五、138譯碼器從上面的程序中可看到。選擇數(shù)碼管占用了整整一個P2端口,8個IO ,這51單片機總共才4組,這樣使用,效率低。于是138譯碼器出場了,它讓8個IO 口的占用減少到只用3個 IO,為什么3個IO就夠了呢,3個IO可以從000數(shù)到111,剛好是十進制的 0到7,共8個數(shù),可以代表8個數(shù)碼管的選擇位。 就取某一學習板的138電路原理圖,那J15直接連上 8位數(shù)碼管的COM控制端,同時也用P22、P23、P24這三個IO來控制選位。 OK,在function.h 上補上這三個IO的定義: sbit P22=P2^2; sbit P23=P2^3; sbit P24=P2^4; 然后修改main()主程序: void main() { uint i; //循環(huán)變量,用于控制循環(huán) P24 =1; // P23=0; // 100 就是十進制4,第5個數(shù)碼管有顯示 P22=0; // for(i=9;i>0;i--) { P0= Elight[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 P15=0; // 給信號0,讓蜂鳴器在顯示數(shù)字同時響 mDelay(1000); //延時1秒,可以調(diào)節(jié) P15=1; //響1秒,夠了,靜音 mDelay(1000);//延時,否則直接進入下一個循環(huán)立即又響,沒停了 } for(;;); //讓程序停在這 不斷做空體循環(huán) } 同樣方式,可以選擇其他位的數(shù)碼管。 六、 讓8位數(shù)碼管動起來這里8位數(shù)碼管,僅顯示1位,不行,下面要讓8位輪顯示不同的數(shù),動起來。 前面課程學過用移位的方法讓LED輪流發(fā)光,這里也可以使用。如果不采用138譯碼器的方式,直接P2控制數(shù)碼管COM端,直接移位試就可以,同學可以自己課后編程實驗下。這里采用138譯碼器,要有點改動,因為P22,P23,P24在P2的中間位置,用01表示這三位,就是11100011(給0是選位),即0xE3。那么只要這三個位的數(shù)有變化就行了。 看代碼中的注釋。 void main() { uchar a =0x00; //用于從0到7的計算 uchar b =0x00;//用于讓P22,P23,P24 對應(yīng)的位置與a相同 uint i; //循環(huán)變量,用于控制循環(huán) for(i=8;i>0;i--) { b=a<2;>2;> P2=0xE3+b; // P2原值加上P22,P23,P24 對應(yīng)位置的數(shù) a++; //從0到7 變化 P0= Elight[i-1]; //顯示數(shù)組中第i-1個數(shù),注意C語言順序是從0開始 mDelay(1000); } } 分析代碼: 1)b=a<> 例如,某一時刻 a值是 000000101,(即0x05,十進制 5),左移2位是 00010100剛好其中原 101這三位進入到P22,P23,P24的位置。 2)P2=0xE3+b; 0xE3就是11100011,加上b值后,就是11110111,即P22,P23,P24 這幾位放上了對應(yīng)的數(shù)了,而這三位控制數(shù)碼管選位,于是對應(yīng)位顯示了。 3)P0= Elight[i-1]; 每次循環(huán)顯示不同的數(shù),這樣各位就顯示不同的數(shù)。 編譯,下載實驗板檢驗,可以看到每隔1秒,效果出來了。 那里的延時 mDelay(1000); 可以按自己的想法隨意改,可以試下填入 100,10,1,觀看不同的效果。 到最后用 mDelay(1000);時,看到各個數(shù)碼管同時亮起來,穩(wěn)定顯示不同的數(shù)。 這是由于數(shù)碼管的LED有顯示數(shù)后有余輝,才1毫秒的延時基本沒消失就顯示進入下一次的顯示,這樣顯示就是連續(xù)的效果。 |
|
|