8051 ASM
;────────────────────────────────
;記憶體宣告,宣告各中斷程式存放在記憶體的位址
;────────────────────────────────
ORG 0H ;主程式存放位址,從0開始
AJMP MAIN ;跳到主程式段,執行主程式
ORG 03H ;外部中斷INT0服務程式存放位址,從03H開始
AJMP INT0 ;跳到外部中斷INT0,執行外部中斷0服務程式
;────────────────────────────────
;主程式開始
;────────────────────────────────
;使用副程式有
; INIT_SERIAL:設定串列埠的初值
MAIN: ;主程式名稱
ACALL INIT_SERIAL ;設定串列埠的初值
M5:
NOP
SJMP M5 ;不做任何事,等待中斷
;────────────────────────────────
;中斷服務程式0開始
;────────────────────────────────
INT0: ;外部中斷INT0服務程式名稱
PUSH PSW ;貯存狀態暫存器
; PUSH A ;貯存累加器A,因為這裡用到A
PUSH IE ;貯存中斷致能暫存器
CLR EA ;暫停接受其它中斷
ACALL DELAY0_1S ;延遲0.1秒,避免彈跳
MOV R2,#49 ;前置送出的49bytes 0x00
INIT_00H:
MOV A,#0 ; 49 bytes = 13ms
MOV SBUF,A ;傳送IR編碼(00H)
DJNZ R2,INIT_00H
MOV R2,#11 ;傳送11個bytes的00H
INIT_FFH:
MOV A,#0FFH ; 11 bytes = 3ms
MOV SBUF,A ;傳送IR編碼(0FFH)
DJNZ R2,INIT_FFH
MOV R2,#7 ;傳送7次的0x00、0xFF(最後一次不含0xFF)
NEXT_VAL:
MOV A,#0 ;設定傳送的值
MOV R3,#4 ;1ms on
AT_1MS_ON:
MOV SBUF,A ;傳送IR編碼(00H)
DJNZ R3,AT_1MS_ON
MOV A,#0FFH
MOV R3,#4 ;1ms off
JMP FINISH ;到FINISH處檢查是否為第七次執行
AT_1MS_OFF:
MOV SBUF,A ;傳送IR編碼(FFH)
DJNZ R3,AT_1MS_OFF
DJNZ R2,NEXT_VAL
FINISH:
CJNE R2,#1,AT_1MS_OFF ;若不是第七次執行,則回到AT_1MS_OFF
MOV A,#0
MOV SBUF,A ;送出最後一筆00H
SETB EA ;重新致能中斷
; POP A ;載入原累加器A的值
POP PSW ;載入原狀態暫存器的值
RETI ;中斷返回
;────────────────────────────────
;延遲0.1秒副程式
;────────────────────────────────
DELAY0_1S:;副程式名稱
MOV R1,#250 ;設定迴圈250次,每次500us
A1: ;共延遲0.1s
MOV R0,#250 ;設定迴圈250次
A0: DJNZ R0,A0 ;設定迴圈250次,每次2us
DJNZ R1,A1
RET ;延遲程式返回
;────────────────────────────────
;串列埠的初始化
;────────────────────────────────
;串列埠的模式設定SCON
;串列埠的傳輸率設定 TMOD TH1 PCON TR1
;致能串列中斷 IE
INIT_SERIAL: ;設定串列埠的初值
MOV IE,#91H ;致能串列及外部中斷
MOV SCON,#40H ;設定串列模式(一對一、八位元單向傳輸)
;設定Baud Rate
MOV PCON,#80H ;雙倍率設定
MOV TMOD,#20H ;計時模式設定
MOV TH1,#0FDH ;計時值設定
SETB TR1 ;啟動計時器(38000 @ 22M OSC)
RET ;副程式返回
