專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

單片機(jī)流水燈設(shè)計(jì)方法

作者:mcu110   來(lái)源:51hei   點(diǎn)擊數(shù):  更新時(shí)間:2007年08月01日   【字體:

     這一課我們就結(jié)合at89sS51增強(qiáng)型單片機(jī)實(shí)驗(yàn)板、ISP編程器來(lái)手把手教你詳細(xì)學(xué)習(xí)單片機(jī)流水燈設(shè)計(jì)方法。購(gòu)買電路板聯(lián)系qq125739409

 

圖1:S51增強(qiáng)型單片機(jī)實(shí)驗(yàn)板


 

圖2: ISP編程器套件


  S51增強(qiáng)型單片機(jī)實(shí)驗(yàn)板上有8個(gè)高亮度發(fā)光二極管(見圖1所示),可以用來(lái)做單片機(jī)流水燈、跑馬燈。。。等實(shí)驗(yàn),電路原理圖見下圖3。

圖3單片機(jī)流水燈設(shè)計(jì)方法

  從原理圖可以看出,如果我們想讓接在P1.0口的LED1亮起來(lái),那么我們只要把P1.0口的電平變?yōu)榈碗娖骄涂梢粤耍幌喾,如果要接在P1.0口的LED1熄滅,就要把P1.0口的電平變?yōu)楦唠娖骄涂梢;同理,接在P1.1~P1.7口的其他7個(gè)LED的點(diǎn)亮和熄滅方法方法同LED1。因此,要實(shí)現(xiàn)流水燈功能,我們只要將LED2~LED8依次點(diǎn)亮、熄滅,依始類推,8只LED變會(huì)一亮一暗的做流水燈了。

  實(shí)現(xiàn)8個(gè)LED流水燈程序用中文表示為:P1.0低、延時(shí)、P1.0高、P1.1低、延時(shí)、P1.1高、P1.2低、延時(shí)、P1.2高、P1.3低、延時(shí)、P1.3高、P1.4低、延時(shí)、P1.4高、P1.5低、延時(shí)、P1.5高、P1.6低、延時(shí)、P1.6高、P1.7低、延時(shí)、P1.7高、返回到開始、程序結(jié)束。

  從上面中文表示看來(lái)實(shí)現(xiàn)單片機(jī)流水燈很簡(jiǎn)單,但是我們不能說P1.0你變低,它就變低了。因?yàn)閱纹瑱C(jī)聽不懂我們的漢語(yǔ)的,只能接受二進(jìn)制的“1、0......”機(jī)器代碼。我們又怎樣來(lái)使單片機(jī)按我們的意思去工作呢?為了讓單片機(jī)工作,只能將程序?qū)憺槎M(jìn)制代碼交給其執(zhí)行;早期單片機(jī)開發(fā)人員就是使用人工編寫的二進(jìn)制代碼交給單片機(jī)去工作的。今天,我們不必用煩人的二進(jìn)制去編寫程序,完全可以將我們?nèi)菀桌斫獾?ldquo;程序語(yǔ)言”通過“翻譯”軟件“翻譯”成單片機(jī)所需的二進(jìn)制代碼,然后交給單片機(jī)去執(zhí)行。這里的“程序語(yǔ)言”目前主要有匯編語(yǔ)言和C語(yǔ)言兩種;在這里我們所說的“翻譯”軟件,同行們都叫它為“編譯器”,將“程序語(yǔ)言”通過編譯器產(chǎn)生單片機(jī)的二進(jìn)制代碼的過程叫編譯。前面說到,要想使LED1變亮,只需將對(duì)應(yīng)的單片機(jī)引腳電平變?yōu)榈碗娖骄涂梢粤恕,F(xiàn)在讓我們將上面提到的8只LED流水燈實(shí)驗(yàn)寫為匯編語(yǔ)言程序。

實(shí)現(xiàn)8個(gè)LED流水燈匯編語(yǔ)言源程序 liu01.asm
 

    ;----- 主程序開始 -----
START: CLR   P1.0       ;P1.0輸出低電平,使LED1點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.0       ;P1.0輸出高電平,使LED1熄滅
    CLR   P1.1       ;P1.1輸出低電平,使LED2點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.1       ;P1.1輸出高電平,使LED2熄滅
    CLR   P1.2       ;P1.2輸出低電平,使LED3點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.2       ;P1.2輸出高電平,使LED3熄滅
    CLR   P1.3       ;P1.3輸出低電平,使LED4點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.3       ;P1.3輸出高電平,使LED4熄滅
    CLR   P1.4       ;P1.4輸出低電平,使LED5點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.4       ;P1.4輸出高電平,使LED5熄滅
    CLR   P1.5       ;P1.5輸出低電平,使LED6點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.5       ;P1.5輸出高電平,使LED6熄滅
    CLR   P1.6       ;P1.6輸出低電平,使LED7點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.6       ;P1.6輸出高電平,使LED7熄滅
    CLR   P1.7       ;P1.7輸出低電平,使LED8點(diǎn)亮
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    SETB  P1.7       ;P1.7輸出高電平,使LED8熄滅
    ACALL  DELAY      ;調(diào)用延時(shí)子程序
    AJMP  START      ;8個(gè)LED流了一遍后返回到標(biāo)號(hào)START處再循環(huán)

    ;----- 延時(shí)子程序 -----
DELAY: MOV   R0,#255     ;延時(shí)一段時(shí)間
D1:   MOV   R1,#255
    DJNZ  R1,$
    DJNZ  R0,D1
    RET            ;子程序返回

    END           ;程序結(jié)束

 

  在上面主程序中用到了五條匯編語(yǔ)言指令:CLR、ACALL、SETB、LJMP、END。

  CLR: 是將其后面指定的位清為0,程序中使對(duì)應(yīng)端口輸出低電平
  ACALL:是子程序調(diào)用指令,程序中調(diào)用了DELAY延時(shí)子程序
  SETB:是將其后面指定的位置成1,程序中使對(duì)應(yīng)端口輸出高電平
  AJMP:是無(wú)條件跳轉(zhuǎn)指令,意思是:跳轉(zhuǎn)到指定的標(biāo)號(hào)處繼續(xù)運(yùn)行
  END: 是程序結(jié)束的偽指令,意思是告訴編譯器,程序到此結(jié)束。偽指令只告訴編譯器此程序到此有何要求或條件,它不參與和影響程序的執(zhí)行。

  在上面源程序中"ACALL  DELAY"指令的作用是調(diào)用DELAY延時(shí)子程序。為什么要使用這指令呢?如果不用該指令能夠?qū)崿F(xiàn)"流水"效果嗎?答案是肯定的,一定要用該指令才能看到我們需要的"流水"效果。如果不用該指令,則由于8個(gè)LED發(fā)光與熄滅的時(shí)間都很短,我們?nèi)庋蹮o(wú)法看到LED的熄滅與點(diǎn)亮,憑我們?nèi)庋劭吹降氖荓ED1~LED8都同時(shí)亮(半亮),而看不到“流水”效果的!注:初學(xué)者可以將上面源程序中所有"ACALL  DELAY"指令行刪除后再編譯后燒寫到單片機(jī)進(jìn)行驗(yàn)證一下。

  產(chǎn)生這種現(xiàn)象主要是因?yàn)閱纹瑱C(jī)執(zhí)行每條指令的時(shí)間很短,我們知道實(shí)驗(yàn)板上單片機(jī)的時(shí)鐘高達(dá)11.0592MHz,在這個(gè)時(shí)鐘信號(hào)(即晶體振蕩信號(hào))下,一個(gè)“機(jī)器周期”僅大約1.08uS(微秒)。本程序中我們用到的SETB P.x和CLR P.x均屬于單周期指令,也就是說,執(zhí)行一句 SETB P.x 用時(shí)僅1.08uS(微秒),CLR P.x 也是1.08uS(微秒);也就是點(diǎn)亮和熄滅時(shí)間都為1.08uS(微秒),在如此高速的流水速度下,8個(gè)LED發(fā)光與熄滅的時(shí)間都很短,當(dāng)然憑我們的肉眼看不到“流水”效果了!

  這里需要說明的是,按匯編語(yǔ)法要求,所編制的程序(下稱源程序)之格式和書寫要求必須依下列原則:
  1、源程序必須為純文本格式文件,如用Windows“附件”中的“記事本”編寫的文本文件或用UltraEdit文本編輯器編輯;
  2、源程序的擴(kuò)展名應(yīng)是 *.ASM;
  3、一行只能寫一條語(yǔ)句,以回車作為本句的結(jié)束,每一語(yǔ)句行長(zhǎng)度應(yīng)少于80個(gè)字符(即40個(gè)漢字)。
  4、每行的格式應(yīng)為:標(biāo)號(hào): 命令 參數(shù) ;注釋 。即一行由四部份組成,各部份的順序不能搞錯(cuò),依實(shí)際要求可以缺省其中的一部份或幾部份,甚至全部省去,即空白行。需要使用標(biāo)號(hào)時(shí)標(biāo)號(hào)后面必須有“:”(冒號(hào)),而命令語(yǔ)句和參數(shù)之間必須用空格分開,如果命令有多個(gè)參數(shù),則參數(shù)與參數(shù)之間必須用“,”(逗號(hào))分開,需要注釋時(shí)注釋前必須用“;”(分號(hào)),“;”后面的語(yǔ)句可以寫任何字符,包括漢字用于解釋前面的匯編語(yǔ)句,它將不參與匯編,不生成代碼。由于匯編程序?qū)ξ覀冞不直觀,所以在編寫源程序時(shí),應(yīng)當(dāng)養(yǎng)成多寫注釋的習(xí)慣,這樣有助于今后源程序的閱讀和維護(hù)。

  標(biāo)號(hào)是標(biāo)志程序中某一行的符號(hào)名,編譯后標(biāo)號(hào)的數(shù)值就是標(biāo)號(hào)所在行代碼的地址。在宏匯編ASM51中標(biāo)號(hào)的長(zhǎng)度不受限制,但標(biāo)號(hào)中不能包含‘:'或其它的一些特殊符號(hào),也不能用漢字,可以用數(shù)字作標(biāo)號(hào),但必須用字母開頭。當(dāng)標(biāo)號(hào)作參數(shù)用(如標(biāo)號(hào)作轉(zhuǎn)移地址),在命令后面出現(xiàn)時(shí),必須舍去‘:'(如上面程序中的 AJMP START中的START是不能再有:)。每行只能有一個(gè)標(biāo)號(hào),一個(gè)標(biāo)號(hào)只能用在一處,如果有兩行用了同一個(gè)標(biāo)號(hào),則匯編時(shí)就會(huì)出錯(cuò)。由于標(biāo)號(hào)的長(zhǎng)度沒有限制,可以用有意義的英文或漢語(yǔ)拼音來(lái)說明行,使源程序讀起來(lái)更方便。在源程序中的字母不區(qū)分大小寫,也就是說 start 和 START 是一樣的,請(qǐng)不要用大小寫方式去區(qū)分不同的標(biāo)號(hào)。

  好啦!我們知道了匯編語(yǔ)言程序的規(guī)則,現(xiàn)在就動(dòng)手編輯源程序吧。馬上啟動(dòng)Keil單片機(jī)集成開發(fā)環(huán)境,建立新工程liu01.UV2,將上面的源程序liu01.asm導(dǎo)入到工程中,設(shè)置好Keil工程的編譯參數(shù),編譯得到HEX格式的目標(biāo)文件liu01.hex,用 ISP編程器 將目標(biāo)文件liu01.hex燒寫到AT89S51單片機(jī)中,接下來(lái)就是將燒寫好的AT89S51從編程器上取下,放到“ S51增強(qiáng)型單片機(jī)實(shí)驗(yàn)板 ”上通電,我們就看到了LED1~LED8的"流水"效果了。

圖4: ISP編程器燒寫目標(biāo)文件liu01.hex

  到此,我們做的流水燈已成功,工作原理也清楚啦,若你完全掌握了上面程序,那么你就可以將“流水燈”的流向改變一下,可以將從"左向右流"改為從"右向左流",也可以改為"兩邊向內(nèi)流"、"內(nèi)部向外流"......,我想你一定能用前面學(xué)到的方法實(shí)現(xiàn)這些功能。可能有些高手說,前面的編程方法是最最笨的!不錯(cuò)!但初學(xué)單片機(jī)初期可以不必講究語(yǔ)言的簡(jiǎn)練,只要能實(shí)現(xiàn)預(yù)先要求就好,最主要的是學(xué)好基本指令(111條)的用法,清楚各個(gè)指令的功能,這是初學(xué)者要知道的。那么還有更好的編程思路嗎?當(dāng)然有!請(qǐng)跟隨站長(zhǎng)繼續(xù)學(xué)習(xí)下面的內(nèi)容。

  在前面學(xué)習(xí)的程序中我們讓LED流水是去逐個(gè)控制P1端口的每個(gè)位來(lái)實(shí)現(xiàn)的,因此程序顯得有點(diǎn)復(fù)雜,下面我們就采用新的思路來(lái)編程。新的編程思路如下:我們?cè)诔绦蛞婚_始就給P1口送一個(gè)數(shù),這個(gè)數(shù)本身就讓P1.0先低,其他位為高,然后讓這個(gè)數(shù)據(jù)向高位移動(dòng)不就實(shí)現(xiàn)“流水”效果啦?的確如此!8051指令中沒有讓P1數(shù)據(jù)移動(dòng)的指令,但有對(duì)累加器ACC中數(shù)據(jù)左移或右移的指令,ACC在指令中常寫為A,累加器A數(shù)據(jù)左移指令為"RL A",累加器數(shù)據(jù)右移指令為"RR A",累加器在數(shù)據(jù)傳輸和數(shù)據(jù)處理過程中作用十分重要,累加器ACC為8位。他可與片內(nèi)所有單字節(jié)寄存器交換數(shù)據(jù),實(shí)際上P1和其他端口在單片機(jī)中也是一個(gè)寄存器。這樣我們可以將需移動(dòng)的數(shù)據(jù)先放到ACC中,讓其移動(dòng),然后將ACC移動(dòng)后的數(shù)據(jù)再轉(zhuǎn)送到P1口,這樣同樣可以實(shí)現(xiàn)“流水”效果。下面程序就是采用新的編程思路源程序liu02.asm。

實(shí)現(xiàn)8個(gè)LED流水燈匯編語(yǔ)言程序 liu02.asm
 

    ;----- 主程序開始 -----
START: MOV   ACC,#0FEH   ;ACC中先裝入LED1亮的數(shù)據(jù)(二進(jìn)制的11111110)
    MOV   P1,ACC     ;將ACC的數(shù)據(jù)送P1口
    MOV   R0,#7     ;將數(shù)據(jù)再移動(dòng)7次就完成一個(gè)8位流水過程
LOOP:  RL   A       ;將ACC中的數(shù)據(jù)左移一位
    MOV   P1,A      ;把ACC移動(dòng)過的數(shù)據(jù)送p1口顯示
    ACALL  DELAY     ;調(diào)用延時(shí)子程序
    DJNZ  R0,LOOP    ;沒有移動(dòng)夠7次繼續(xù)移動(dòng)
    AJMP  START     ;移動(dòng)完7次后跳到開始重來(lái),以達(dá)到循環(huán)流動(dòng)效果

    ;----- 延時(shí)子程序 -----
DELAY: MOV   R0,#255    ;延時(shí)一段時(shí)間
D1:   MOV   R1,#255
    DJNZ  R1,$
    DJNZ  R0,D1
    RET          ;子程序返回

    END          ;程序結(jié)束

 

  接下來(lái),我們將上述程序編譯,并燒寫到實(shí)驗(yàn)芯片中,放到實(shí)驗(yàn)板上可以看到程序的"流水"效果是一樣的,但源程序看起來(lái)更加簡(jiǎn)潔,直觀。其實(shí)8051單片機(jī)有111條指令,有的指令常用,有的指令不常用,只要遵守語(yǔ)法規(guī)則,你可以用這些指令“組合”成你想象到的任何程序。當(dāng)然,有時(shí)一條指令可以替代很多條指令,這樣會(huì)使程序簡(jiǎn)潔,程序代碼減少,在編寫較大程序時(shí)可以讓程序存儲(chǔ)器放得下你需要的代碼,這也是單片機(jī)高手所追求的“程序簡(jiǎn)潔高效”。當(dāng)然,初學(xué)者不必刻意去追求程序的簡(jiǎn)潔高效,主要是要全面地掌握各種指令的應(yīng)用,只要你對(duì)基本指令都熟悉了,那么你也就可以編出簡(jiǎn)潔高效的程序了,不過這編程“內(nèi)功”是需要你勤學(xué)苦練,日積月累的練習(xí)、實(shí)驗(yàn)才能達(dá)到的哦!馬上拿起你的實(shí)驗(yàn)板,現(xiàn)在就開始動(dòng)手吧:)

  上面我們學(xué)習(xí)的兩個(gè)程序都是比較簡(jiǎn)單的流水燈程序,"流水"花樣只能實(shí)現(xiàn)單一的"從左到右"流方式。下面介紹一個(gè)實(shí)用的流水燈程序,程序能夠?qū)崿F(xiàn)任意方式流水,而且流水花樣無(wú)限,只要更改流水花樣數(shù)據(jù)表的流水?dāng)?shù)據(jù)就可以隨意添加或改變流水花樣,真正實(shí)現(xiàn)隨心所欲的流水。只要將下面的程序稍稍修改一下,通過S51增強(qiáng)型單片機(jī)實(shí)驗(yàn)板的擴(kuò)展接口連接到霓虹燈高壓驅(qū)動(dòng)接口板就可以驅(qū)動(dòng)真正的霓虹燈了。

實(shí)用的查表方式多功能流水燈程序 liu03.asm
 

    ;----- 主程序開始 -----
    ORG   0000H       ;上電復(fù)位,程序從0000H開始執(zhí)行
START: MOV   SP,#60H      ;堆棧初始化為60H
    MOV   DPTR,#LIU_TAB   ;流水花樣表首地址送DPTR
LOOP:  CLR   A
    MOVC  A,@A+DPTR
    CJNE  A,#0FFH,SHOW   ;檢查流水結(jié)束標(biāo)志
    AJMP  START       ;所有花樣流完,則從頭開始重復(fù)流
SHOW:  MOV   P1,A       ;將數(shù)據(jù)送到P1口
    ACALL  DELAY
    INC   DPTR
    AJMP  LOOP

    ;----- 延時(shí)子程序 -----
DELAY: MOV   R0,#255     ;延時(shí)一段時(shí)間
D1:   MOV   R1,#255
    DJNZ  R1,$
    DJNZ  R0,D1
    RET            ;子程序返回

 

    ;----- 下面是流水花樣數(shù)據(jù)表 -----
LIU_TAB:
    DB 01111111B       ;二進(jìn)制表示的流水花樣數(shù)據(jù)
    DB 10111111B
    DB 11011111B
    DB 11101111B
    DB 11110111B
    DB 11111011B
    DB 11111101B
    DB 11111110B
    DB 11111110B
    DB 11111101B
    DB 11111011B
    DB 11110111B
    DB 11101111B
    DB 11011111B
    DB 10111111B
    DB 01111111B
    DB 7FH,0BFH,0DFH,0EFH,0F7H,0FBH,0FDH,0FEH ;十六進(jìn)制表示
    DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,7FH
    DB 7EH,0BDH,0DBH,0E7H,0E7H,0DBH,0BDH,7EH
    DB 7FH,3FH,1FH,0FH,07H,03H,01H,00H
    DB 0FFH          ;流水花樣結(jié)束標(biāo)志0FFH

    END           ;程序結(jié)束

 
關(guān)閉窗口

相關(guān)文章