找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10612|回復(fù): 0
收起左側(cè)

五種方法實(shí)現(xiàn)流水燈

[復(fù)制鏈接]
ID:51090 發(fā)表于 2014-9-24 22:03 | 顯示全部樓層 |閱讀模式
嗨,大家好,我是寶哥,很高興您能關(guān)注我的文章,作為一名職業(yè)的IT男,把自己的所學(xué)記錄下來并與大家分享是我由來已久的一個想法,于是開通了這個博客,希望對還在迷茫和困惑中的朋友有所幫助。
今天懷著無比激動的心情,我完成了單片機(jī)C語言板塊第一篇博客的撰寫,寫的不好希望大家見諒,歡迎大家拍磚,給我提寶貴意見,我一定盡力改進(jìn),寫的不對的地方也請大家指出,以免誤人子弟,總之本人能力有限,希望大家不吝賜教!
本系列博客的撰寫我打算采用這樣的一個思路:以例子為路線,講解單片機(jī)C程序設(shè)計的方法,側(cè)重知識的活學(xué)活用,適合于有一定單片機(jī)和C語言基礎(chǔ)的朋友。
好了,廢話少說,開始我今天的主題,今天的主題是五種方法實(shí)現(xiàn)流水燈,講這個的目的不是為了讓你會五種方法而可以在小伙伴中炫耀,而是想告訴大家一個理念,學(xué)習(xí)要善于思考,活學(xué)活用,解決問題的辦法不只有一個。
好了,先上一個電路圖:


P0口為例,我連接了8個共陽的led燈,電路很簡單,當(dāng)IO口給低電平時,led點(diǎn)亮。那么實(shí)現(xiàn)流水燈的原理是:先點(diǎn)亮第一個led,保持一會,然后熄滅,點(diǎn)亮下一個led,保持,再熄滅,直到第8led點(diǎn)亮,之后熄滅,循環(huán)執(zhí)行這個過程。
其實(shí)這個功能的實(shí)現(xiàn)很簡單,就是循環(huán)執(zhí)行點(diǎn)亮、熄滅的過程。根據(jù)上面的電路圖,我想到了5個我認(rèn)為還比較簡單的方法(也許是我太自戀了,哈哈),那些位操作和單獨(dú)的總線操作的方法這里就不提了,實(shí)在是很笨的方法。
第一種方法:運(yùn)用總線操作的方法,但使用了循環(huán)操作的方式,大大減少了代碼的編寫。首先定義一個數(shù)組將8個總線數(shù)據(jù)存到數(shù)組中,用循環(huán)的方法給IO口賦值,之后延時保持led點(diǎn)亮,然后重新給IO口賦值,實(shí)現(xiàn)了led的流水顯示,具體請看代碼,不再解釋:
u_char table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void main(void)
{
u_char i;
while(1)
{
   for(i=0;i<8;i++)
   {
     P0=table[ i];
     delay();
   }
}
}
第二種方法:運(yùn)用了“移位”和“按位或”兩個操作,還不清楚這兩個操作的朋友該回去惡補(bǔ)C語言了。這是實(shí)現(xiàn)流水燈最常用的方法之一了,原理是先給IO口賦值(代碼中的temp),點(diǎn)亮第一個led,然后將數(shù)值左移一位,此時數(shù)值低兩位變成0,需要將最低位置1,所以又將數(shù)值與0x01按位或,循環(huán)8次執(zhí)行這個過程,實(shí)現(xiàn)了led的流水顯示,具體實(shí)現(xiàn)請看代碼:
void main(void)
{
u_char i;
while(1)
{
   u_char temp=0xfe;
   for(i=0;i<8;i++)
   {
     P0=temp;
     delay();
     temp=temp<<1;
     temp |= 0x01;
   }
}
}
第三種方法:相對于第二種方法在代碼上能簡單一點(diǎn),但是原理同出一轍,原理其一是二進(jìn)制數(shù)左移一位相當(dāng)于數(shù)值乘以2,右移一位相當(dāng)于數(shù)值除以2,原理其二是01按位或相當(dāng)于01。掌握了這兩個原理,那好的,方法二的程序順理成章的可以改成下面的這個程序,代碼如下:
void main(void)
{
u_char i;
while(1)
{
   u_char temp=0xfe;
   for(i=0;i<8;i++)
   {
     P0=temp;
     delay();
     temp=temp*2+1;
   }
}
}
第四種方法:也是運(yùn)用了移位的方法,但反其道而行之,使得代碼得到了一定簡化。這種方法數(shù)值temp給的是0x01,對它進(jìn)行移位操作,如果直接將其賦值給IO口,那么實(shí)現(xiàn)的效果是流水熄滅,這個效果很好,想想如果我對temp這個值取了一下反,再賦值給IO口,實(shí)現(xiàn)的是什么效果呢?請看代碼:
void main(void)
{
u_char i;
while(1)
{
   u_char temp=0x01;
   for(i=0;i<8;i++)
   {
    P0=~temp;
    delay();
    temp=temp<<1;
   }
}
}
第五種方法:我認(rèn)為很簡單,調(diào)用系統(tǒng)庫函數(shù)的循環(huán)移位函數(shù)實(shí)現(xiàn),需要注意的是在預(yù)編譯時需要包含頭文件。循環(huán)移位的好處是可以保持各位數(shù)值間的關(guān)系不變,因此整個過程只需要一個操作即可。這種方法雖然簡單,但是使用面不是很廣,因?yàn)槲覀兂3S洸蛔∠到y(tǒng)都有哪些庫函數(shù)可以用,所以對這種方法做以了解即可,程序代碼如下:
#include<reg52.h>
#include"intrins.h"
#define u_char unsigned char
#define u_int unsigned int
void delay(void);
void main(void)
{
u_char temp=0xfe;
while(1)
{
   P0=temp;
   delay();
   temp=_crol_(temp,1);
}
}
講到這里,五種方法實(shí)現(xiàn)流水燈已經(jīng)給大家介紹完了,相信大家已經(jīng)可以輕松自如的運(yùn)用上面的某一種方法實(shí)現(xiàn)流水燈了。其實(shí)單片機(jī)學(xué)起來,就是這么簡單,只要你喜歡,肯努力,一切so easy!
最后提一句,學(xué)習(xí)很重要的一點(diǎn)是舉一反三,舉個例子,現(xiàn)在你可以實(shí)現(xiàn)一個往返的流水燈了嗎?如果可以,很好,恭喜你已經(jīng)理解了!那么我們繼續(xù)加油!好了今天就到這里吧,再次歡迎大家拍磚,多提寶貴意見,感謝您的支持。
歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留以下信息:
文章出自:寶哥的博客
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表