隨著產(chǎn)業(yè)結(jié)構(gòu)的不斷調(diào)整、生產(chǎn)工藝的飛速發(fā)展、人們生活水平的不斷提高及家用電器的逐漸普及, 市場(chǎng)對(duì)定時(shí)控制系統(tǒng)的需求越來越大。 如, 定時(shí)自動(dòng)報(bào)警、定時(shí)自動(dòng)打鈴、定時(shí)開關(guān)烘箱、定時(shí)通斷動(dòng)力設(shè)備以及各種電氣的定時(shí)啟動(dòng)等都屬于定時(shí)控制系統(tǒng)[ 1] 。 定時(shí)控制系統(tǒng)的實(shí)現(xiàn)方法很多, 本文主要介紹以80C51 系列單片機(jī)中的AT89C51 為核心的智能定時(shí)控制系統(tǒng)的設(shè)計(jì)實(shí)現(xiàn)方式。 80C51 系列單片機(jī)進(jìn)入市場(chǎng)時(shí)間早, 總線開放, 仿真開發(fā)設(shè)備多, 芯片及其開發(fā)價(jià)格低廉、速度較快、電磁兼容性較好。 本文所述智能時(shí)鐘控制系統(tǒng)主要包括時(shí)鐘顯示、時(shí)間校正、鬧鈴設(shè)置及各種設(shè)備定時(shí)開關(guān)機(jī)( 可擴(kuò)展功能) 等功能。 實(shí)時(shí)日歷和時(shí)鐘顯示的設(shè)計(jì)過程在硬件與軟件方面進(jìn)行同步設(shè)計(jì)。硬件部分主要由AT89S52單片機(jī),LED顯示電路,以及調(diào)時(shí)按鍵電路等組成,系統(tǒng)通過LED顯示數(shù)據(jù),所以具有人性化的操作和直觀的顯示效果。軟件方面主要包括時(shí)鐘程序、鍵盤程序,顯示程序等。
我們?cè)谌粘I钪?,?jīng)常碰到一些需要定時(shí)的事情,例如:印相或放大照片,需要定在零點(diǎn)幾秒的時(shí)間,洗衣機(jī)洗滌衣物需要定在幾分鐘到幾十分鐘的時(shí)間,電風(fēng)扇需要定在數(shù)十分鐘的時(shí)間。完成這種定時(shí)的定時(shí)器有多種多樣,在家用電器中采用機(jī)械定時(shí)器就是根據(jù)一般上弦鐘表原理設(shè)計(jì)的,這種定時(shí)器雖然結(jié)構(gòu)簡(jiǎn)單,成本低,維修也比較方便,但是它的觸頭頻繁接觸和斷開,大大的縮減了它的使用壽命,也不利于進(jìn)一步全自動(dòng)化。在電子技術(shù)突飛猛進(jìn)的今天,電子定時(shí)器一定會(huì)逐步取而代之,這是不言而喻的。
定時(shí)器的應(yīng)用
定時(shí)器在家用電器中經(jīng)常用于延時(shí)自動(dòng)關(guān)機(jī)、定時(shí)。延時(shí)自動(dòng)關(guān)機(jī)可用于:收音機(jī)、電視機(jī)、錄音機(jī)、催眠器、門燈、路燈、汽車頭燈、轉(zhuǎn)彎燈以及其他電器的延時(shí)斷電及延時(shí)自停電源等。定時(shí)可用于:照相定時(shí)曝光、定時(shí)閃光、定時(shí)放大、定時(shí)調(diào)速、定時(shí)烘箱、冰箱門開定時(shí)報(bào)警、水位定時(shí)報(bào)警、延時(shí)催眠器、延時(shí)電鈴、延時(shí)電子鎖、觸摸定時(shí)開關(guān)等。例如:空調(diào)中的定時(shí)器,在工作一段時(shí)間之后便能自動(dòng)切斷電源停止工作。夏季夜間使用,入睡前先頂好時(shí)間,等睡熟后到了預(yù)定時(shí)間,空調(diào)自動(dòng)關(guān)機(jī)。方便節(jié)能。定時(shí)器除了應(yīng)用于家用電器外,還廣泛地用于工業(yè)農(nóng)業(yè)生產(chǎn)和服務(wù)設(shè)施,甚至軍事等。
51單片機(jī)內(nèi)部有一個(gè)8位的CPU,同時(shí)CPU內(nèi)部包含了運(yùn)算器,控制器及若干寄存器如圖(圖1)所示。
計(jì)數(shù)原理
STC單片機(jī)內(nèi)部設(shè)有兩個(gè)16位的可編程定時(shí)器/計(jì)數(shù)器。可編程的意思是指其功能(如工作方式、定時(shí)時(shí)間、量程、啟動(dòng)方式等)均可由指令來確定和改變。在定時(shí)器/計(jì)數(shù)器
中除了有兩個(gè)16位的計(jì)數(shù)器之外,還有兩個(gè)特殊功能寄存器(控制寄存器和方式寄存器)。
從上面定時(shí)器/計(jì)數(shù)器的結(jié)構(gòu)圖中我們可以看出,16位的定時(shí)/計(jì)數(shù)器分別由兩個(gè)8位專用寄存器組成,即:T0由TH0和TL0構(gòu)成;T1由TH1和TL1構(gòu)成。其訪問地址依次為8AH-8DH。每個(gè)寄存器均可單獨(dú)訪問。這些寄存器是用于存放定時(shí)或計(jì)數(shù)初值的。此外,其內(nèi)部還有一個(gè)8位的定時(shí)器方式寄存器TMOD和一個(gè)8位的定時(shí)控制寄存器TCON。這些寄存器之間是通過內(nèi)部總線和控制邏輯電路連接起來的。TMOD主要是用于選定定時(shí)器的工作方式;TCON主要是用于控制定時(shí)器的啟動(dòng)停止,此外TCON還可以保存T0、T1的溢出和中斷標(biāo)志。當(dāng)定時(shí)器工作在計(jì)數(shù)方式時(shí),外部事件通過引腳T0(P3.4)和T1(P3.5)輸入。
在這里,小編帶你一起 從零開始學(xué)51單片機(jī)定時(shí)器?;趩纹瑱C(jī)的定時(shí)器電路原理圖如下所示:
我們學(xué)單片機(jī)是首先學(xué)的就是 LED 閃爍,那是用延時(shí)程序做的,現(xiàn)在回想起來,這樣做不很恰當(dāng),為什么呢?我們的主程序做了燈的閃爍,就不能再干其它的事了,難道單片機(jī)只能這樣工作嗎?當(dāng)然不是,我們能用定時(shí)器來實(shí)現(xiàn)燈的閃爍的功能。
例 1:查詢方式
ORG 0000H
AJMP START
ORG 30H
START:
MOV P1,#0FFH ;關(guān)所 燈
MOV TMOD,#00000001B ;定時(shí)/計(jì)數(shù)器 0 工作于方式 1
MOV TH0,#15H
MOV TL0,#0A0H ;即數(shù) 5536
SETB TR0 ;定時(shí)/計(jì)數(shù)器 0 開始運(yùn)行
LOOP:JBC TF0,NEXT ;如果 TF0 等于 1,則清 TF0 并轉(zhuǎn) NEXT 處
AJMP LOOP ;不然跳轉(zhuǎn)到 LOOP 處運(yùn)行
NEXT:CPL P1.0
MOV TH0,#15H
MOV TL0,#9FH;重置定時(shí)/計(jì)數(shù)器的初值
AJMP LOOP
END AJMP LOOP
END
鍵入程序,看到了什么?燈在閃爍了,這可是用定時(shí)器做的,不再是主程序的循環(huán)了。簡(jiǎn)單地分析一下程序,為什么用 JBC 呢?TF0 是定時(shí)/計(jì)數(shù)器 0 的溢出標(biāo)記位,當(dāng)定時(shí)器產(chǎn)生溢出后,該位由 0 變 1,所以查詢?cè)撐痪涂芍顣r(shí)時(shí)間是否已到。該位為 1 后,要用軟件將標(biāo)記位清 0,以便下一次定時(shí)是間到時(shí)該位由 0 變 1,所以用了 JBC 指令,該指位在判 1轉(zhuǎn)移的同時(shí),還將該位清 0。
以上程序是能實(shí)現(xiàn)燈的閃爍了,可是主程序除了讓燈閃爍外,還是不能做其他的事??!不,不對(duì),我們能在 LOOP:……和 AJMP LOOP 指令之間插入一些指令來做其他的事情,只要保證執(zhí)行這些指令的時(shí)間少于定時(shí)時(shí)間就行了。那我們?cè)谟密浖訒r(shí)程序的時(shí)候不是也能用一些指令來替代 DJNZ 嗎?是的,但是那就要求你精確計(jì)算所用指令的時(shí)間,然后再減去對(duì)應(yīng)的 DJNZ 循環(huán)次數(shù),很不方便,而現(xiàn)在只要求所用指令的時(shí)間少于定時(shí)時(shí)間就行,顯然要求低了。當(dāng)然,這樣的辦法還是不好,所以我們常用以下的辦法來實(shí)現(xiàn)。
程序 2:用中斷實(shí)現(xiàn)
ORG 0000H
AJMP START
ORG 000BH ;定時(shí)器 0 的中斷向量地址
AJMP TIME0 ;跳轉(zhuǎn)到真正的定時(shí)器程序處
ORG 30H
START:
MOV P1,#0FFH ;關(guān)所 燈
MOV TMOD,#00000001B ;定時(shí)/計(jì)數(shù)器 0 工作于方式 1
MOV TH0,#15H
MOV TL0,#0A0H ;即數(shù) 5536
SETB EA ;開總中斷允許
SETB ET0 ;開定時(shí)/計(jì)數(shù)器 0 允許
SETB TR0 ;定時(shí)/計(jì)數(shù)器 0 開始運(yùn)行
LOOP: AJMP LOOP ;真正工作時(shí),這里可寫任意程序
TIME0: ;定時(shí)器 0 的中斷處理程序
PUSH ACC
PUSH PSW ;將 PSW 和 ACC 推入堆棧保護(hù)
CPL P1.0
MOV TH0,#15H
MOV TL0,#0A0H ;重置定時(shí)常數(shù)
POP PSW
POP ACC
RETI
END
上面的例程中,定時(shí)時(shí)間一到,TF0 由 0 變 1,就會(huì)引發(fā)中斷,CPU 將自動(dòng)轉(zhuǎn)至 000B處尋找程序并執(zhí)行,由于留給定時(shí)器中斷的空間只有 8 個(gè)字節(jié),顯然不足以寫下所有有中斷處理程序,所以在 000B 處安排一條跳轉(zhuǎn)指令,轉(zhuǎn)到實(shí)際處理中斷的程序處,這樣,中斷程序能寫在任意地方,也能寫任意長(zhǎng)度了。進(jìn)入定時(shí)中斷后,首先要保存當(dāng)前的一些狀態(tài),程序中只 演示了保存存 ACC 和 PSW,實(shí)際工作中應(yīng)該根據(jù)需要將可能會(huì)改變的單元的值都推入堆棧進(jìn)行保護(hù)(本程序中實(shí)際不需保存護(hù)任何值,這里只作個(gè)演示)。
上面的兩個(gè)單片機(jī)程序運(yùn)行后,我們發(fā)現(xiàn)燈的閃爍非常快,根本分辨不出來,只是視覺上感到燈有些晃動(dòng)而已,為什么呢?我們能計(jì)算一下,定時(shí)器中預(yù)置的數(shù)是 5536,所以每計(jì) 60000 個(gè)脈沖就是定時(shí)時(shí)間到,這 60000 個(gè)脈沖的時(shí)間是多少呢?我們的晶體震蕩器 是12M,所以就是 60000 微秒,即 60 毫秒,因此速度是非常快的。如果我想實(shí)現(xiàn)一個(gè) 1S 的定時(shí),該怎么辦呢?在該晶體震蕩器瀕率下,最長(zhǎng)的定時(shí)也就是 65。536 個(gè)毫秒啊!上面給出 一個(gè)例程。
ORG 0000H
AJMP START
ORG 000BH ;定時(shí)器 0 的中斷向量地址
AJMP TIME0 ;跳轉(zhuǎn)到真正的定時(shí)器程序處
ORG 30H
START:
MOV P1,#0FFH ;關(guān)所 燈
MOV 30H,#00H ;軟件計(jì)數(shù)器預(yù)清 0
MOV TMOD,#00000001B ;定時(shí)/計(jì)數(shù)器 0 工作于方式 1
MOV TH0,#3CH
MOV TL0,#0B0H ;即數(shù) 15536
SETB EA ;開總中斷允許
SETB ET0 ;開定時(shí)/計(jì)數(shù)器 0 允許
SETB TR0 ;定時(shí)/計(jì)數(shù)器 0 開始運(yùn)行
LOOP: AJMP LOOP ;真正工作時(shí),這里可寫任意程序
TIME0: ;定時(shí)器 0 的中斷處理程序
PUSH ACC
PUSH PSW ;將 PSW 和 ACC 推入堆棧保護(hù)
INC 30H
MOV A,30H
CJNE A,#20,T_RET ;30H 單元中的值到了 20 了嗎?
T_L1: CPL P1.0 ;到了,取反 P10
MOV 30H,#0 ;清軟件計(jì)數(shù)器
T_RET:
MOV TH0,#15H
MOV TL0,#9FH ;重置定時(shí)常數(shù)
POP PSW
POP ACC
RETI
END
先自己分析一下,看看是怎么實(shí)現(xiàn)的?這里采用了軟件計(jì)數(shù)器的概念,思路是這樣的,先用定時(shí)/計(jì)數(shù)器 0 做一個(gè) 50 毫秒的定時(shí)器,定時(shí)是間到了以后并不是立即取反 P10,而是將軟件計(jì)數(shù)器中的值加 1,如果軟件計(jì)數(shù)器計(jì)到了 20,就取反 P10,并清掉軟件計(jì)數(shù)器中的值,不然直接返回,這樣,就變成了 20 次定時(shí)中斷才取反一次 P10,因此定時(shí)時(shí)間就延長(zhǎng)了成了 20*50 即 1000 毫秒了。
這個(gè)思路在工程中是非常有用的,有的時(shí)候我們需要若干個(gè)定時(shí)器,可 51 中總共才有 2個(gè),怎么辦呢?其實(shí),只要這幾個(gè)定時(shí)的時(shí)間有一定的公約數(shù),我們就能用軟件定時(shí)器加以實(shí)現(xiàn),如我要實(shí)現(xiàn) P10 口所接燈按 1S 每次,而 P11 口所接燈按 2S 每次閃爍,怎么實(shí)現(xiàn)呢?對(duì)了我們用兩個(gè)計(jì)數(shù)器,一個(gè)在它計(jì)到 20 時(shí),取反 P10,并清零,就如上面所示,另一個(gè)計(jì)到 40 取反 P11,然后清 0,不就行了嗎?這部份的程序如下
ORG 0000H
AJMP START
ORG 000BH ;定時(shí)器 0 的中斷向量地址
AJMP TIME0 ;跳轉(zhuǎn)到真正的定時(shí)器程序處
ORG 30H
START:
MOV P1,#0FFH ;關(guān)所 燈
MOV 30H,#00H ;軟件計(jì)數(shù)器預(yù)清 0
MOV TMOD,#00000001B ;定時(shí)/計(jì)數(shù)器 0 工作于方式 1
MOV TH0,#3CH
MOV TL0,#0B0H ;即數(shù) 15536
SETB EA ;開總中斷允許
SETB ET0 ;開定時(shí)/計(jì)數(shù)器 0 允許
SETB TR0 ;定時(shí)/計(jì)數(shù)器 0 開始運(yùn)行
LOOP: AJMP LOOP ;真正工作時(shí),這里可寫任意程序
TIME0: ;定時(shí)器 0 的中斷處理程序
PUSH ACC
PUSH PSW ;將 PSW 和 ACC 推入堆棧保護(hù)
INC 30H
INC 31H ;兩個(gè)計(jì)數(shù)器都加 1
MOV A,30H
CJNE A,#20,T_NEXT ;30H 單元中的值到了 20 了嗎?
T_L1: CPL P1.0 ;到了,取反 P10
MOV 30H,#0 ;清軟件計(jì)數(shù)器
T_NEXT:
MOV A,31H
CJNE A,#40,T_RET ;31h 單元中的值到 40 了嗎?
T_L2:
CPL P1.1
MOV 31H,#0 ;到了,取反 P11,清計(jì)數(shù)器,返回
T_RET:
MOV TH0,#15H
MOV TL0,#9FH ;重置定時(shí)常數(shù)
POP PSW
POP ACC
RETI
END