實習十一 8051做1/100秒計時碼表
一•目的:瞭解 8051 Timer 計時功能原理及控制方法。
二•使用材料:8051 微電腦一片,4個共陰七段顯示器。
三•功能說明:Power ON Reset ( 冷開機 )後,4個七段顯 "0000";若接著按一次Reset
( 第一次暖開機 ),則開始以1/100秒計時並由七段跳動顯示;此時再按一次Reset
( 第二次暖開機 ),則停止計時,七段顯示出時間如 " 32 : 85 "為 32 秒 85 。再
按 Reset 相當冷開機動作。
四•程式流程圖
(a) 主程式:
(b)中斷程式
五•接線及說明
接線圖如實習六
(1) J47 接 P3.0 ~ P3.3
(2) J50 接 P1.0 ~ P1.7
六•程式及程式說明
. RSECT ; define register section
. ABSOLUTE ; adsolute RAM address
. ORG 20H ; offset address = 20h
RESET _ COUNT .DS 1 ; reset switch hit counter
SECOND1_200 .DS 1 ; unit = 1/200 S , 0-2
SECOND1_100 .DS 1 ; unit = 1/100 S , 0-9 ,D0
SECOND1_10 .DS 1 ; unit = 1/10 S , 0-9 ,D1
SECOND1 .DS 1 ; unit = 1s , 0-9 ,D2
SECOND10 .DS 1 ; unit = 10s , 0-9 ,D3
COUNT .DS 1 ; scan digit counter
STACK _ BOTTOM EQU $ ; stack bottom pointer
. CODE ; program code
. RELATIVE ; relative address
ORG 000H ; reset offset address
JMP BEGIN ; jump to main procedure
ORG 00BH ; timer0 offset address
JMP TIMER ; jump to interrupt
BEGIN : ; reset stare here
MOV COUNT,#0 ; clear scan counter
MOV SP,#STACK _ BOTTOM ; set stack bottom pointer
MOV R0,#RESET _ COUNT ; load r0 with reset _ times
CJNE @R0,#1,NEXT1 ; first warm reset ?
INC RESET _ COUNT ; inc reset times
;first warm reset , activate timer0 , start to count , once/5000us
MOV SECOND1_200,#0 ; clear clock buffer
MOV SECOND1_100,#0 ; clear clock buffer (dis0)
MOV SECOND1_10,0 ; clear clock buffer (dis1)
MOV SECOND1,#0 ; clear clock buffer (dis2)
MOV SECOND10,#0 ; clear clock buffer (dis3)
MOV TMOD,#00000001B ; set time0 ; mode1 , 16-bit
MOV TH0,#> - 5000 ; load TH0 with high byte
MOV TL0,#< - 5000 ; load TL0 with high byte
MOV IE,#100000010B ; enable timer0 interrupt
SETB TR0 ; turn timer0 on
JMP $ ; do nothing , loop here
NEXT1:
CJNE @RO,#2,CLEAR ; second warm reset ?
INC RESET_ COUNT ; inc reset times
HOLD: ;
;second warm reset , show how many seconds , get from display buffer
CALL DISPLAY ; scanning one display
CALL DELAY - 5000us ; delay about 5000us
JMP HOLD ; keep scanning display
CLEAR: ;
; cold reset start or third warm reset , show 00:00
MOV RESET_ COUNT,#1 ; initial reset _ counter=1
MOV SECOND1_100,#0 ; clear clock buffer (dis0)
MOV SECOND1_10,0 ; clear clock buffer (dis1)
MOV SECOND1,#0 ; clear clock buffer (dis2)
MOV SECOND10,#0 ; clear clock buffer (dis3)
show_0: ;
CALL DISPLAY ; scanning one display
CALL DELAY - 5000us ; delay about 5000us
JMP SHOW_0 ; keep scanning display
DELAY _ 5000US: ; delay for scan each digit
MOV R7,#10 ; delay time about
$1: MOV R6,#250 ; = R7*(R6*2us)
DJNZ R6,$ ; = 10 *(250*2us)
DJNZ R7,$1 ; = 5000US
RET ;
; timer0 mode1 overflow interrupt procedure , 5000us / once=(200hz)
TIMER: ;
PUSH ACC ; save accumulator value
PUSH PSW ; save program status
SETB RS0 ; select register bank1
CLR TR0 ; stop timer0
MOV A,#< (-5000+7) ; compensate 7u seconds
ADD A,TL0 ; = MOV TH0 - TL0,#(-5000+7)
MOV TL0,A ; 7 one cycle instructions
MOV A,#> (-5000+7) ; =MOV, ADD, MOV , MOV ,
ADDC A, TH0 ; ADDC, MOV , SETB,
MOV TH0,A ; reload , include overflow
SETB TR0 ; restart timer0 .
;
INC SECOND1_200 ; count per 5000u=1/200 S
MOV A, SECOND1_200 ; A = times of (1/200 s)
CJNE A, #2,NEXT ; non- equal 2, jmp away
MOV SECOND1_200,#0 ; 1/100 S = 2*(1/200 S )
;
INC SECOND1_100 ; increment per 1/100S
MOV A, SECOND1_100 ; A = times of (1/100 s)
CJNE A, #10,NEXT ; non- equal 10, jmp away
MOV SECOND1_100,#0 ; 1/10 S = 10*(1/100 S )
;
INC SECOND1_10 ; increment per 1/10S
MOV A, SECOND1_10 ; A = times of (1/10 s)
CJNE A, #10,NEXT ; non- equal 10, jmp away
MOV SECOND1_10,#0 ; 1 S = 10*(1/10 S )
;
INC SECOND1 ; increment per 1 S
MOV A, SECOND1 ; A = times of (1 s)
CJNE A, #10,NEXT ; non- equal 10, jmp away
MOV SECOND1,#0 ; 10 S = 10*(1 S )
;
INC SECOND10 ; increment per 10 S
MOV A, SECOND10 ; A = times of (10 s)
CJNE A, #10,NEXT ; non- equal 10, jmp away
MOV SECOND10,#0 ; 1 min = 10*(10 S )
;
NEXT:
CALL DISPLAY ; go to scan dislpay
POP PSW ; get back program status
POP ACC ; get back accumulator
RETI ; return main program
DISPLAY:
MOV R0,#COUNT ; load r0 with scan counter
CJNE @R0,#0,DIS1 ; if count not 0,jmp dis1
INC COUNT ; count = count +1
MOV P3,#111111110B ; enable digit 0
MOV DPTR, #TABLE_7_SEG ; get 7-segment table address
MOV R0,#SECOND1_100 ; index = 1/100 s buffer addr
MOV A,@R0 ; load A with buffer content
MOVC A, @A + DPTR ; convert number to 7-seg code
MOV P1,A ; display from port 1
RET ; return caller
;
DIS1:
MOV R0,#COUNT ; load r0 with scan counter
CJNE @R0,#1,DIS2 ; if count not 1,jmp dis2
INC COUNT ; count = count +1
MOV P3,#111111101B ; enable digit 1
MOV DPTR, #TABLE_7_SEG ; get 7-segment table address
MOV R0,#SECOND1_10 ; index = 1/10 s buffer addr
MOV A,@R0 ; load A with buffer content
MOVC A, @A + DPTR ; convert number to 7-seg code
MOV P1,A ; display from port 1
RET ; return caller
;
DIS2:
MOV R0,#COUNT ; load r0 with scan counter
CJNE @R0,#2,DIS3 ; if count not 2,jmp dis3
INC COUNT ; count = count +1
MOV P3,#111111011B ; enable digit 3
MOV DPTR, #TABLE_7_SEG ; get 7-segment table address
MOV R0,#SECOND1 ; index = 1 s buffer addr
MOV A,@R0 ; load A with buffer content
MOVC A, @A + DPTR ; convert number to 7-seg code
MOV P1,A ; display from port 1
RET ; return caller
;
DIS3:
MOV R0,#COUNT ; load scan count with zero
MOV P3,#111110111B ; enable digit 3
MOV DPTR, #TABLE_7_SEG ; get 7-segment table address
MOV R0,#SECOND10 ; index = 10 s buffer addr
MOV A,@R0 ; load A with buffer content
MOVC A, @A + DPTR ; convert number to 7-seg code
MOV P1,A ; display from port 1
RET ; return caller
;7-segment LED 0-9 display code , PABCDEFG , "0"=LED ON.
TABLE_7_SEG DB 10000001B,11001111B,10010010B,1000110B
DB 11001100B,10100100B,10100000B,1000111B
DB 10000000B,10000100B;0-9
END
程式說明
1•4 ~ 6 行 :設定暫存器段(Register Section),且聯結時偏移位址設為絕對 20H。
2•7 ~ 14 行:由RAM位址20H開始保留名變數之記憶位址。其中20H設定為判斷
Reset次數之記憶位址。冷開機(cold start)時, RAM內含值不定,依程式則做
clear 碼表動作,並設20H內含為1,再按 Reset 則設 2,再按則設3,以後20 H
之內就隨 Reset 鈕而成1,2,3 之變化。
3•16 ~ 21行 : 程式段開始,並以相對方式組譯指令。安排斷向量位址。
4•23 ~ 26行 :先判斷是暖開機嗎?若 RAM 20H 為 1 表示暖開機。
5•27 ~ 37行 :變更RAM 20H值,清除存放碼表計數的 RAM 記憶體,設定Timer 0
工作方式為 16 位元上數計時器,每 1us 上數一次,設 -5000 表示 5000us 溢位
一次。致能 Timer 0 溢位中斷。
6•38 ~ 39 行:啟始 Timer 0,計時開始。程式原地執行表示不做任何事。
7•40 ~ 42 行:按 Reset 後,20H 不是 1而是2,表示第三次 Reset, 做下一 hold 動作。
並將位址 20H 遞增成為 3。
8•43 ~ 47 行:將目前顯示器各計數的 RAM 位址持續多工掃描顯示。須注意,此時
之 Timer 0 是在停止狀態,因為 Reset 後,直接到此處執行程式而末曾啟始 Timer 0
。每 5000 us 致能一個七段顯示器。
9•48 ~ 58 行:將顯示器計數的 RAM清除,再掃描顯 "0000"。此段為冷開機或每隔
3次 Reset 之動作。
10•59 ~ 64 行:延遲 5000us之副程式。
11•66~108行:中斷副程式,負責碼表計時遞顯器計數RAM 之值,再做多工掃描顯示
器工作。其中 72~78 行為重新將 -5000 載人TH0、TL0;但是為求準確計時,Timer 0
溢位後,又超越遞增若干應一併補償,71行先停止上數,72行之7為停止Timer 0 到
再次啟動 Timer 0 間 (72~78行)共花費之指令時間為7us,73行是TL0 計數過頭也一併
加人,加完若進位也會在76行中加人 TH0 。反正,Timer 溢位直到進人中斷,一定少
許過數( overrun);若純粹用來多工掃描鍵盤或顯示器是不必計較的,做為時鐘計則可
比照此段指令補償之。
12• 109 ~ 155 行:多工掃描顯示器副程式,請參考第三章3.5節實驗四說明。