全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4500
推到 Plurk!
推到 Facebook!

時鐘程式改碼表加按鍵

答題得分者是:src
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-10-18 11:11:33 IP:122.125.xxx.xxx 訂閱
我的原始程式可以動作,時鐘程式改碼表加按鍵後卻不能動作,請問是哪裡有問題
我是要讓他按下p3.7開始執行,p3.6暫停執行,p3.5歸0 ,讓他計時0.01秒,當他跑到0.99時再來進位為1秒

這是我的程式原始程式

程式1:

EN REG P3.0
RW REG P3.1
RS REG P3.2
LCD REG P1
AMPM REG 38H ;上午/下午符號
HOUR REG 20H ;小時位址
MIN REG 21H ;分鐘位址
SEC REG 22H ;秒鐘位址
TIMES EQU 20 ;50000mSx20=1sec
COL EQU 3AH ;":"
DATAS EQU 30H ;顯示字元之起始位址
COUNTS EQU 9 ;顯示字元之個數
;=========================================================
ORG 0 ;程式從0位址開始
JMP START ;跳至START
ORG BH ;TIMER0中斷向量
JMP TIMER ;
START: MOV HOUR, #0 ;開始之時
MOV MIN, #0 ;開始之分
MOV SEC, #0 ;開始之秒
MOV 32H, #COL ;填入:
MOV 35H, #COL ;填入:
MOV AMPM, #0 ;填入自建字型位址
;=========================================================
MOV IE, #10000010B ;設定TIMER0中斷
MOV TMOD, #1 ;MODE 1
MOV SP, #60H ;移開堆疊指標
MOV TH0, #(65536-50000) ;填入計時量
MOV TL0, #(65536-50000) ;填入計時量
MOV R3, #TIMES ;設定中斷次數
SETB TR0 ;啟動TIMER 0
;=========================================================
INITIALIZE:
MOV A, #00111000B ;設定為8BIT, 2列, 5X7字型
CALL WR_INST ;
MOV A, #00001000B ;關閉顯示幕
CALL WR_INST ;
MOV A, #00000001B ;清除顯示幕
CALL WR_INST ;
MOV A, #00001111B ;開啟顯示幕, 游標, 與閃爍
CALL WR_INST ;
MOV A, #00000110B ;設定AC 1
CALL WR_INST ;
CALL WR_CG ;將自建字型寫入CG RAM
;=========================================================
JMP $ ;停滯
;=========================================================
WR_INST: CALL CHECK_BF
CLR RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
CHECK_BF: PUSH A
BUSY: CLR RS
SETB RW
SETB EN
MOV A,LCD
CLR EN
JB ACC.7,BUSY
CALL DELAY
POP A
RET
;=========================================================
WR_CG: MOV A, #01000000B ;指定CG RAM起始位址
CALL WR_INST ;將指令寫入LCM
MOV R2, #16 ;指定所要寫入之字元數
MOV R0, #0 ;間距
MOV DPTR, #CHAR ;指定自建字型位置
NEXT_C: MOV A, R0 ;
MOVC A, @A DPTR ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_C ;最後一個字元?
RET ;返回
;=========================================================
WR_STRING: MOV A, #10000000B ;指定第一列位址
CALL WR_INST ;將指令寫入LCM
MOV R2, #COUNTS ;指定所要寫入之字元數
MOV R0, #DATAS ;指定字元起始位址
NEXT_D: MOV A, @R0 ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_D ;最後一個字元?
RET ;返回
;=========================================================
WR_DATA: CALL CHECK_BF
SETB RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
DELAY: MOV R6,#15
D1: MOV R7,#200
DJNZ R7,$
DJNZ R6,D1
RET
;=========================================================
TIMER: PUSH A ;儲存ACC
MOV TH0, #(65536-50000) ;填入計時量
MOV TL0, #(65536-50000) ;填入計時量

DJNZ R3, AGAIN ;填入計時量
MOV R3, #TIMES ;設定中斷次數
CALL MODIFY ;調整時間顯示
AGAIN: POP A
RETI
;=========================================================
;=============秒
MODIFY: MOV A, SEC ;取回秒數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV SEC, A ;存回秒數
CJNE A, #60H, NEXT ;超過60秒?
MOV SEC, #0 ;歸零
;=============分
MOV A, MIN ;取回分數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV MIN, A ;存回分數
CJNE A, #60H, NEXT ;超過60分?
MOV MIN, #0 ;歸零
;=============時
MOV A, HOUR ;取回時數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV HOUR, A ;存回時數
CJNE A, #12H, NEXT ;超過12小時?
MOV HOUR, #0 ;歸零
MOV A, AMPM ;取回上/下午
CPL ACC.0 ;改變上/下午
MOV AMPM, A ;儲存上/下午
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
RET
;=========================================================
NUM2ASCII:
;=============時
MOV A, HOUR ;取回時
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 31H, A ;將ACC存入31H位置
INC R0 ; 下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 30H, A ;將ACC存入30H位置
;=============分
MOV A, MIN ;取回分
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 34H, A ;將ACC存入34H位置
INC R0 ; 下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 33H, A ;將ACC存入33H位置
;=============秒
MOV A, SEC ;取回秒
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 37H, A ;將ACC存入37H位置
INC R0 ;下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 36H, A ;將ACC存入36H位置
RET
;=========================================================
;=========================================================
CHAR:
DB 04H, 0EH, 1FH, 00H ;AM
DB 00H, 00H, 00H, 00H
DB 00H, 00H, 00H, 00H ;PM
DB 1FH, 0EH, 04H, 00H
;=========================================================
END






這是更改後的程式

程式2:

EN REG P3.0
RW REG P3.1
RS REG P3.2
LCD REG P1
AMPM REG 38H ;上午/下午符號
HOUR REG 20H ;小時位址
MIN REG 21H ;分鐘位址
SEC REG 22H ;秒鐘位址
TIMES EQU 20 ;50000mSx20=1sec
COL EQU 3AH ;":"
DATAS EQU 30H ;顯示字元之起始位址
COUNTS EQU 9 ;顯示字元之個數
;=========================================================
ORG 0 ;程式從0位址開始
JMP START ;跳至START
ORG 0BH ;TIMER0中斷向量
JMP TIMER ;
START: MOV HOUR, #0 ;開始之時
MOV MIN, #0 ;開始之分
MOV SEC, #0 ;開始之秒
MOV 32H, #COL ;填入:
MOV 35H, #COL ;填入:
MOV AMPM, #0 ;填入自建字型位址
;=========================================================
MOV IE, #10000010B ;設定TIMER0中斷
MOV TMOD, #1 ;MODE 1
MOV SP, #60H ;移開堆疊指標
MOV TH0, #>(65536-500) ;填入計時量
MOV TL0, #<(65536-500) ;填入計時量
MOV R3, #TIMES ;設定中斷次數
SETB EA
SETB ET0
;
ACALL DELAY1
JNB P3.7,$
ACALL DELAY1
;
JB P3.7,$
SETB TR0
ACALL DELAY1
JNB P3.7,$
ACALL DELAY1
;
JB P3.6,$
CLR TR0
ACALL DELAY1
JNB P3.6,$
ACALL DELAY1
;
JB P3.5,$
AJMP START
;
;=========================================================
INITIALIZE:
MOV A, #00111000B ;設定為8BIT, 2列, 5X7字型
CALL WR_INST ;
MOV A, #00001000B ;關閉顯示幕
CALL WR_INST ;
MOV A, #00000001B ;清除顯示幕
CALL WR_INST ;
MOV A, #00001111B ;開啟顯示幕, 游標, 與閃爍
CALL WR_INST ;
MOV A, #00000110B ;設定AC 1
CALL WR_INST ;
CALL WR_CG ;將自建字型寫入CG RAM
;=========================================================
JMP $ ;停滯
;=========================================================
WR_INST: CALL CHECK_BF
CLR RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
CHECK_BF: PUSH A
BUSY: CLR RS
SETB RW
SETB EN
MOV A,LCD
CLR EN
JB ACC.7,BUSY
CALL DELAY
POP A
RET
;=========================================================
WR_CG: MOV A, #01000000B ;指定CG RAM起始位址
CALL WR_INST ;將指令寫入LCM
MOV R2, #16 ;指定所要寫入之字元數
MOV R0, #0 ;間距
MOV DPTR, #CHAR ;指定自建字型位置
NEXT_C: MOV A, R0 ;
MOVC A, @A DPTR ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_C ;最後一個字元?
RET ;返回
;=========================================================
WR_STRING: MOV A, #10000000B ;指定第一列位址
CALL WR_INST ;將指令寫入LCM
MOV R2, #COUNTS ;指定所要寫入之字元數
MOV R0, #DATAS ;指定字元起始位址
NEXT_D: MOV A, @R0 ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_D ;最後一個字元?
RET ;返回
;=========================================================
WR_DATA: CALL CHECK_BF
SETB RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
DELAY: MOV R6,#15
D1: MOV R7,#200
DJNZ R7,$
DJNZ R6,D1
RET
;
DELAY1: MOV R6,#100
D2: MOV R7,#200
DJNZ R7,$
DJNZ R6,D2
RET
;
;=========================================================
TIMER: PUSH A ;儲存ACC
MOV TH0, #>(65536-500) ;填入計時量
MOV TL0, #<(65536-500) ;填入計時量
DJNZ R3, AGAIN ;填入計時量
MOV R3, #TIMES ;設定中斷次數
CALL MODIFY ;調整時間顯示
AGAIN: POP A
RETI
;=========================================================
;=============秒
MODIFY: MOV A, SEC ;取回秒數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV SEC, A ;存回秒數
CJNE A, #99H, NEXT ;超過99毫?
MOV SEC, #0 ;歸零
;=============分
MOV A, MIN ;取回分數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV MIN, A ;存回分數
CJNE A, #60H, NEXT ;超過60秒?
MOV MIN, #0 ;歸零
;=============時
MOV A, HOUR ;取回時數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV HOUR, A ;存回時數
CJNE A, #60H, NEXT ;超過60分?
MOV HOUR, #0 ;歸零
MOV A, AMPM ;取回上/下午
CPL ACC.0 ;改變上/下午
MOV AMPM, A ;儲存上/下午
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
RET
;=========================================================
NUM2ASCII:
;=============時
MOV A, HOUR ;取回時
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 31H, A ;將ACC存入31H位置
INC R0 ; 下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 30H, A ;將ACC存入30H位置
;=============分
MOV A, MIN ;取回分
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 34H, A ;將ACC存入34H位置
INC R0 ; 下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 33H, A ;將ACC存入33H位置
;=============秒
MOV A, SEC ;取回秒
MOV R0, #25H ;指定暫存位置
MOV @R0, A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0, A ;存入暫存位置
MOV A, #30H ;將30H存入ACC
MOV R0, #25H ;指定暫存位置
XCHD A, @R0 ;將25H之低四位元移入ACC
MOV 37H, A ;將ACC存入37H位置
INC R0 ;下一個暫存位置
XCHD A, @R0 ;將26H之低四位元移入ACC
MOV 36H, A ;將ACC存入36H位置
RET
;=========================================================
;=========================================================
CHAR:
DB 04H, 0EH, 1FH, 00H ;AM
DB 00H, 00H, 00H, 00H
DB 00H, 00H, 00H, 00H ;PM
DB 1FH, 0EH, 04H, 00H
;=========================================================
END
編輯記錄
yha043027 重新編輯於 2007-10-18 16:16:32, 註解 無‧
yha043027 重新編輯於 2007-10-22 15:05:33, 註解 以更改程式,但每10分會慢大約5秒‧
yha043027 重新編輯於 2007-10-24 14:44:45, 註解 無‧
yha043027 重新編輯於 2007-10-24 14:51:43, 註解 無‧
yha043027 重新編輯於 2007-11-04 09:41:20, 註解 無‧
bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-10-24 22:56:36 IP:61.217.xxx.xxx 訂閱
大概看了一下, 你那段 INITIALIZE 的程式, 是要初始化 LCM 的, 如果沒有作, LCM 應該不會顯示資料.
所以按判斷按鍵那段程式擋在前面了, LCM 沒有機會被 INITIALIZE, 就不會有畫面了.

順道建議一下, 大大你在問問題時, 請考慮一下看問題的人的立場. 看問題的人不是和你一起工作的,
沒看過你的東西, 沒經歷過你遇到的問題, 所以你在描述問題時, 最好多想想看的人的感覺, 不要有
模擬兩可的狀況.

"時鐘程式改碼表加按鍵後卻不能動作", 這句話中的 "不能動作" 其實很含糊. 通電沒有字幕? 有字幕
但按下按鈕字幕沒有反應? 有字幕按下按鈕後消失?... 這其中有太多的狀況.

曾經有人打電話來問我一個問題 "我的程式有三個迴圈, 但是跑了之後當掉". 你接了這個電話, 有
辦法回答嗎?
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-10-25 09:51:11 IP:122.125.xxx.xxx 訂閱
很抱歉我下次會注意的,他是通電之後就沒動作
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-11-02 15:12:58 IP:122.125.xxx.xxx 訂閱
MOV TH0, #(65536-50000) ;填入計時量
MOV TL0, #(65536-50000) ;填入計時量

還沒加按鍵就不能動,因為這裡最多只能改成 -30000 ,所以最快只能顯示0.03秒

我問過人,他說是因為跑太快我們無法看見,請問要怎麼做才能讓它顯示在LCD上
編輯記錄
yha043027 重新編輯於 2007-11-02 15:18:17, 註解 無‧
bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-11-02 23:05:37 IP:59.121.xxx.xxx 訂閱
你原本說 "我的原始程式可以動作,時鐘程式改碼表加按鍵後卻不能動作"

聽起來很像是你原始程式是個時鐘程式, 運作正常. 後來你把它改成碼錶並加了按鍵之後,
就不能動作了.

後來說 "還沒加按鍵就不能動"

這又是什麼意思? 硬體上沒有加上按鍵就不能動了? 軟體上沒有加上按鍵功能就不能動了?
那麼能動的是什麼部份? 後來作了什麼改變之後才不能動的?

如果你懷疑是人家和你說的那個原因, 那你可以把中斷先禁止, 然後在主程式中先 call
modify, 看看到底有沒輸出到 LCM.

"沒動作" 這個詞很含糊, 是沒畫面? 還是有畫面但是數字不會變動? 還是按了鈕沒反應?

yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-11-04 10:23:54 IP:125.233.xxx.xxx 訂閱

我的意思是說在程式1,也就是我的原始程式是可以正常動作
但我改變綠色的地方卻不能動
EN REG P3.0
RW REG P3.1
RS REG P3.2
LCD REG P1
AMPM REG 38H ;上午/下午符號
HOUR REG 20H ;小時位址
MIN REG 21H ;分鐘位址
SEC REG 22H ;秒鐘位址
TIMES EQU 1 ;50000mSx20=1sec
COL EQU 3AH ;":"
DATAS EQU 30H ;顯示字元之起始位址
COUNTS EQU 9 ;顯示字元之個數
;=========================================================
ORG 0 ;程式從0位址開始
JMP START ;跳至START
ORG BH ;TIMER0中斷向量
JMP TIMER ;
START: MOV HOUR, #0 ;開始之時
MOV MIN, #0 ;開始之分
MOV SEC, #0 ;開始之秒
MOV 32H, #COL ;填入:
MOV 35H, #COL ;填入:
MOV AMPM, #0 ;填入自建字型位址
;=========================================================
MOV IE, #10000010B ;設定TIMER0中斷
MOV TMOD, #1 ;MODE 1
MOV SP, #60H ;移開堆疊指標
MOV TH0, #(65536-10000) ;填入計時量
MOV TL0, #(65536-10000) ;填入計時量

因為這裡最多只能改成 -30000 ,所以最快只能顯示0.03秒
而我改成-10000時就完全沒畫面

我問過人,他說是因為跑太快我們無法看見,請問要怎麼做才能讓它顯示在LCD上


bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-11-04 22:16:03 IP:59.115.xxx.xxx 訂閱
我想問一下, 在 CHECK_BF 中,  當程式已經確定 LCM 沒有 busy 之後, 再 call DELAY
的用意為何?

因為你一個 DELAY 跑下來, 至少要 6ms 的時間, 每次填寫資料至 LCM 均會 DELAY 這麼久.
所以你的中斷週期至少要 30mS 才夠, 否則你用 10mS 的中斷週期, 會造成中斷程式還沒跑完,
下一個中斷就發生了, 所以程式變成這個局面吧.

如果那個 DELAY 沒有什麼特別的目的 (先人的遺跡?) , 先把它拿掉試試. 如果達到目的, 就
恭喜你. 如果還不行, 可以試試改成中斷程式中只去異動時間, 然後在主程式中去異動 LCM.

另外一直想要告訴你一點, 你在中斷程式中去設 TH, TL, 會迼成時鐘有很大的誤差, 隨著你
中斷的頻繁度提高而上昇.
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-11-16 14:33:00 IP:122.125.xxx.xxx 訂閱
我已經改成
DELAY: MOV R6,#4
D1: MOV R7,#200
DJNZ R7,$
DJNZ R6,D1
RET


已經可以動了,但就如你所說跑起來真的比較慢
但人家不是多說用中斷去設會比較準嗎?
要怎樣才能讓他跑起來較準確


bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-11-16 18:34:30 IP:61.218.xxx.xxx 訂閱
比較慢, 是多慢呢? 給個明確一點的數值比較好猜.

用中斷比較準沒錯, 但是你在中斷程式中去填 timer 的值, 這樣一定會慢.
因為你填了 -10000 之後, 中斷會在 -10000 之後發生, 但是中斷發生之後,
又有幾個指令, delay 了幾個 uS, 才會再重填 10000, 那幾個指令就會造成
delay.

比較好的辦法, 是用 auto reload 的 timer, 這樣中斷就會準確的發生.
但是 timer 會變為 8bits, 中斷頻率高, 所以不要在中斷常式中去作太多
的事情, 就把時分秒的數值更新一下就好了. 由主程式中去判斷時間更新,
再傳新的值到 LCM.

沒查到 8051 中斷發生到進入 ISR 要多少個 instruction cycle. 假設 5 cycle,
那麼加上那幾個 reload timer 的指令, 大約就用了 10 cycle. 所以誤差就近
千分之一, 至少十幾分就會慢一秒以上. 如果慢的更明顯, 可能還有別的原因.
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-11-17 12:15:58 IP:122.125.xxx.xxx 訂閱
比較好的辦法, 是用 auto reload 的 timer, 這是什麼意思,要怎麼去設 我的程式1分就會慢20秒 ,請問是哪有問題

bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-11-17 14:14:22 IP:59.121.xxx.xxx 訂閱
你的程式一分會慢 20 秒, 顯然有更嚴重的問題要先解決, 等到你十分慢一秒時, 再來弄 auto reload 的部份.



我猜你的問題, 是在於中斷服務程式執行過久, 造成中斷遺失. 所以會有那麼嚴重的誤差. 你試試看把程式作

以下的調整, 問題會不會改善.



1. 將 MODIFY 最後面 CALL NUM2ASCII 與 CALL WR_STRING 拿掉.



2. 將主程式最後的 JMP $ 改成

mainloop:
CALL NUM2ASCII
CALL WR_STRING
JMP mainloop


這樣子 ISR 應該就不會有跑太久的問題.
src
高階會員


發表:1
回覆:94
積分:154
註冊:2005-08-23

發送簡訊給我
#12 引用回覆 回覆 發表時間:2007-11-18 22:39:51 IP:125.224.xxx.xxx 訂閱

[code delphi]
請在此區域輸入程式碼
;1.LCD CHECK_BF:在讀取忙碌旗標前必須先將P1送FFH並取消DELAY
;2.將TIMER改成MODE2自動載入
;==========================================================
STAR REG P3.7
STOP REG P3.6
RESET REG P3.5
EN REG P3.0
RW REG P3.1
RS REG P3.2
LCD REG P1
AMPM REG 38H ;上午/下午符號
HOUR REG 20H ;小時位址
MIN REG 21H ;分鐘位址
SEC REG 22H ;秒鐘位址
TIMES EQU 50 ;50x200=0.01sec
COL EQU 3AH ;":"
DATAS EQU 30H ;顯示字元之起始位址
COUNTS EQU 9 ;顯示字元之個數
;=========================================================
ORG 0 ;程式從0位址開始
JMP START ;跳至START
ORG 0BH ;TIMER0中斷向量
JMP TIMER ;
START: MOV HOUR,#0 ;開始之時
MOV MIN,#0 ;開始之分
MOV SEC,#0 ;開始之秒
MOV 32H,#COL ;填入:
MOV 35H,#COL ;填入:
MOV AMPM,#0 ;填入自建字型位址
;=========================================================
MOV IE,#10000010B ;設定TIMER0中斷
MOV TMOD,#2 ;MODE 2
MOV SP,#60H ;移開堆疊指標
MOV TH0,#(256-200) ;填入計時量
MOV TL0,#(256-200) ;填入計時量
MOV R3,#TIMES ;設定中斷次數
;SETB TR0 ;啟動TIMER 0
;=========================================================
INITIALIZE:
MOV A,#00111000B ;設定為8BIT, 2列, 5X7字型
CALL WR_INST ;
MOV A,#00001000B ;關閉顯示幕
CALL WR_INST ;
MOV A,#00000001B ;清除顯示幕
CALL WR_INST ;
MOV A,#00001111B ;開啟顯示幕, 游標, 與閃爍
CALL WR_INST ;
MOV A,#00000110B ;設定AC 1
CALL WR_INST ;
CALL WR_CG ;將自建字型寫入CG RAM
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
;=========================================================
MAIN:
JB STAR,LOOP1
SETB TR0 ;啟動TIMER 0
LOOP1:
JB STOP,LOOP2
CLR TR0 ;停止TIMER 0
LOOP2:
JB RESET,MAIN_RET
MOV HOUR,#0 ;開始之時
MOV MIN,#0 ;開始之分
MOV SEC,#0 ;開始之秒
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
MAIN_RET:
JMP MAIN
;=========================================================
WR_INST:
CALL CHECK_BF
CLR RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
CHECK_BF:
PUSH A
MOV LCD,#0FFH
CLR RS
SETB RW
BUSY: SETB EN
MOV A,LCD
CLR EN
JB ACC.7,BUSY
;CALL DELAY
POP A
RET
;=========================================================
WR_CG: MOV A,#01000000B ;指定CG RAM起始位址
CALL WR_INST ;將指令寫入LCM
MOV R2,#16 ;指定所要寫入之字元數
MOV R0,#0 ;間距
MOV DPTR,#CHAR ;指定自建字型位置
NEXT_C: MOV A,R0 ;
MOVC A,@A DPTR ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2,NEXT_C ;最後一個字元?
RET ;返回
;=========================================================
WR_STRING:
MOV A,#10000000B ;指定第一列位址
CALL WR_INST ;將指令寫入LCM
MOV R2,#COUNTS ;指定所要寫入之字元數
MOV R0,#DATAS ;指定字元起始位址
NEXT_D: MOV A,@R0 ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_D ;最後一個字元?
RET ;返回
;=========================================================
WR_DATA:
CALL CHECK_BF
SETB RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
RET
;=========================================================
DELAY: MOV R6,#15
D1: MOV R7,#200
DJNZ R7,$
DJNZ R6,D1
RET
;=========================================================
TIMER: PUSH A ;儲存ACC
DJNZ R3,AGAIN ;填入計時量
MOV R3,#TIMES ;設定中斷次數
CALL MODIFY ;調整時間顯示
AGAIN: POP A
RETI
;=========================================================
;=============秒
MODIFY: MOV A,SEC ;取回秒數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV SEC,A ;存回秒數
CJNE A,#99H, NEXT ;超過60秒?
MOV SEC,#0 ;歸零
;=============分
MOV A,MIN ;取回分數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV MIN,A ;存回分數
CJNE A,#60H, NEXT ;超過60分?
MOV MIN,#0 ;歸零
;=============時
MOV A,HOUR ;取回時數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV HOUR,A ;存回時數
CJNE A,#60H, NEXT ;超過12小時?
MOV HOUR,#0 ;歸零
MOV A,AMPM ;取回上/下午
CPL ACC.0 ;改變上/下午
MOV AMPM,A ;儲存上/下午
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
RET
;=========================================================
NUM2ASCII:
;=============時
MOV A,HOUR ;取回時
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 31H,A ;將ACC存入31H位置
INC R0 ; 下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 30H,A ;將ACC存入30H位置
;=============分
MOV A,MIN ;取回分
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 34H,A ;將ACC存入34H位置
INC R0 ; 下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 33H,A ;將ACC存入33H位置
;=============秒
MOV A,SEC ;取回秒
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 37H,A ;將ACC存入37H位置
INC R0 ;下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 36H,A ;將ACC存入36H位置
RET
;=========================================================
;=========================================================
CHAR:
DB 04H,0EH,1FH,00H ;AM
DB 00H,00H,00H,00H
DB 00H,00H,00H,00H ;PM
DB 1FH,0EH,04H,00H
;=========================================================
END
[/code]

編輯記錄
src 重新編輯於 2007-11-18 22:45:29, 註解 無‧
src 重新編輯於 2007-11-18 22:47:27, 註解 無‧
src 重新編輯於 2007-11-18 22:52:58, 註解 無‧
src 重新編輯於 2007-11-18 22:55:50, 註解 無‧
src 重新編輯於 2007-11-18 23:07:17, 註解 無‧
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#13 引用回覆 回覆 發表時間:2007-11-21 13:49:58 IP:122.125.xxx.xxx 訂閱
src 謝謝你,可以動作了,但是10分鐘會慢5秒

bernie_w39 我照你說的將
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
拿掉
將主程式最後的 JMP $ 改成
mainloop:
CALL NUM2ASCII
CALL WR_STRING
JMP mainloop

這裡是不是要改成
CJNE A, #60H, mainloop ;超過60秒?
MOV SEC, #0 ;歸零
CJNE A, #60H, mainloop ;超過60分?
MOV MIN, #0 ;歸零
CJNE A, #12H, mainloop ;超過12小時?
MOV HOUR, #0 ;歸零

我改好之後接上電源他ㄧ直停在00:00:00
是哪裡有改錯嗎

編輯記錄
yha043027 重新編輯於 2007-11-21 14:02:39, 註解 無‧
src
高階會員


發表:1
回覆:94
積分:154
註冊:2005-08-23

發送簡訊給我
#14 引用回覆 回覆 發表時間:2007-11-21 17:12:30 IP:59.121.xxx.xxx 訂閱
不懂你的意識,把修改後的程式貼上來看看。
===================引 用 yha043027 文 章===================
src 謝謝你,可以動作了,但是10分鐘會慢5秒

bernie_w39 我照你說的將
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
拿掉
將主程式最後的 JMP $ 改成
mainloop:
CALL NUM2ASCII
CALL WR_STRING
JMP mainloop

這裡是不是要改成
CJNE A, #60H, mainloop ;超過60秒?
MOV SEC, #0 ;歸零
CJNE A, #60H, mainloop ;超過60分?
MOV MIN, #0 ;歸零
CJNE A, #12H, mainloop ;超過12小時?
MOV HOUR, #0 ;歸零

我改好之後接上電源他ㄧ直停在00:00:00
是哪裡有改錯嗎

bernie_w39
資深會員


發表:3
回覆:199
積分:280
註冊:2007-10-07

發送簡訊給我
#15 引用回覆 回覆 發表時間:2007-11-21 23:06:26 IP:59.121.xxx.xxx 訂閱
我的意思是把 call num2ascii 與 call wr_string 這兩個從 modify 中移出.
但是那個 next: 的標記還是可以留著, 這樣你原本那幾行就不用動.
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#16 引用回覆 回覆 發表時間:2007-11-22 13:27:50 IP:122.125.xxx.xxx 訂閱
src   我是照你的程式下去跑,但10分會慢5秒

===================引 用 src 文 章===================
不懂你的意識,把修改後的程式貼上來看看。
編輯記錄
yha043027 重新編輯於 2007-11-22 13:28:23, 註解 無‧
src
高階會員


發表:1
回覆:94
積分:154
註冊:2005-08-23

發送簡訊給我
#17 引用回覆 回覆 發表時間:2007-11-23 06:52:29 IP:61.217.xxx.xxx 訂閱

[code delphi]
每增加一個指令都會增加執行的時間而使時間便嫚
還有振盪晶體的誤差
用時間IC就可以解決時間慢的問題
以下修改僅作參考
程式最前面加一行宣告
DISPLAY EQU 2FH.0
主程式修改
MAIN:
JB STAR,LOOP1
SETB TR0 ;啟動TIMER 0
LOOP1:
JB STOP,LOOP2
CLR TR0 ;停止TIMER 0
LOOP2:
JB RESET,LOOP3
MOV HOUR,#0 ;開始之時
MOV MIN,#0 ;開始之分
MOV SEC,#0 ;開始之秒
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
LOOP3:
JNB DISPLAY,MAIN_RET
CLR DISPLAY
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
MAIN_RET:
JMP MAIN
中斷程式的修改
TIMER: ;PUSH ACC ;儲存ACC
DJNZ R3,AGAIN ;填入計時量
MOV R3,#TIMES ;設定中斷次數
CALL MODIFY ;調整時間顯示
AGAIN: ;POP ACC
調整時間顯示的修改
MODIFY: MOV A,SEC ;取回秒數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV SEC,A ;存回秒數
CJNE A,#99H, NEXT ;超過60秒?
MOV SEC,#0 ;歸零
;=============分
MOV A,MIN ;取回分數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV MIN,A ;存回分數
CJNE A,#60H, NEXT ;超過60分?
MOV MIN,#0 ;歸零
;=============時
MOV A,HOUR ;取回時數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV HOUR,A ;存回時數
CJNE A,#60H, NEXT ;超過12小時?
MOV HOUR,#0 ;歸零
MOV A,AMPM ;取回上/下午
CPL ACC.0 ;改變上/下午
MOV AMPM,A ;儲存上/下午
NEXT: ;CALL NUM2ASCII ;轉換碼
;CALL WR_STRING ;顯示時間
SETB DISPLAY
RET
RETI

[/code]

===================引 用 yha043027 文 章===================
src 我是照你的程式下去跑,但10分會慢5秒

===================引 用 src 文 章===================
不懂你的意識,把修改後的程式貼上來看看。
編輯記錄
src 重新編輯於 2007-11-23 06:54:53, 註解 無‧
yha043027
一般會員


發表:2
回覆:11
積分:2
註冊:2007-05-18

發送簡訊給我
#18 引用回覆 回覆 發表時間:2007-12-04 16:22:24 IP:122.125.xxx.xxx 訂閱
src 我照你說的下去改,但他會停在00:00:00
完全不能跑
src
高階會員


發表:1
回覆:94
積分:154
註冊:2005-08-23

發送簡訊給我
#19 引用回覆 回覆 發表時間:2007-12-04 19:42:43 IP:59.121.xxx.xxx 訂閱
I/O請修改不同的宣告
[code delphi]
DISPLAY EQU 2FH.0
STAR EQU P3.7
STOP EQU P3.6
RESET EQU P3.5
EN EQU P1.7
RW EQU P1.6
RS EQU P1.5
LCD EQU P0
AMPM EQU 38H ;上午/下午符號
HOUR EQU 20H ;小時位址
MIN EQU 21H ;分鐘位址
SEC EQU 22H ;秒鐘位址
TIMES EQU 50 ;50x200=0.01sec
COL EQU 3AH ;":"
DATAS EQU 30H ;顯示字元之起始位址
COUNTS EQU 9 ;顯示字元之個數
;=========================================================
ORG 0 ;程式從0位址開始
JMP START ;跳至START
ORG 0BH ;TIMER0中斷向量
JMP TIMER ;
START: MOV HOUR,#0 ;開始之時
MOV MIN,#0 ;開始之分
MOV SEC,#0 ;開始之秒
MOV 32H,#COL ;填入:
MOV 35H,#COL ;填入:
MOV AMPM,#0 ;填入自建字型位址
;=========================================================
MOV IE,#10000010B ;設定TIMER0中斷
MOV TMOD,#1 ;MODE 2
MOV SP,#60H ;移開堆疊指標
MOV TH0,#(65536-10000)/256 ;填入計時量
MOV TL0,#(65536-10000) MOD 256 ;填入計時量
MOV R3,#TIMES ;設定中斷次數
;SETB TR0 ;啟動TIMER 0
;=========================================================
INITIALIZE:
MOV A,#00111000B ;設定為8BIT, 2列, 5X7字型
CALL WR_INST ;
MOV A,#00001000B ;關閉顯示幕
CALL WR_INST ;
MOV A,#00000001B ;清除顯示幕
CALL WR_INST ;
MOV A,#00001111B ;開啟顯示幕, 游標, 與閃爍
CALL WR_INST ;
MOV A,#00000110B ;設定AC 1
CALL WR_INST ;
CALL WR_CG ;將自建字型寫入CG RAM
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
;=========================================================
MAIN:
JB STAR,LOOP1
SETB TR0 ;啟動TIMER 0
LOOP1:
JB STOP,LOOP2
CLR TR0 ;停止TIMER 0
LOOP2:
JB RESET,LOOP3
MOV HOUR,#0 ;開始之時
MOV MIN,#0 ;開始之分
MOV SEC,#0 ;開始之秒
CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
LOOP3:
JNB DISPLAY,MAIN_RET
CLR DISPLAY
CALL MODIFY ;調整時間顯示
MAIN_RET:
JMP MAIN
;=========================================================
WR_INST:
CALL CHECK_BF
CLR RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
;CALL DELAY
RET
;=========================================================
CHECK_BF:
PUSH ACC
MOV LCD,#0FFH
CLR RS
SETB RW
BUSY: SETB EN
MOV A,LCD
CLR EN
JB ACC.7,BUSY
;CALL DELAY
POP ACC
RET
;=========================================================
WR_CG: MOV A,#01000000B ;指定CG RAM起始位址
CALL WR_INST ;將指令寫入LCM
MOV R2,#16 ;指定所要寫入之字元數
MOV R0,#0 ;間距
MOV DPTR,#CHAR ;指定自建字型位置
NEXT_C: MOV A,R0 ;
MOVC A,@A DPTR ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2,NEXT_C ;最後一個字元?
RET ;返回
;=========================================================
WR_STRING:
MOV A,#10000000B ;指定第一列位址
CALL WR_INST ;將指令寫入LCM
MOV R2,#COUNTS ;指定所要寫入之字元數
MOV R0,#DATAS ;指定字元起始位址
NEXT_D: MOV A,@R0 ;取用字元
CALL WR_DATA ;寫入LCM
INC R0 ;下一個字元
DJNZ R2, NEXT_D ;最後一個字元?
RET ;返回
;=========================================================
WR_DATA:
CALL CHECK_BF
SETB RS
CLR RW
SETB EN
MOV LCD,A
CLR EN
;CALL DELAY
RET
;=========================================================
DELAY: MOV R6,#15
D1: MOV R7,#200
DJNZ R7,$
DJNZ R6,D1
RET
;=========================================================
TIMER: ;PUSH ACC ;儲存ACC
MOV TH0,#(65536-10000)/256 ;填入計時量
MOV TL0,#(65536-10000) MOD 256 ;填入計時量
;DJNZ R3,AGAIN ;填入計時量
;MOV R3,#TIMES ;設定中斷次數
SETB DISPLAY
;CALL MODIFY ;調整時間顯示
AGAIN: ;POP ACC
RETI
;=========================================================
;=============秒
MODIFY: MOV A,SEC ;取回秒數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV SEC,A ;存回秒數
CJNE A,#99H, NEXT ;超過60秒?
MOV SEC,#0 ;歸零
;=============分
MOV A,MIN ;取回分數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV MIN,A ;存回分數
CJNE A,#60H, NEXT ;超過60分?
MOV MIN,#0 ;歸零
;=============時
MOV A,HOUR ;取回時數
INC A ;加1秒
CLR CY ;清除進位
DA A ;BCD調整
MOV HOUR,A ;存回時數
CJNE A,#60H, NEXT ;超過12小時?
MOV HOUR,#0 ;歸零
MOV A,AMPM ;取回上/下午
CPL ACC.0 ;改變上/下午
MOV AMPM,A ;儲存上/下午
NEXT: CALL NUM2ASCII ;轉換碼
CALL WR_STRING ;顯示時間
RET
;=========================================================
NUM2ASCII:
;=============時
MOV A,HOUR ;取回時
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 31H,A ;將ACC存入31H位置
INC R0 ; 下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 30H,A ;將ACC存入30H位置
;=============分
MOV A,MIN ;取回分
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 34H,A ;將ACC存入34H位置
INC R0 ; 下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 33H,A ;將ACC存入33H位置
;=============秒
MOV A,SEC ;取回秒
MOV R0,#25H ;指定暫存位置
MOV @R0,A ;存入暫存位置
SWAP A ;高低四位元互換
INC R0 ;下一個暫存位置
MOV @R0,A ;存入暫存位置
MOV A,#30H ;將30H存入ACC
MOV R0,#25H ;指定暫存位置
XCHD A,@R0 ;將25H之低四位元移入ACC
MOV 37H,A ;將ACC存入37H位置
INC R0 ;下一個暫存位置
XCHD A,@R0 ;將26H之低四位元移入ACC
MOV 36H,A ;將ACC存入36H位置
RET
;=========================================================
;=========================================================
CHAR:
DB 04H,0EH,1FH,00H ;AM
DB 00H,00H,00H,00H
DB 00H,00H,00H,00H ;PM
DB 1FH,0EH,04H,00H
;=========================================================
END
[/code]
編輯記錄
src 重新編輯於 2007-12-05 12:23:19, 註解 無‧
系統時間:2024-05-07 20:12:50
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!