芯片IC單片機解密百科

十年專注單片機解密

89S51單片機PT2221紅外解碼匯編程序


   51單片機解碼用於區別各個廠家的遙控器的不同,而後16位為數據碼,分前8位和後8位,前後8位互為反碼,用於檢驗

   這裏BBIN导航隻接收了16位的數據,別的數據則丟掉了,對16的數據在程序中進行了檢驗

解碼的結果用兩種方式輸出:1.用串口以9600的波特率發送,2.四位一體數碼管顯示

   一體化接P3.2,即外部中斷0

   數碼管:P1口送段碼,P0口低四位送位碼

   程序中采用11.0592M的晶振,若用12M晶振隻需按程序注釋的提示選擇相應程序即可

b_bit equ 20h ;數碼管個位數存放內存位置

a_bit equ 21h ;數碼管十位數存放內存位置

ORG 0000H

AJMP MAIN;轉入主程序

ORG 0003H ;外部中斷P3.2腳INT0入口地址

AJMP INT ;轉入外部中斷服務子程序(解碼程序)

;=============以下為主程序進行CPU中斷方式設置===================================

MAIN: SETB EA ;打開CPU總中斷請求

SETB IT0 ;設定INT0的觸發方式為脈衝負邊沿觸發

SETB EX0 ;打開INT0中斷請求

AJMP $

;============以下為進入P3.2腳外部中斷子程序,也就是解碼程序======================

INT: CLR EA ;暫時關閉CPU的所有中斷請求,隻處理當前中斷,避免受外部信號幹擾

MOV R6,#10

SB: ACALL YS1;調用882微秒延時子程序

JB P3.2,EXIT;延時882微秒後判斷P3.2腳是否出現高電平如果有就退出解碼程序,(882um就出現高電平說明是幹擾信號)

DJNZ R6, SB;重複10次,目的是檢測在8820微秒內如果出現高電平就退出解碼程序

;=======以上完成對遙控信號的9ms的初始低電平信號的識別======================

JNB P3.2, $ ;等待高電平避開9毫秒低電平引導脈衝

ACALL YS2 ;延時4.74毫秒避開4.5毫秒的結果碼

MOV R7,#16;忽略前16位係統識別碼,PT2221共發送32位數據,前16位為用戶碼,後16為數據碼才是BBIN导航需要的

JJJJA: JNB P3.2,$;等待地址碼第一位的高電平信號

LCALL YS1;高電平開始後用882微秒的時間尺去判斷信號此時的高低電平狀態

MOV C,P3.2;將P3.2引腳此時的電平狀態0或1存入C中

JNC UUUA;如果為0就跳轉到UUUA

LCALL YS3;檢測到高電平1的話延時1毫秒等待脈衝高電平結束

UUUA: DJNZ R7,JJJJA

;==============到此為止,已跳過13.5ms的引導碼和前16位的用戶碼=====================

MOV R1,#1AH ;設定1AH為起始RAM區

MOV R2,#2 ;接收從1AH到1BH的2個內存,用於存放操作碼和操作反碼,

;16位數據分前8位和後8位,後8位是前8位的反碼,用於檢驗

PP: MOV R3,#8;每組數據為8位

JJJJ: JNB P3.2,$;等待地址碼第一位的高電平信號

LCALL YS1;高電平開始後用882微秒的時間尺去判斷信號此時的高低電平狀態

MOV C,P3.2;將P3.2引腳此時的電平狀態0或1存入C中

JNC UUU;如果為0就跳轉到UUU

LCALL YS3;檢測到高電平1的話延時1毫秒等待脈衝高電平結束,然後把C中的1存入R1

UUU: MOV A,@R1;將R1中的數據給A

RRC A;將C中的值0或1移入A中的最低位

MOV @R1,A;將A中的數暫時存放在R1數值的內存中

DJNZ R3,JJJJ;接收滿8位換一個內存

INC R1;對R1中的值加1,換下一個RAM

DJNZ R2,PP ;接收完8位數據碼和8位數據反碼,存放在1AH/1BH中

;==================上麵的程序已完成了16位數據碼的接收工作,下麵進行檢驗==================

MOV A,1AH

CPL A;對1AH取反後和1BH比較

CJNE A,1BH,EXIT;如果不等表示接收數據發生錯誤,放棄

;====================校驗正確則繼續執行下麵程序,不正確則作為幹擾丟棄===================

LCALL SEND ;調用串口發送程序,把16位數據碼用串口發送出去

LCALL DISPLAY ;把16位數據碼送數碼管顯示

CLR P3.5;P3.5口上的LED閃爍一次,表示解碼成功

LCALL YS2

LCALL YS2

LCALL YS2

SETB P3.5;

;==================退出子程序,解碼出錯時退出解碼子程序========================

EXIT: SETB EA ;允許中斷

RETI ;退出解碼子程序

;===================串口發送子程序============================================

SEND: mov a,1AH;將1AH中的十六進製數轉換成16進製

mov b,#16 ;10進製/16=16進製,此時輸出按鍵的16進製編碼,00~1F

div ab

SWAP A

ADD A,B

mov 30H,a ;轉換為16進製代碼後存到30H

MOV TMOD,#20H

MOV TL1,#0FDH

MOV TH1,#0FDH

MOV SCON,#40H

MOV PCON,0

CLR TI

CLR RI

SETB TR1

MOV R0,#30H

MOV A,@R0

MOV SBUF,A

WAIT: JNB TI,WAIT

CLR TI

RET

;******************************************顯示子程序********************************************

display:mov a,1AH;將1AH中的十六進製數轉換成10進製或16進製

mov b,#10 ;10進製/10=10進製,此時輸出按鍵對應的鍵號,00~31

;mov b,#16 ;10進製/16=16進製,此時輸出按鍵的16進製編碼,00~1F

div ab

mov a_bit,a ;十位在a

mov b_bit,b ;個位在b

mov dptr,#numtab ;指定查表啟始地址

mov r0,#4

dpl1: mov r1,#250 ;顯示1000次

dplop: mov a,b_bit ;取個位數

MOVC A,@A+DPTR ;查個位數的7段代碼

mov p1,a ;送出個位的7段代碼

SETB p0.0 ;開個位顯示

acall d1ms ;顯示1ms

CLR P0.0

mov a,a_bit ;取十位數

MOVC A,@A+DPTR ;查十位數的7段代碼

mov p1,a ;送出十位的7段代碼

SETB P0.1 ;開十位顯示

acall d1ms ;顯示1ms

CLR P0.1

CLR P0.2

CLR P0.3

djnz r1,dplop ;100次沒完循環

djnz r0,dpl1 ;4個100次沒完循環

ret

D1MS: MOV R4,#250 ;延時1ms

DJNZ R4,$

RET

numtab: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H ;字形碼表"0","1","2"~"7"

DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H ;字形碼表"8","9","A"~"F"

;=============延時子程序1,精確延時882微秒=========================================

;YS1: MOV R4,#20 ;12M晶振請用此句延時

YS1: MOV R4,#17 ;11.0592M晶振請用此句延時

D1: MOV R5,#20

DJNZ R5,$

DJNZ R4,D1

RET

;============延時子程序2,精確延時4740微秒==========================================

YS2: MOV R4,#10 ;

;D2: MOV R5,#235 ;12M晶振請用此句延時

D2: MOV R5,#217 ;11.0592M晶振請用此句延時

DJNZ R5,$

DJNZ R4,D2

RET

;=============延時程序3,精確延時1000微秒===========================================

YS3: MOV R4,#2;

;D3: MOV R5,#248 ;12M晶振請用此句延時

D3: MOV R5,#230 ;11.0592M晶振請用此句延時

DJNZ R5,$

DJNZ R4,D3

RET

;=========================

END