|
這款單片機紅外線萬能學習遙控器,使用的單片機是STC15F104單片機,長按進入學習,這樣就有3個學習鍵,電路簡單,容易制作,缺點:測試了一下,效果不錯,但是還發(fā)現(xiàn)個問小題,就是按鍵發(fā)射信號時稍微按久了點就會進入從新學習的狀態(tài)中,這時已學習的波形也被擦除了。
;STC15F104E 3路學習萬能遙控器
;內部振蕩11.0592M
;EPPROM寄存器
IAP_DATA EQU 0C2H
IAP_ADDRH EQU 0C3H
IAP_ADDRL EQU 0C4H
IAP_CMD EQU 0C5H
IAP_TRIG EQU 0C6H
IAP_CONTR EQU 0C7H
;***********************
;F38_4KHZ EQU 0FF70H ;38.4KHZ 1T MODE (65536-11059200/2/38400)
;F38_4KHZ EQU 0FFF4H ;38.4KHZ 12T MODE(65536-11059200/2/38400/12)
AUXR EQU 08EH
INT_CLKO EQU 08FH ;輸出時鐘使能
K0 BIT P3.0;按鍵1
K1 BIT P3.1;按鍵2
K2 BIT P3.2;按鍵3
LED BIT P3.3;指示燈
IR BIT P3.4;紅外接收頭
T1CLKO BIT P3.5;紅外發(fā)射管
;****************************
ORG 0
LJMP START
ORG 0BH
LJMP INT_T0;T0中斷
ORG 30H
START:;初始化
MOV R0,#20H
QL:
MOV @R0,#0;內存清0
INC R0
CJNE R0,#80H,QL
;MOV AUXR,#40H ; 1T
MOV P3,#0FFH;拉高管腳
MOV AUXR,#00H ;定時器12T模式
MOV TMOD,#00H ;定時器16位自動重裝
;--------------------
MOV TH1,#0FFH ;38K方波定時T1
MOV TL1,#0F4H
SETB TR1
;MOV INT_CLKO,#02H;發(fā)射38K
;MOV INT_CLKO,#00H;停止發(fā)射
;-----------------------------
MAIN:;主程序
CALL KEY0
CALL KEY1
CALL KEY2
JMP MAIN
;-----------------------------
KEY0:
JB K0,KEY0OUT
CALL DELAY20MS;延時消抖
JB K0,KEY0OUT
;-----------------
CALL OPEN_T0INT;打開T0中斷判斷長按
;-----------------
JBC 0,XUEXI0;長按,跳轉到學習功能
JNB K0,$-3;短按等待放開
;-----------------
CLR TR0;關T0
CLR ET0;關T0中斷
CLR EA;發(fā)射關中斷
MOV DPTR,#1000H;第1扇區(qū)
CALL FFSS;紅外發(fā)射
KEY0OUT:
RET
XUEXI0:;學習
MOV DPTR,#0;第1扇區(qū)
CALL ERASE;扇區(qū)擦除,做好寫入準備
MOV DPTR,#1;第1扇區(qū)第2字節(jié)
CALL XIEXI;紅外接收,存入第1扇區(qū)
RET
;************************
KEY1:
JB K1,KEY1OUT
CALL DELAY20MS;延時消抖
JB K1,KEY1OUT
;-----------------
CALL OPEN_T0INT;打開T0中斷判斷長按
;-----------------
JBC 0,XUEXI1;長按跳轉到學習
JNB K0,$-3;等待放開
;-----------------
CLR TR0;關T0
CLR ET0;關T0中斷
CLR EA;關中斷
MOV DPTR,#1200H;第2扇區(qū)
CALL FFSS;紅外發(fā)射
KEY1OUT:RET
XUEXI1:;學習
MOV DPTR,#200H;第2扇區(qū)
CALL PDSQ;讀數(shù)判斷扇區(qū)是否為空
MOV DPTR,#201H;第2扇區(qū)第2字節(jié)
CALL XIEXI;紅外接收,存入第2扇區(qū)
RET
;************************
KEY2:
JB K2,KEY2OUT
CALL DELAY20MS;延時消抖
JB K2,KEY2OUT
;-----------------
CALL OPEN_T0INT;打開T0中斷判斷長按
;-----------------
JBC 0,XUEXI2;長按跳轉到學習
JNB K0,$-3;等待放開
;-----------------
CLR TR0;關T0
CLR ET0;關T0中斷
CLR EA;關中斷
MOV DPTR,#1300H;第2扇區(qū)
CALL FFSS;紅外發(fā)射
KEY2OUT:RET
XUEXI2:;學習
MOV DPTR,#300H;第2扇區(qū)
CALL PDSQ;讀數(shù)判斷扇區(qū)是否為空
MOV DPTR,#301H;第2扇區(qū)第301字節(jié)
CALL XIEXI;紅外接收,存入第2扇區(qū)
RET
;***********************
PDSQ:;讀數(shù)判斷扇區(qū)是否為空,是空就擦除
MOV R1,#200;讀200個字節(jié)
ZDKA:;
CALL EEPROMR
INC DPTR
CJNE A,#0FFH,RESA;跳到扇區(qū)擦除
DJNZ R1,ZDKA;是否讀完
RET
RESA:
CALL ERASE;扇區(qū)擦除
RET
;*********************
;-----------------------
OPEN_T0INT:;打開T0中斷
CLR 0;清長按標志位
MOV 2FH,#0;清計數(shù),每計一次70MS
MOV TH0,#0;定時器0初值
MOV TL0,#0
CLR TF0
SETB ET0;開T0中斷
SETB TR0;開T0
SETB EA
RET
;***************************
INT_T0:;T0中斷,判斷長按,長按標志位0置1
INC 2FH;中斷計數(shù),
MOV A,2FH
CJNE A,#12,INT_T0OUT;70MS*12=840MS
SETB 0;置1
CLR TR0
CLR ET0
CLR EA
INT_T0OUT:
RETI
;***************************
;***************************
XIEXI:;;紅外接收;存入EEPROMW
PUSH DPL;保護指針
PUSH DPH
CLR 2;清判斷位
CLR LED;亮燈
MOV R1,#0;高電平和低電平總數(shù)
CLR TR0;停止計時
X0: JB IR,X0;等待接收頭,無信號返回等待
MOV TH0,#0;;定時器初值歸0
MOV TL0,#0
SETB TR0;有信號開始計數(shù)
;-------------------
WAIT0:JBC TF0,XOUT;等待超時;超過70MS退出
JNB IR,WAIT0;等待高電平到來
CLR TR0;停止計數(shù),存低電平時長
;-------------------
BAOCUN:;存低(高)電平時長
MOV A,TH0;高位
CPL A;取反計數(shù)值就是定時初值
CALL EEPROMW;寫一字節(jié)EEPROMW大約60US
INC DPTR;下一地址
MOV A,TL0;低位
CPL A;取反
CALL EEPROMW;寫一字節(jié)EEPROMW大約60US
;-------------------
MOV TH0,#0;定時器初值歸0
MOV TL0,#6EH;補償120US
SETB TR0;開始計數(shù)
INC DPTR;下一地址
INC R1;電平個數(shù)加1
CPL 2;取反判斷位,初始是0
JNB 2,WAIT0;是0就跳到等待高電平到來
;***********************************
WAIT1:JBC TF0,XOUT;等待超時
JB IR,WAIT1;是1就等待低電平到來
CLR TR0;停止計時
;---------------------------
JMP BAOCUN;存高電平時長
XOUT:;退出
CLR TR0;停止計時
POP DPH;指針出棧
POP DPL
DEC DPL;減1就是第1字節(jié)地址;用來保存電平總數(shù)
MOV A,R1;電平總數(shù)
CALL EEPROMW;寫入扇區(qū)第1個地址
SETB LED;關燈
RET
;***************************
;***************************
FFSS:;紅外發(fā)射
CLR LED;;開燈
MOV A,#0;
MOVC A,@A+DPTR
MOV R1,A;從第1扇區(qū)第1地址取出電平總數(shù)
CLR TR0;停止計數(shù)
INC DPTR;下一地址開始為發(fā)射數(shù)據(jù)時長
FFSS0:
MOV INT_CLKO,#02H;發(fā)射38K紅外(A版T1為3.5)
;***************************
ZCZ:;讀出定時時長裝入定時器
MOV A,#0;
MOVC A,@A+DPTR
MOV TH0,A
INC DPTR;下一地址
MOV A,#0
MOVC A,@A+DPTR
;---------------------
CLR C;數(shù)據(jù)修正,10US左右
ADD A,#10
MOV TL0,A
MOV A,#0
ADDC A,TH0
MOV TH0,A
;***************************
SETB TR0;開始計時
INC DPTR;下一地址
JNB TF0,$;等待溢出
MOV INT_CLKO,#00H;停止發(fā)射
SETB P3.5;熄滅紅外管
CLR TF0;清溢出位
CLR TR0;停止計數(shù)
;-----------------------
DJNZ R1, FFSS1;電平數(shù)-1是否完畢
SETB P3.5;熄滅紅外管
SETB LED;;關燈
RET
FFSS1:
MOV A,#0;裝入初值
MOVC A,@A+DPTR
MOV TH0,A
INC DPTR;下一地址
MOV A,#0
MOVC A,@A+DPTR
;---------------------
CLR C;數(shù)據(jù)修正
ADD A,#10
MOV TL0,A
MOV A,#0
ADDC A,TH0
MOV TH0,A
;***************************
SETB TR0;開始計數(shù)
INC DPTR;下一地址
JNB TF0,$;等待溢出
CLR TF0
CLR TR0;停止計數(shù)
;-----------------------
DJNZ R1,FFSS0;電平數(shù)-1是否完畢
;***************************
MOV INT_CLKO,#00H;停止發(fā)射
SETB P3.5;熄滅紅外管
SETB LED;關燈
RET
;******************
;EPPROM讀寫
;******************
ERASE:;擦除
MOV IAP_CONTR,#83H;允許IAP/IAP操作
MOV IAP_CMD,#3 ;扇區(qū)擦除
MOV IAP_ADDRH,DPH ;送高地址
MOV IAP_ADDRL,DPL ;送低地址
ACALL IAPXX ;觸發(fā)
RET
;************************
EEPROMW:;寫
MOV IAP_CONTR,#83H;允許IAP/IAP操作
MOV IAP_CMD,#2 ;送寫命令
MOV IAP_ADDRH,DPH ;送高地址
MOV IAP_ADDRL,DPL ;送低地址
MOV IAP_DATA,A ;A是要寫入的數(shù)據(jù)
ACALL IAPXX ;觸發(fā)
RET
;************************
EEPROMR:;讀
MOV IAP_CONTR,#83H;允許IAP/IAP操作
MOV IAP_CMD,#1 ;送讀命令
MOV IAP_ADDRH,DPH ;送高地址
MOV IAP_ADDRL,DPL ;送低地址
ACALL IAPXX ;觸發(fā)
MOV A,IAP_DATA ;讀出的數(shù)據(jù)放到A
RET
;************************
IAPXX:;觸發(fā)
;CLR EA ;關中斷在觸發(fā)之前
MOV IAP_TRIG, #5AH;和11F/15F的相同,而與12C2052的不同
MOV IAP_TRIG, #0A5H ;
NOP
NOP
NOP
;SETB EA
RET
;----------------------
IAP_DISABLE:;禁止IAP/IAP操作
MOV IAP_CONTR,#0
MOV IAP_CMD,#0
MOV IAP_TRIG,#0
MOV IAP_ADDRH,#0FFH
MOV IAP_ADDRL,#0FFH
RET
;----------------------
DELAY20MS: ;延時
MOV R7,#0EH
DL1:
MOV R6,#0A8H
DL0:
MOV R5,#16H
DJNZ R5,$
DJNZ R6,DL0
DJNZ R7,DL1
RET
END
|
|