前面一課掌握了嵌入式程序源代碼級(jí)調(diào)試,為復(fù)雜單片機(jī)實(shí)驗(yàn)程序的調(diào)試做好了準(zhǔn)備工作。本次實(shí)驗(yàn)完成流水燈電路模型設(shè)計(jì)和編程,在實(shí)驗(yàn)過(guò)程中,學(xué)習(xí)流水燈電路設(shè)計(jì)、編寫延遲函數(shù)、循環(huán)移位宏定義。
流水燈電路設(shè)計(jì)
本次實(shí)驗(yàn)設(shè)計(jì)要求通過(guò)單片機(jī)P0口實(shí)現(xiàn)流水燈控制電路,P0口8個(gè)端口外接8個(gè)LED,每個(gè)LED串聯(lián)一個(gè)200歐姆的限流電阻,8個(gè)限流電阻的公共端接5V直流電源。電路設(shè)計(jì)如下圖所示:
8個(gè)LED正極端通過(guò)串聯(lián)電阻接5V直流電源,負(fù)極端接P0端口,只要給P0端口一個(gè)低電平,就可以點(diǎn)亮LED,若需要熄滅LED,需要給P0端口一個(gè)高電平,要實(shí)現(xiàn)LED流水燈功能,只要將8個(gè)LED依次點(diǎn)亮、熄滅即可。
編寫時(shí)間延遲函數(shù)
流水燈電路要求LED依次點(diǎn)亮,每個(gè)LED要持續(xù)亮一段時(shí)間后熄滅。用程序來(lái)控制LED的點(diǎn)亮和熄滅,只需要將與LED連接的端口寫入低電平或高電平即可,代碼如下:
#include
void main()
{
P0 = 0xFF;
P0 = 0xFD;
}
上述代碼第1條語(yǔ)句將P0第0位寫入低電平,與第0位連接的lED被點(diǎn)亮,第2條語(yǔ)句將第0位寫入高電平,與第0位連接的lED熄滅。兩條語(yǔ)句連續(xù)執(zhí)行,每條語(yǔ)句的執(zhí)行時(shí)間非常短,也就十幾微秒,LED點(diǎn)亮后很快被熄滅,人們通過(guò)眼睛感覺不到LED被點(diǎn)亮。因此需要在第1條語(yǔ)句和第2條語(yǔ)句之間進(jìn)行時(shí)間延遲,延遲一段時(shí)間后再執(zhí)行第2條語(yǔ)句。
如何用軟件來(lái)模擬延時(shí)時(shí)間呢?在設(shè)計(jì)的電路模型中,51單片機(jī)的時(shí)鐘頻率是12MHZ,一個(gè)時(shí)鐘周期約0.08微秒,一個(gè)機(jī)器周期由12個(gè)時(shí)鐘周期構(gòu)成,一個(gè)機(jī)器周期約1微秒,51單片機(jī)執(zhí)行一個(gè)指令的時(shí)間是機(jī)器周期的倍數(shù),若使用for循環(huán)語(yǔ)句來(lái)實(shí)現(xiàn)時(shí)間延遲,一條基本的for循環(huán)語(yǔ)句執(zhí)行時(shí)間大約為8微秒,若延遲500毫秒,大約需要執(zhí)行500*120次循環(huán)。
// 時(shí)間延遲函數(shù)
void delay(unsigned int millisecond)
{
unsigned int i,j;
for(i=millisecond;i >0;i--)
for(j=120;j >0;j--);
}
delay()函數(shù)延遲millisecond毫秒,函數(shù)使用for嵌套循環(huán),外層for循環(huán)用于控制延遲的毫秒數(shù),內(nèi)層for循環(huán)用于控制1毫秒執(zhí)行的語(yǔ)句次數(shù)。
循環(huán)移位
流水燈需要在每個(gè)時(shí)間間隔內(nèi)只有一個(gè)LED點(diǎn)亮,其余LED均為熄滅狀態(tài),流水燈可以通過(guò)循環(huán)左移實(shí)現(xiàn)。循環(huán)左移是將操作數(shù)的二進(jìn)制位按1位進(jìn)行循環(huán)左移,移出的位并不會(huì)丟失,而是被后續(xù)移動(dòng)的位填充。
P0默認(rèn)值為0xFE,P0第0位的LED被點(diǎn)亮,其它位熄滅;延遲一段時(shí)間后,P0循環(huán)左移1位,其值為0xFD,P0第1位LED被點(diǎn)亮,其它位熄滅;延遲一段時(shí)間后,P0循環(huán)左移1位,其值為0xFB,P0第2位LED被點(diǎn)亮,其它位熄滅;以此類推,P0不斷循環(huán)左移1位,從而實(shí)現(xiàn)了流水燈控制。
C語(yǔ)言并沒有提供循環(huán)左移或循環(huán)右移的運(yùn)算功能,需要開發(fā)者自己編程實(shí)現(xiàn)。
循環(huán)左移位的具體算法如上圖所示:value為操作數(shù),其值為0xFE,先將value左移1位,賦值給變量a,其值為0xFC,然后將value右移7位,賦值給變量b,其值為0X1,最后計(jì)算a|b,計(jì)算結(jié)果為value循環(huán)左移1位,并將計(jì)算結(jié)果賦值為value。
流水燈算法實(shí)現(xiàn)代碼如下:
void main()
{
unsigned char value=0xfe,a,b;
unsigned char count = 0;
while(1)
{
P0 = value;
delay(5000);
a = value < < 1;
b = value > > 7;
value = a | b;
count += 1;
if( count >= 8 )
{
value = 0xfe;
count = 0;
}
}
}
算法通過(guò)while循環(huán)實(shí)現(xiàn)流水燈控制,在循環(huán)內(nèi)部,變量value賦值給P0,點(diǎn)亮第0位的LED,其它位的LED為熄滅狀態(tài),然后調(diào)用delay()函數(shù)延遲5000毫秒,value循環(huán)左移1位,在下輪循環(huán)中,點(diǎn)亮第1位的LED,其它位的LED為熄滅狀態(tài),以此類推……。
count為計(jì)數(shù)變量,當(dāng)流水燈循環(huán)點(diǎn)亮一次后,將value重新賦值為0xFE,并將conunt清零。
考慮到循環(huán)移位是經(jīng)常使用的操作,可以將循環(huán)左移位操作定義為宏,在代碼中直接調(diào)用宏就可以了。
循環(huán)左移位的宏定義:
#define ROTATE_LEFT(x) ((x) << 1) | ((x) >> 7 )
完整C程序代碼如下:
#include
#define ROTATE_LEFT(x) ((x) < < 1) | ((x) > > 7 )
void delay(unsigned int millisecond)
{
unsigned int i,j;
for(i=millisecond;i >0;i--)
for(j=120;j >0;j--);
}
void main()
{
unsigned char value=0xfe,count=0;
while(1)
{
P0 = value;
delay(5000);
value = ROTATE_LEFT(value);
count += 1;
if( count >= 8 )
{
value = 0xfe;
count = 0;
}
}
}
實(shí)驗(yàn)小結(jié)
通過(guò)這次實(shí)驗(yàn),掌握了流水燈的電路模型設(shè)計(jì)和編程,流水燈電路模型比較簡(jiǎn)單,單片機(jī)通過(guò)I/O口的8個(gè)端口來(lái)控制8個(gè)LED的點(diǎn)亮和熄滅。流水燈的控制通過(guò)編程實(shí)現(xiàn),編程主要涉及到時(shí)間延遲函數(shù)和循環(huán)左移位宏定義,時(shí)間延遲函數(shù)用于控制間LED點(diǎn)亮和熄滅的隔時(shí)間,循環(huán)左移位用于控制I/O口循環(huán)輸出高電平和低電平。
-
led
+關(guān)注
關(guān)注
242文章
23785瀏覽量
672361 -
單片機(jī)
+關(guān)注
關(guān)注
6067文章
44960瀏覽量
648770 -
嵌入式
+關(guān)注
關(guān)注
5145文章
19597瀏覽量
316136 -
電路設(shè)計(jì)
+關(guān)注
關(guān)注
6703文章
2534瀏覽量
213880 -
流水燈
+關(guān)注
關(guān)注
21文章
433瀏覽量
60401
發(fā)布評(píng)論請(qǐng)先 登錄

STM32單片機(jī)流水燈#電路設(shè)計(jì) #電子元器件 #電子工程師 #物聯(lián)網(wǎng)
基于單片機(jī)的流水燈介紹_51單片機(jī)流水燈的五種實(shí)現(xiàn)方法

單片機(jī)控制花樣流水燈原理圖及程序

基于單片機(jī)的簡(jiǎn)易流水燈實(shí)驗(yàn)設(shè)計(jì)方案

51單片機(jī)流水燈實(shí)驗(yàn)

單片機(jī)51的流水燈

51單片機(jī)流水燈制作

評(píng)論