線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4005
推到 Plurk!
推到 Facebook!

想請教一下有關8051中斷的問題

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


發表:8
回覆:21
積分:5
註冊:2008-12-29

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-12-29 18:53:48 IP:203.68.xxx.xxx 訂閱
你好,我是剛接觸8051沒多久的新手。

我最近寫了一個程式,功能為...
程式一開始時一直跑LED的跑馬燈,直到按下按鈕發生中斷後8個LED會一起閃滅5次,
5次後會回到主程式繼續跑LED的跑馬燈。

現在我的問題是,當8個LED閃滅5次後會停約"25秒"才回到主程式。
請問這是正常的現象嗎?
還是我有哪裡沒顧慮到?


[code cpp]
;----- 暫存器定義 -----
LED_OUT EQU P2 ;LED_OUT定義為P2
TAB_NUM EQU 20H ;存入當前抓到查表的那一個位置
TIME EQU 21H ;存入DELAY時間參數
NUM_TEM EQU 22H ;計數

;------ 向量設置 ------
ORG 00H ;重置向量
JMP MAIN
ORG 03H ;外部中斷INT0向量
JMP INT0_MAIN

;----- 載入副程式 -----
#include ;載入DELAY0.1s副程式
#include ;載入DELAY10ms副程式
#include ;載入DELAY20ms副程式

;---- 設定外部中斷 ----
MAIN: SETB EA ;開啟總中斷
SETB EX0 ;開啟外部中斷 0
SETB IT0 ;設置成負緣觸發模式
MOV SP,#70H ;堆疊區由RAM的70H開始

;------ 程式開始 ------
START:
MOV LED_OUT,#0FFH ;清除LED_OUT
MOV DPTR,#TABLE ;將查表位置存入指標暫存器(DPTR)
MOV TAB_NUM,#0 ;指向查表初值

LOOP:
MOV A,TAB_NUM ;抓取第幾個查表值
MOVC A,@A DPTR ;將指定的查表值存入A
MOV LED_OUT,A ;輸出至LED_OUT

MOV TIME,#03
CALL delay_01s ;延遲0.3秒

INC TAB_NUM ;抓下一個查表值
CJNE A,#00H,LOOP ;檢查是否抓到最後一筆o。否,跳到LOOP
JMP START ;是,跳到START

TABLE: DB 11111111B ;建立查表
DB 11111110B ;PORT輸出0時LED亮
DB 11111100B
DB 11111000B
DB 11110000B
DB 11100000B
DB 11000000B
DB 10000000B
DB 00000000B

;----- 中斷副程式 -----
INT0_MAIN:
PUSH ACC ;將累加器放入堆疊區
PUSH TIME ;將TIME放入堆疊區
MOV NUM_TEM,#5
MOV TIME,#5

INT0_GO:
MOV LED_OUT,#0FFH ;清除LED_OUT
CALL delay_01s ;延遲0.5秒
MOV LED_OUT,#00H ;清除LED_OUT
CALL delay_01s ;延遲0.5秒

DJNZ NUM_TEM,INT0_GO
POP TIME ;取回TIME值
POP ACC ;取回累加器值
RETI
END

[/code]
附加檔案:4958ac3c3f0b8_8051.7z
編輯記錄
inlem2000 重新編輯於 2008-12-29 22:47:55, 註解 無‧
inlem2000 重新編輯於 2008-12-29 22:48:24, 註解 無‧
inlem2000 重新編輯於 2008-12-29 22:59:02, 註解 無‧
inlem2000 重新編輯於 2008-12-29 23:00:05, 註解 無‧
inlem2000 重新編輯於 2008-12-29 23:01:42, 註解 無‧
src
高階會員


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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-12-30 11:29:43 IP:59.115.xxx.xxx 訂閱
您好:
問題應該是載入的延遲副程式,建議自己寫延遲副程式就可以。
inlem2000
一般會員


發表:8
回覆:21
積分:5
註冊:2008-12-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-12-30 12:17:26 IP:203.68.xxx.xxx 訂閱
感謝回覆。
我當初也是這麼認為,但試過之後還是不行。

目前我覺得應該是 loop: 到 jmp start 這之間有問題,因為我有試著改短看看結果從25秒變成約1、2秒。
編輯記錄
inlem2000 重新編輯於 2008-12-30 12:49:51, 註解 無‧
src
高階會員


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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-12-30 16:18:53 IP:61.216.xxx.xxx 訂閱
進入中段時BANK相衝

[code delphi]
;----- 暫存器定義 -----
LED_OUT EQU P2 ;LED_OUT定義為P2
TAB_NUM EQU 20H ;存入當前抓到查表的那一個位置
TIME EQU 21H ;存入DELAY時間參數
NUM_TEM EQU 22H ;計數

;------ 向量設置 ------
ORG 00H ;重置向量
JMP MAIN
ORG 03H ;外部中斷INT0向量
JMP INT0_MAIN

;----- 載入副程式 -----
#include ;載入DELAY0.1s副程式
#include ;載入DELAY10ms副程式
#include ;載入DELAY20ms副程式

;---- 設定外部中斷 ----
MAIN: SETB EA ;開啟總中斷
SETB EX0 ;開啟外部中斷 0
SETB IT0 ;設置成負緣觸發模式
MOV SP,#70H ;堆疊區由RAM的70H開始

;------ 程式開始 ------
START:
MOV LED_OUT,#0FFH ;清除LED_OUT
MOV DPTR,#TABLE ;將查表位置存入指標暫存器(DPTR)
MOV TAB_NUM,#0 ;指向查表初值

LOOP:
MOV A,TAB_NUM ;抓取第幾個查表值
MOVC A,@A DPTR ;將指定的查表值存入A
MOV LED_OUT,A ;輸出至LED_OUT

MOV TIME,#03
CALL delay_01s ;延遲0.3秒

INC TAB_NUM ;抓下一個查表值
CJNE A,#00H,LOOP ;檢查是否抓到最後一筆o。否,跳到LOOP
JMP START ;是,跳到START

TABLE: DB 11111111B ;建立查表
DB 11111110B ;PORT輸出0時LED亮
DB 11111100B
DB 11111000B
DB 11110000B
DB 11100000B
DB 11000000B
DB 10000000B
DB 00000000B

;----- 中斷副程式 -----
INT0_MAIN:
PUSH PSW
SETB RS0
PUSH ACC ;將累加器放入堆疊區
PUSH TIME ;將TIME放入堆疊區
MOV NUM_TEM,#5
MOV TIME,#5

INT0_GO:
MOV LED_OUT,#0FFH ;清除LED_OUT
CALL delay_01s ;延遲0.5秒
MOV LED_OUT,#00H ;清除LED_OUT
CALL delay_01s ;延遲0.5秒

DJNZ NUM_TEM,INT0_GO
POP TIME ;取回TIME值
POP ACC ;取回累加器值
POP PSW
RETI
END
[/code]

===================引 用 inlem2000 文 章===================
感謝回覆。
我當初也是這麼認為,但試過之後還是不行。

目前我覺得應該是 loop: 到 jmp start 這之間有問題,因為我有試著改短看看結果從25秒變成約1、2秒。
編輯記錄
src 重新編輯於 2008-12-30 16:20:40, 註解 無‧
src 重新編輯於 2008-12-30 16:22:18, 註解 無‧
inlem2000
一般會員


發表:8
回覆:21
積分:5
註冊:2008-12-29

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-12-30 16:40:12 IP:203.68.xxx.xxx 訂閱
請問意思是指我暫存器庫相衝嗎?
可是我應該只有delay副程式有用到 R0 R1 R2 外其他都應該沒用到...

還是說是我弄錯你的意思了? 是的話請見諒...
src
高階會員


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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-12-30 18:08:42 IP:61.216.xxx.xxx 訂閱
是的
因為主程式及中斷副程式共用DELAY副程式,當中斷返回R0R1R2已被更改,
所以當進入中斷時選擇暫存器庫1就不會改變R0R1R2。
===================引 用 inlem2000 文 章===================
請問意思是指我暫存器庫相衝嗎?
可是我應該只有delay副程式有用到 R0 R1 R2 外其他都應該沒用到...

還是說是我弄錯你的意思了? 是的話請見諒...
inlem2000
一般會員


發表:8
回覆:21
積分:5
註冊:2008-12-29

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-12-30 18:16:31 IP:203.68.xxx.xxx 訂閱
阿,確實!
這點我的確沒想到!

我等等吃完飯後去測試一下 ^^


>測試完了,果然是這個問題呢!
感謝你解答!! ^^

↓修改過的版本
[code delphi]
;----- 暫存器定義 -----
LED_OUT EQU P2 ;LED_OUT定義為P2
TAB_NUM EQU 20H ;存入當前抓到查表的那一個位置
TIME EQU 21H ;存入DELAY時間參數
NUM_TEM EQU 22H ;計數

;------ 向量設置 ------
ORG 00H ;重置向量
JMP MAIN
ORG 03H ;外部中斷INT0向量
JMP INT0_MAIN

;----- 載入副程式 -----
#include ;載入DELAY0.1s副程式
#include ;載入DELAY10ms副程式
#include ;載入DELAY20ms副程式

;---- 設定外部中斷 ----
MAIN: SETB EA ;開啟總中斷
SETB EX0 ;開啟外部中斷 0
SETB IT0 ;設置成負緣觸發模式
MOV SP,#70H ;堆疊區由RAM的70H開始

;------ 程式開始 ------
START:
MOV LED_OUT,#0FFH ;清除LED_OUT
MOV DPTR,#TABLE ;將查表位置存入指標暫存器(DPTR)
MOV TAB_NUM,#0 ;指向查表初值

LOOP:
MOV A,TAB_NUM ;抓取第幾個查表值
MOVC A,@A DPTR ;將指定的查表值存入A
MOV LED_OUT,A ;輸出至LED_OUT

MOV TIME,#03
CALL delay_01s ;延遲0.3秒

INC TAB_NUM ;抓下一個查表值
CJNE A,#00H,LOOP ;檢查是否抓到最後一筆o。否,跳到LOOP
JMP START ;是,跳到START


TABLE: DB 11111111B ;建立查表
DB 11111110B ;PORT輸出0時LED亮
DB 11111100B
DB 11111000B
DB 11110000B
DB 11100000B
DB 11000000B
DB 10000000B
DB 00000000B


;----- 中斷副程式 -----
INT0_MAIN:
PUSH ACC ;將累加器放入堆疊區
PUSH TIME ;將TIME放入堆疊區
PUSH PSW ;將PSW放入堆疊區
CLR RS1 ;選擇暫存器庫1
SETB RS0
MOV NUM_TEM,#5 ;存入計數次數
MOV TIME,#5

INT0_GO:
MOV LED_OUT,#0FFH ;清除LED_OUT
CALL delay_01s ;延遲0.5秒
MOV LED_OUT,#00H ;清除LED_OUT
CALL delay_01s ;延遲0.5秒

DJNZ NUM_TEM,INT0_GO
POP PSW ;取回PSW值,指回暫存器庫0
POP TIME ;取回TIME值
POP ACC ;取回累加器值
RETI
END

[/code]
編輯記錄
inlem2000 重新編輯於 2008-12-30 18:45:53, 註解 無‧
inlem2000 重新編輯於 2008-12-30 18:47:53, 註解 無‧
inlem2000 重新編輯於 2008-12-30 18:48:57, 註解 無‧
系統時間:2024-04-19 20:17:41
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!