新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 用AT89C51實現(xiàn)自設(shè)定時間控制

用AT89C51實現(xiàn)自設(shè)定時間控制

作者: 時間:2011-02-21 來源:網(wǎng)絡(luò) 收藏

  本期教程用一個可以人工設(shè)置控制時間、實現(xiàn)電器定時開關(guān)的小系統(tǒng),詳細講解數(shù)據(jù)顯示代碼轉(zhuǎn)換,簡單介紹一下中斷原理的應(yīng)用及相關(guān)指令等問題。

一、本系統(tǒng)實現(xiàn)的功能

  本系統(tǒng)由AT89C51、LED數(shù)碼管、按鍵、訊響器等部分構(gòu)成,能實現(xiàn)計時時間的調(diào)整、控制時間的設(shè)定,對負載實現(xiàn)開關(guān)控制以及秒信號“嘀嗒”聲提示等功能。系統(tǒng)的功能選擇由SB1、SB2、SB3完成。SB1為功能切換鍵。第一輪按動SB1進入負載開關(guān)時間設(shè)置程序,接下來按動此鍵,依次進入“時”十位調(diào)整、“時”個位調(diào)整、 “分”十位調(diào)整、“分”個位調(diào)整和負載開關(guān)設(shè)置狀態(tài)。第二輪按動SB1是負載開關(guān)時間上、下限設(shè)置。第三輪按動SB1進入計時時間調(diào)整。不管是進入那種狀態(tài),按動SB2皆可以使被調(diào)整位進行不進位增量變化。各預(yù)置量設(shè)置完成后,可按動SB3 確認,系統(tǒng)將所有的設(shè)置存入RAM中,立刻進入計時程序。上電后,系統(tǒng)自動進入計時狀態(tài),起始于“00”時“00”分。秒數(shù)字不顯示,而是以一種模擬傳統(tǒng)機械表的運行節(jié)奏,發(fā)出清脆的“嘀嗒”聲做秒信號指示。本系統(tǒng)可將計時誤差縮小至每日±0.18s。

二、電原理

1. 顯示原理

  電原理圖見圖1。P0口的8條數(shù)據(jù)線P0.0 至P0.7 分別與LED數(shù)碼管的a、b、c、d、e、f、g、dp字段相接,P2口的 P2.7至P2.4分別通過電阻R10至R13與VT1至VT4的基極相連接。這樣通過P0 口送出顯示代碼,通過P2口送出掃描選通代碼輪流點亮LED1至LED4,就會將要顯示的數(shù)據(jù)在數(shù)碼管中顯示出來。從P0口輸出的代碼就是段選碼,從P2口輸出的就是位選碼。掃描顯示原理與上期的“活動字符顯示屏”相似。

2. 數(shù)碼管結(jié)構(gòu)及代碼顯示

  共陰LED數(shù)碼管結(jié)構(gòu)、字段及引腳排列見圖2(a),電原理見圖2(b)。

  由圖可知,共陰LED數(shù)碼管由8只發(fā)光二極管VD1至VD8共陰連接并按“8”字形結(jié)構(gòu)排列而成。這樣,我們將這些二極管的正極接高低不同的電位,把所有的負極接地,當正極為高電位時相應(yīng)的二極管就會導通而發(fā)光,從而使數(shù)碼管呈現(xiàn)不同的字符。比如,我們將數(shù)碼管的a、c、d、f、g端接高電位,將GND端接低電位,VD1、VD3、VD4、VD6和VD7就會發(fā)光,數(shù)碼管的 a、c、d、f、g字段就會被點亮,數(shù)碼管即顯示出“5”字,在圖1中,數(shù)碼管的a、 b、c、d、e、f、g、dp引腳分別與P0口的P0.0至P0.7相連接。若執(zhí)行MOV P0,#6DH和MOV P2,#80H,P2口輸出的位選碼是“1000 0000B”,只有P2.7呈現(xiàn)高電位,VT1導通,LED1的GND與地相接,LED1位被選中因而具備發(fā)光的使能條件;P0口的段選碼是0110 1101B”,P0.0、P0.2、P0.3、P0.5、P0.6呈現(xiàn)高電位,數(shù)碼管的a、c、d、 f、g字段被點亮,LED1就顯示出“5”字,而LED2至LED4則不會被點亮??梢姡诶肞2口送出位選碼,使各位輪流得到發(fā)光使能條件的同時,通過P0口分別送出不同的段選碼,就會在LED1至LED4中顯示出不同的數(shù)字來。

三、程序設(shè)計思想和相關(guān)指令介紹

  本系統(tǒng)的主程序主要完成時間控制和按鍵判斷功能。而掃描、計時、顯示和發(fā)聲等功能全部在中斷服務(wù)程序中完成。因此,主程序?qū)⑼瓿砂存I判斷、時間判斷等功能,而中斷服務(wù)程序中有代碼轉(zhuǎn)換及查表子程序、掃描子程序、計時子程序、顯示子程序和發(fā)聲子程序。

1.數(shù)據(jù)與代碼轉(zhuǎn)換及查表程序

  由前述可知,從P2口輸出位選碼,從P0口輸出段選碼,LED就會顯示出數(shù)字來。但P0口的段選碼和要顯示的數(shù)據(jù),也就是顯示出的字符表達的含義是不一致的??梢姡珻PU將要顯示的數(shù)據(jù)直接送到P0口去驅(qū)動LED數(shù)碼管顯示是不能正確表達的,必須在系統(tǒng)內(nèi)部將要顯示的數(shù)據(jù)經(jīng)過顯示代碼進行轉(zhuǎn)換后,將數(shù)據(jù)的段選代碼送入P0口,使數(shù)碼管顯示出正確的數(shù)據(jù)表達符,才能被準確識讀。

  要顯示的數(shù)據(jù)與其段選碼的轉(zhuǎn)換,可以用一段簡單的程序來實現(xiàn),我們將所有需要顯示的數(shù)據(jù)的顯示代碼放在一起組成代碼表,使數(shù)據(jù)與其顯示代碼有一個準確的對應(yīng)關(guān)系,以便查找轉(zhuǎn)換。如附表所示,我們將0至9這10個數(shù)字的段選碼存到RAM 的70H至79H之中,利用一條間接尋址命令,就能很方便地實現(xiàn)顯示數(shù)據(jù)與其段選碼之間的轉(zhuǎn)換。

  具體轉(zhuǎn)換過程如下:

  我們先將要顯示的數(shù)據(jù)裝入累加器A中,再將A中的數(shù)據(jù)加上立即數(shù)#70H,再放回A中,然后將A中的值,放入間址寄存器R0中,這便得到了存放該數(shù)據(jù)段選碼的存儲地址,取出該單元內(nèi)的內(nèi)容,就得到了正確的顯示代碼,這個過程就是查表轉(zhuǎn)換數(shù)據(jù)顯示代碼的過程。比如:我們要將“#05H”送LED顯示,執(zhí)行MOV A,#05H和ADD A,#70H,再執(zhí)行MOV R0,A,結(jié)果是使R0中的值為#75H,這就得到了存放數(shù)據(jù)#05的段選碼的存儲單元地址,利用一條間接尋址指令,MOV P0,@R0,就將75H中的數(shù)據(jù)#05H的段選碼#6DH送到了P0口中,于是“5”字就在LED中顯示出來。

  在該系統(tǒng)中,我們用LED1和LED2顯示“時”,用LED3和LED4顯示“分”,并將“時”、“分”數(shù)據(jù)轉(zhuǎn)換后的段選碼存于片內(nèi)RAM的24H到27H組成的顯示緩存區(qū)之中,利用掃描程序,將4個單元的內(nèi)容送LED1至LED4中顯示出來。

2.計時功能的實現(xiàn)與中斷服務(wù)程序

  作為時間控制系統(tǒng),一定要保證在完成有關(guān)操作,比如掃描顯示、按鍵狀態(tài)檢測、秒信號“嘀嗒”提示聲輸出等的同時,保證計時正常進行,這樣,一定要一邊進行操作,一邊計算時間,當滿1秒或一個更大或更小的計時單位時,及時地完成進位,并及時修改顯示緩存區(qū)的段選碼。上述過程,用中斷來實現(xiàn)是最方便的。

  明白了重裝定時方式的中斷,計時功能的實現(xiàn)就容易理解了,我們將一些運行時間確定的程序統(tǒng)統(tǒng)放到中斷服務(wù)程序中,如掃描、顯示、“嘀嗒”提示聲等功能子程序,然后再加上定時器定時時間,這樣每次中斷所需時間就是中斷程序的運行時間與定時器溢出時間之和,它是個固定的值,即計時單位。因此,系統(tǒng)的計時就可以做得很準確,而在中斷之外的主程序,則可以隨便安放一些諸如按鍵判斷等時間不確定的隨機事件處理程序。整個中斷程序運行時間與定時器溢出時間之和是 1s。這樣,當完成60次定時中斷,即為1分鐘,主程序就以此為基本計時單位進行計時顯示操作。

  進入中斷服務(wù)程序以后,執(zhí)行CLR TR0將定時器0關(guān)閉,執(zhí)行PUSH PSW和PUSH A將程序狀態(tài)寄存器PSW的內(nèi)容和累加器A中的數(shù)據(jù)保存起來,這便是所謂的“保護現(xiàn)場”;之后,先調(diào)秒信號“嘀嗒”聲子程序,完成機械表運行節(jié)奏的模擬,再調(diào)查表子程序?qū)r間數(shù)據(jù)區(qū)20H~23H的數(shù)據(jù)經(jīng)譯碼后存入顯示緩存區(qū) 24H~27H內(nèi),然后反復(fù)進行掃描顯示;當進入中斷連續(xù)掃描至999.526ms時,停止掃描,執(zhí)行POP A和POP PSW 指令,將保護現(xiàn)場時存起來的數(shù)據(jù)重新送回到累加器A中和程序狀態(tài)寄存器PSW中,恢復(fù)現(xiàn)場,再執(zhí)行SETB TR0,開啟定時器/計數(shù)器0,使之開始計時,然后返回主程序。自停止掃描到中斷返回,執(zhí)行了5條單機器周期指令,共用時間10μs,這樣,整個中斷的總時間為999.536ms,由于定時器/計數(shù)器0的定時時間為464μs,所以,定時時間與中斷服務(wù)程序運行時間之和恰為1s,也就是說每次中斷用時1s,這樣,每次中斷,將秒計數(shù)存儲單元內(nèi)的數(shù)加1 ,就可得計時秒數(shù),然后根據(jù)進率,得到時、分的值,并將時、分值經(jīng)譯碼后,通過掃描程序送LED中顯示出來。秒的累加是用指令I(lǐng)NC來實現(xiàn)的。

  用以保護現(xiàn)場和恢復(fù)現(xiàn)場時存取關(guān)鍵數(shù)據(jù)的存儲區(qū)叫做堆棧。在軟件的控制之下,堆??稍谄瑑?nèi)RAM中的任一區(qū)間設(shè)定,而堆棧的數(shù)據(jù)存取與一般的RAM存取又有區(qū)別,對它的操作,要遵循“后進先出”的原則。堆棧的設(shè)定和堆棧的讀寫操作,主要靠一個特殊寄存器SP來完成,SP謂之堆棧指針,對堆棧的操作,其被操作數(shù)存儲單元的地址是由SP中的內(nèi)容決定的。如 MOV SP,#2FH指令,能使SP中的內(nèi)容修改為#2FH,2FH單元稱之為“棧底”。這樣當執(zhí)行堆棧的寫操作時,被操作數(shù)將從片內(nèi)RAM的30H開始存放。在中斷程序中為了保護現(xiàn)場,使用了PUSH指令,該指令是將被保護的數(shù)據(jù)存于堆棧的指令,利用該指令完成的操作叫做壓棧。當棧底為2FH時,CPU執(zhí)行PUSH PSW指令時,SP首先加1,使其中的值改為#30H,然后再將程序狀態(tài)寄存器PSW中的數(shù)據(jù)存到RAM的30H單元之中,接著執(zhí)行PUSH A,累加器A中的數(shù)據(jù)便被送到了31H之中,我們稱31H為此時的棧頂。相反的,POP指令是將堆棧棧頂?shù)臄?shù)據(jù)送回指定地址的指令,我們稱之為出棧指令,執(zhí)行結(jié)果是將棧頂?shù)臄?shù)據(jù)送到直接地址的存儲單元中,并將SP中內(nèi)容減 1,建立新棧頂。如前述,棧頂為31H,也就是說SP中的值為#31H,此時執(zhí)行POP A指令,CPU先將31H單元內(nèi)的數(shù)據(jù)送到累加器A中,再將SP中的值減1,使之變成 #30H,此時棧指針SP必指向30H,新的棧頂也便是30H,然后執(zhí)行POP PSW,30H中的數(shù)據(jù)又被送到了PSW之中。由于SP具備在壓棧時使棧頂逐一上升,在出棧時使棧頂逐一下降的功能,才使棧操作具有“后進先出”的特征。所以,在中斷程序的設(shè)計中,出棧數(shù)據(jù)的目的地址和壓棧數(shù)據(jù)的源地址要嚴格對應(yīng),還必須遵循“后進先出”原則。

3.時間控制功能與比較指令

  系統(tǒng)的另一功能就是實現(xiàn)對執(zhí)行設(shè)備的定時開關(guān)控制,其主要控制思想是這樣的:先將執(zhí)行設(shè)備開啟的時間和關(guān)閉時間置入RAM某一單元,在計時主程序當中執(zhí)行幾條比較指令,如果當前計時時間與執(zhí)行設(shè)備的設(shè)定開啟時間相等,就執(zhí)行一條 CLR P1.7指令,將P1 .7置為低電位,使光耦可控硅K導通,負載L開啟;如果當前計時時間與執(zhí)行設(shè)備設(shè)定的關(guān)閉時間相等,就執(zhí)行SETB P1.7,將P1.7置高電位,光耦可控硅K截止,負載L關(guān)閉。實現(xiàn)此控制功能用到的比較指令為CJNE A,#direct,rel,其轉(zhuǎn)移條件是累加器A中的值與立即數(shù)不等則轉(zhuǎn)移。

四、程序清單 

ORG 0000

地址 機器碼 指令 注釋

0000 02003B LJMP 003b ;跳轉(zhuǎn)至003B

ORG 000b

地址 機器碼 指令 注釋

000B 020100 LJMP 0100 ;跳轉(zhuǎn)至0100

ORG 003b

地址 機器碼 指令 注釋

003B 752000 MOV 20H,#00H ;初始化

003E 752100 MOV 21H,#00H ;

0041 752200 MOV 22H,#00H ;

0044 752300 MOV 23H,#00H ;

0047 75B0FF MOV P3,#FFH ;

004A 7590BF MOV P1,#BFH ;

004D C291 CLR P1.1 ;

004F D296 SETB P1.6

0051 D297 SETB P1.7 ;

0053 75803F MOV P0,#3FH ;

0056 75A00F MOV P2,#0FH ;

0059 75812F MOV SP,#2FH ;修改棧指針

005C 75703F MOV 70H,#3FH ;裝字形代碼

005F 757106 MOV 71H,#06H ;

0062 75725B MOV 72H,#5BH ;

0065 75734F MOV 73H,#4FH ;

0068 757466 MOV 74H,#66H ;

006B 75756D MOV 75H,#6DH ;

006E 75767D MOV 76H,#7DH ;

0071 757707 MOV 77H,#07H ;

0074 75787F MOV 78H,#87H ;

0077 75796F MOV 79H,#6FH ;

007A 756001 MOV 60H,#01H ;設(shè)定負載開啟時間

007D 756108 MOV 61H,#08H ;

0080 756203 MOV 62H,#03H ;

0083 756408 MOV 64H,#08H ;設(shè)定負載關(guān)閉時間

0086 756500 MOV 65H,#00H ;

0089 756601 MOV 66H,#01H ;

008C 00 NOP ;備用字節(jié),可安放判鍵

008D 00 NOP ;設(shè)置程序引導指令

008E 00 NOP ;

008F 00 NOP ;

0090 7C00 MOV R4,#00H ;計時程序

0092 75B802 MOV IP,#02H ;設(shè)定定時器0高優(yōu)先級

0095 758902 MOV TMOD,#02H ;定時器0工作于模式2 0098 75A882 MOV IE,#82H ;設(shè)定中斷允許

009B 758C18 MOV TL1,#18H ;設(shè)定定時重裝載值

009E D28C SETB TR0, ;開啟定時器0

00A0 BC3CFD CJNE R4,#3CH,00A0;判斷秒累計數(shù)

00A3 7C00 MOV R4,#00H ;清秒累計寄存器

00A5 0523 INC 23H ;分個位加1

00A7 E520 MOV A,20H ;負載開時間判斷

00A9 B5600C CJNE A,60H,00B8;

00AC E521 MOV A,21H ;

00AE B56107 CJNE A,61H,00B8;

00B1 E522 MOV A,22H ;

00B3 B56202 CJNE A,62H,00B8;

00B6 C297 CLR P1.7 ;接通負載

00B8 E520 MOV A,20H ;負載關(guān)時間判斷

00BA B5640C CJNE A,64H,00C9;

00BD E521 MOV A,21H ;

00BF B56507 CJNE A,65H,00C9;

00C2 E522 MOV A,22H ;

00C4 B56602 CJNE A,66H,00C9;

00C7 D297 SETB P1.7 ;關(guān)閉負載

00C9 E523 MOV A,23H ;計時進位處理

00CB B40AD2 CJNE A,#0A,00A0;

00CE 752300 MOV 23H,#00H ;

00D1 0522 INC 22H ;

00D3 E522 MOV A,22H ;

00D5 B406D8 CJNE A,#06,00B0;

00D8 752200 MOV 22H,#00H ;

00DB 0521 INC 21H ;

00DD E520 MOV A,20H ;

00DF B4020E CJNE A,#02,00F0;

00E2 E521 MOV A,21H ;

00E4 B404C9 CJNE A,#04,00B0;

00E7 752100 MOV 21H,#00H ;

00EA 752000 MOV 20H,#00H ;

00ED 0200A0 LJMP 00A0 ;

00F0 E521 MOV A,21H ;

00F2 B40ABB CJNE A,#0A,00B0;

00F5 752100 MOV 21H,#00H ;

00F8 0520 INC 20H ;

00FA 0200A0 LJMP 00A0 ;

00FD 00 NOP ;

00FE 00 NOP ;

00FF 00 NOP ;定時中斷子程序

0100 C28C CLR TR0 ;關(guān)閉定時器0

0102 C0D0 PUSH PSW ;將PSW內(nèi)容壓入棧中

0104 C0E0 PUSH ACC ;將A的內(nèi)容壓棧中

0106 7F30 MOV R7,#30H ;設(shè)掃描常數(shù)

0108 12017D LCALL 017D ;調(diào)“嘀嗒”聲子程序

010B 120174 LCALL 0174 ;調(diào)快慢調(diào)整子程序

010E 120120 LCALL 0120 ;調(diào)查表譯碼顯示子程序0111 DFFB DJNZ R7,010E ;

0113 0C INC R4 ;

0114 D0E0 POP ACC ;出棧

0116 D0D0 POP PSW ;

0118 D28C SETB TR0 ;開計時器0

011A 32 RETI ;中斷返回

011B 00 NOP ;備用字節(jié)

011C 00 NOP ;

011D 00 NOP ;

011E 00 NOP ;

011F 00 NOP ;

0120 7A70 MOV R2,#70H ;查表譯碼顯示子程序

0122 E520 MOV A,20H ;時十位譯碼

0124 2A ADD A,R2 ;

0125 F8 MOV R0,A ;

0126 8624 MOV 24H,@R0

0128 7A70 MOV R2,#70H ;時個位譯碼

012A E521 MOV A,21H ;

012C 2A ADD A,R2 ;

012D F8 MOV R0,A ;

012E 8625 MOV 25H,@R0 ;

0130 7A70 MOV R2,#70H ;分十位譯碼

0132 E522 MOV A,22H ;

0134 2A ADD A, R2 ;

0135 F8 MOV R0, A ;

0136 8626 MOV 26H, @R0 ;

0138 7A70 MOV R2, #70H ;分個位譯碼

013A E523 MOV A,23H ;

013C 2A ADD A,R2 ;

013D F8 MOV R0,A ;

013E 8627 MOV 27H,@R0 ;

0140 758000 MOV P0,#00H ;

0143 75A080 MOV P2,#80H ;掃描時十位

0146 852480 MOV 24H,P0 ;送時十位顯示代碼

0149 120191 LCALL 0191 ;顯示延時

014C 758000 MOV P0,#00H ;

014F 75A040 MOV P2,#40H ;掃描時個位

0152 852580 MOV 25H,P0 ;

0155 120191 LCALL 0191 ;

0158 758000 MOV P0,#00H ;

015B 75A020 MOV P2,#20H ;掃描分十位

015E 852680 MOV 26H,P0 ;

0161 120191 LCALL 0191 ;

0164 758000 MOV P0,#00H ;

0167 75A010 MOV P2,#10H ;掃描分個位

016A 852780 MOV 27H,P0 ;

016D 120191 LCALL 0191 ;

0170 758000 MOV P0,#00H ;

0173 22 RET ;顯示子程序返回

0174 7808 MOV R0,#08H ;秒脈長短調(diào)整子程序

0176 79CE MOV R1,#CEH ;

0178 D9FE DJNZ R1,0178 ;

017A D8FA DJNZ R0,0176 ;

017C 22 RET ;子程序返回

017D 792D MOV R1,#2DH ;嘀嗒聲子程序

017F D291 SETB P1.1

0181 788F MOV R0,#8FH ;

0183 D8FE DTNZ R0,0183 ;

0185 C291 CLR P1.1 ;

0187 788F MOV R0,#8FH ;

0189 D8FD DJNZ R0,0189 ;

018B D9F2 DJNZ R1,017F ;

018D 12019A LCALL 019A ;

0190 22 RET ;子程序返回

0191 7808 MOV R0,#08H ;2ms延時子程序

0193 798F MOV R1,#8FH ;

0195 D9FE DJNZ R1,0195 ;

0197 D8FA DJNZ R0,0193 ;

0199 22 RET ;子程序返回

019A 784F MOV R0,#4FH ;20ms延時子程序

019C 798F MOV R1,#8FH ;

019E D9FE DJNZ R1,019E ;

01A0 D8FA DJNZ R0,019C ;

01A2 22 RET ;子程序返回



評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉