;每按一下INT0按鍵,即可七段顯示器顯示的數字+1
;從0~9,再由9~0,數字越大,七段顯示器跑馬燈(從最左邊到最右邊)速度就越慢
;LED燈顯示2進位的按鈕次數(在這題目沒強迫要求 故顯示數字與七段一樣)
ORG 00H
JMP BEGIN
ORG 03H ;外部中斷#0的中斷向量地址
AJMP INTT0 ;執行外部中斷#0的中斷服程式
ORG 30H
BEGIN:

MOV SP,#60H ;設定堆疊指標
MOV IE,#81H ;設定外部中斷#0的致能旗標(EA=1、EX0=1)
MOV R2,#70H ;初始中斷次數記錄器 ;R2應該是存案的次數
MOV R4,#0AH ;初始計數器暫存器=10
MOV 31H,#02H;將記憶體位置31H放入#02H ;這是用來增減call delay的時間
MOV 34H,#01H;將記憶體位置34H放入#01H ;當作旗標 #01H=遞增 #02H=遞減

MOV P0,R2 ;將R2顯示在R0,顯示=0 ;這行沒用到
MOV R3,#01H ;R3=#01H的時候遞增#R3=02H時候遞減 ;這行沒用到

LOOP:
CALL CH0 ;呼叫變化方式#0之副程式
JMP L0 ;重新再跳回LOOP

L0: JMP LOOP

;外部中斷#0之中斷服務程式
;需求:從0開始遞增+1,到9之後開始遞減
;設定位置是R2
;想法:不斷遞增,到R2=9的時候,跳到某個區塊作遞減,否則執行IN1
;中斷呼叫
INTT0:
CLR EX0
PUSH ACC ;應該是將累加器存入堆疊

MOV R3,34H ;讀取34H位置的內容 放入R3
DJNZ R3,CON2 ;R3-1後,等於0則執行CON1(遞增),否則跳CON2(遞減)

CON1:
MOV A,31H ;取31H位置,放入A
INC A ;遞增1
MOV 31H,A ;放回31H(這是設定CALL DELAY時間長短)

INC R2 ;R2遞增(七段顯示器述職暫存器)
MOV A,R4 ;R4放入暫存器A(計數器計算:就是回圈的意思)
SUBB A,#01H ;計數器-1
MOV R4,A ;放回R4

JNZ IN1 ;A=0,則下一個指令;A!=0否則直接呼叫去彈跳IN1
MOV 34H,#02H ;倘若到9,則將34H位置設定成#02H(旗標:遞減)
MOV R2,#79H ;R2設定 ;七段顯示器為最左邊,數值=9
MOV R4,#0AH ;R4設定 ;計數器=10


CON2:
MOV A,31H ;和上面一樣,存取31H位置到A做遞減
DEC A ;這是減少CALL DELAY時間
MOV 31H,A ;放回去31H

DEC R2 ;R2遞減
MOV A,R4 ;R4放入暫存器A,做回圈
SUBB A,#01H ;-1後放回R4
MOV R4,A


JNZ IN1 ;A=0,則下一個指令;A!=0否則直接呼叫去彈跳IN1
MOV 34H,#01H ;倘若R4=0,則設定旗標01(遞增)
MOV R2,#70H ;設定R2 ;位置最左邊,數值為0
MOV R4,#0AH ;設定R4計數器=10

IN1:
CALL DELAY
JNB P3.2,IN1 ;去彈跳
SETB EX0
; MOV P0,R2 ;這行如果不刪除,在每次按鈕時,會在最左邊位置顯示下個數字
POP ACC ;堆疊推出ACC(恢復)

ANL A,#0F0H ;取得低四位元(這段是為了讓中斷產生時,數值立刻改變,不是等到下輪才改變)
MOV 32H,A ;放入32H位置暫存
MOV A,R2 ;取得R2內容 ;由於不知道中斷何時產生,故要刪除R2低四為元內容
ANL A,#0FH ;消除R2低四位元,也就是顯示數值
ADD A,32H ;將高四位元與暫存(中斷增加的)低四位元加起來 ;完工

RETI ;回去

;變化方式:
;七段顯示器從左邊向右邊位移
;將暫存器A設定值放成#81H,每次位移減掉#10H,call delay_264.
CH0:

;此段要取得顯示的數值,故減掉高四位元內容
;目的要將案的次數放入P1(LED燈),用二進位表示
MOV A,R2
SUBB A,#70H
MOV R1,A


;將R2放入P0,R1放入P1,CALL DEALY(顯示開始)
MOV A,R2
MOV P0,A
MOV P1,R1

;最笨方法之暴力法顯示開始,每次-#10H,就是向右移一位(跑馬燈)
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS
SUBB A,#10H
MOV P0,A
CALL DELAY_264mS

RET



;延遲時間之副程式1
DELAY:
MOV R7,#00H
D1:
MOV R6,#00H
DJNZ R6,$
DJNZ R7,D1
RET

DELAY_264mS:
MOV R5,31H ;存入31H內容,藉此改變DELAY時間長短
D2: CALL DELAY
DJNZ R5,D2 ;這裡再CALL上面的DELAY
RET
END