(四) 呵呵,朋友,!相信你的流水燈也做的不錯(cuò)了吧,,現(xiàn)在能玩出幾種花樣了?你可能會(huì)說,,只要你想得到,,想怎么流就怎么流!呵呵,,是的,。 但是工程師們?cè)O(shè)計(jì)這么一個(gè)單片機(jī),,并不是只為了讓它做流水燈的,那樣也太浪費(fèi)點(diǎn)了吧 ... ^_^ 學(xué)過數(shù)字電路的朋友,,一定動(dòng)手做過8路或者6路的搶答器,。用純粹的數(shù)字電路知識(shí)來做,自己設(shè)計(jì)電路,,感到比較困難,!搶答器上用的顯示器多為7段數(shù)碼管,這里我們來講講,,如何用單片機(jī)讓數(shù)碼管顯示0-9,。搶答器的實(shí)現(xiàn),我們放到后面再來探討,,因?yàn)閾尨鹌鬟€涉及了鍵盤的內(nèi)容,。8段數(shù)碼管分為共陰和共陽兩種。8段數(shù)碼管是由8個(gè)LED組成(還包括一個(gè)小數(shù)點(diǎn)),。若為共陽,,則8個(gè)LED的陽級(jí)是連接在一起的,同理若為共陰,,則陰極連接在一起,。8個(gè)LED對(duì)應(yīng)的標(biāo)號(hào)如下:({0x3f, 0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9數(shù)字) 01 23 4 5 6 7 8 9 0011 1111,0000 0110,0100 1111,0101 1011 a一 f| |b g一 e| |c d一 。dp 一般情況下,,為了計(jì)算或取碼的方便,,我們把a(bǔ)-dp依次接到單片機(jī)某個(gè)口上的Px.0--Px.7上。x表示0,,1,,2,3其中的一個(gè),。這樣我們只要給某個(gè)口,,賦一個(gè)值,則相應(yīng)的LED段就被點(diǎn)亮,,但是在硬件連接上要注意了:?jiǎn)纹瑱C(jī)可能不能直接驅(qū)動(dòng)LED,,所以我們可以通過控制三級(jí)管的導(dǎo)通或截止,來控制LED的亮與滅,!如果我們把共陰的數(shù)碼管的a—dp依次接到單片機(jī)的P0.0--P0.7上,,注意:P0口需接上拉電阻。何為上拉電阻,,簡(jiǎn)單的說,,就是把電平拉高,以提高驅(qū)動(dòng)能力,。那么比如:P0 = 0X3F,;則顯示為數(shù)字0 ,。因?yàn)?X3F即為2進(jìn)制的0011 1111我們低位往高位數(shù),依次為1111 1100,,其I/O的電平分別為高,、高、高,、高,、高、高,、低,、低,即對(duì)應(yīng)的a—dp為亮,、亮,、亮、亮,、亮,、亮、滅,、滅,,由上圖我們可以看出g和dp段不亮其他段均亮,即為我們所看到的數(shù)字0字樣,。其他的數(shù)字或字符,,也同理可以得到。但是有些朋友就會(huì)問,,那我們每取一個(gè)字模,,豈不是很麻煩,?還有自己考慮高低電平什么的,?^-^ 呵呵,其實(shí)網(wǎng)上有很多LED取模軟件,,如果有一定計(jì)算機(jī)編程語言的朋友,,也可以試著自己寫個(gè)取模的程序,讓計(jì)算機(jī)為我們計(jì)算,,諸如上述0X3F的數(shù)值,。 #include<reg51.h> void Delay(unsigned char a) { unsigned char i; while( --a != 0) { for(i = 0; i < 125; i++); } } void main(void) { P0 = 0X3F; //顯示0 Delay(250);//延時(shí) P0 = 0X00;//短暫的關(guān)閉顯示,若不關(guān)閉,,可能會(huì)造成顯示模糊不清,。 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> P0 = 0X06; //顯示1 Delay(250); P0 = 0X00; ... //以下顯示數(shù)字2-F,略,。 } 看到這里,,想必大家一定可以把0-F顯示出來了吧,!但是如果要你顯示兩位數(shù),三位數(shù)呢,?或許,,有的朋友會(huì)這么想:在P0口上接一個(gè)數(shù)碼管,再在P1口上接個(gè)數(shù)碼管,!但是,,如果要顯示4位、5位的數(shù)字呢,?那豈不是一塊AT8951都接不過來,!難到就不能接4位或5位以上的嗎?肯定不是的,!說到這里,,我們來講講數(shù)碼管的顯示方式,可分為兩種:動(dòng)態(tài)掃描和靜態(tài)顯示,。上面我們所說的即為靜態(tài)顯示,。但是如果我們采用動(dòng)態(tài)掃描顯示,那么就可以解決上面的問題,,即可以顯示多個(gè)數(shù)碼管了,。上面我們所說的靜態(tài)顯示把數(shù)碼管的COM腳接至VCC或GND端,其他的接至PX口上,,這樣只要PX口上輸出相應(yīng)的高低電平,,就可以顯示對(duì)應(yīng)的數(shù)字或字符。但是如果我們采用動(dòng)態(tài)掃描的方法,,比如顯示6個(gè)數(shù)碼管,,硬件連接可以這樣解決:a—dp還是接至P0.0--P0.7上,還有6個(gè)COM腳再接至另外口的P2.0--P2.5,。P0口作段選(控制數(shù)字字符)P2口作位選(選通哪個(gè)數(shù)碼管導(dǎo)通)這樣我們控制P0和P2口就可以控制6個(gè)數(shù)碼管了,。但是,細(xì)心的朋友,,會(huì)問這樣的問題:P2位選,,是讓數(shù)碼管一個(gè)一個(gè)亮的,那還是不能控制6個(gè)一起亮或滅嘛??? ^_^ 想想好象是對(duì)的哦?怎么辦...難道錯(cuò)了,?嘿嘿,,問你個(gè)問題?黑夜里,拿著一支煙,,在你面前快速的晃動(dòng),,你會(huì)發(fā)現(xiàn)什么樣的現(xiàn)象?是不是原本不連續(xù)的點(diǎn)變成了一條看上去連續(xù)的曲線或者直線,!再回過頭來,,仔細(xì)想想我們的數(shù)碼管!原理是一樣的,,你可別忘了,,我們的單片機(jī)可是一個(gè)計(jì)算機(jī)哦,計(jì)算機(jī)的運(yùn)算速度,,大家可想而知吧,!這里再說說51單片機(jī)的機(jī)器周期和時(shí)鐘周期等概念。所謂機(jī)器周期就是訪問一次存儲(chǔ)器的時(shí)間,。而1個(gè)機(jī)器周期包括12個(gè)時(shí)鐘周期,。如果單片機(jī)工作在12M晶體下,那么一個(gè)時(shí)鐘周期為:1/12微妙,。一個(gè)機(jī)器周期12*1/12 = 1微妙,。如果晶體為6M,時(shí)鐘周期和機(jī)器周期各是多少呢,?在匯編中,,我們還要關(guān)心,指令執(zhí)行的機(jī)器周期長短不一,,有1個(gè)周期,、2個(gè)周期和4個(gè)周期等。說著說著,,跑了這么遠(yuǎn)了...還是回到原來的話題,,如果我們把位選的P2也看作上面的“煙”一劃而過,那么我們看到的是不是6個(gè)一起亮或一起滅了,! ^_^ 哈哈,,原來如此... 記住,在任何某一時(shí)刻,,有且只有一個(gè)數(shù)碼管能發(fā)光,。如果你能把這句話理解了,你是真明白我的意思了,!朋友,現(xiàn)在給你個(gè)任務(wù),,讓6個(gè)數(shù)碼管分別顯示1,、2、3,、4,、5,、6??茨阕约嚎梢愿愣ú??你自己先試著寫寫看咯... #include<reg51.h> void Delay(unsigned char a) { unsigned char i; while( --a != 0) { for(i = 0; i < 125; i++); } } void main(void) { while(1) { P0 = 0x06;//1的碼段 P2 = 0x01;//選通一位,或者P2_0 = 1; Delay(20);//延時(shí)約20毫秒 P0 = 0X00;//關(guān)閉顯示 P0 = 0x5b;//2的碼段 P2 = 0x02; //選通一位,,或者P2_1 = 1; Delay(20); P0 = 0X00; P0 = 0x4f;//3的碼段 P2 = 0x04; //選通一位,,或者P2_2 = 1; Delay(20); P0 = 0X00; P0 = 0x66;//4的碼段 P2 = 0x08; //選通一位,或者P2_3 = 1; Delay(20); P0 = 0X00; P0 = 0x6d;//5的碼段 P2 = 0x10;//選通一位,,或者P2_4 = 1; Delay(20); P0 = 0X00; P0 = 0x7d;//6的碼段 P2 = 0x20;//選通一位,,或者P2_5 = 1; Delay(20); P0 = 0X00; } } |
|