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