|
这款单片机红外线万能学习遥控器,使用的单片机是STC15F104单片机,长按进入学习,这样就有3个学习键,电路简单,容易制作,缺点:测试了一下,效果不错,但是还发现个问小题,就是按键发射信号时稍微按久了点就会进入从新学习的状态中,这时已学习的波形也被擦除了。
;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;红外发射管
;****************************
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;发射38K
;MOV INT_CLKO,#00H;停止发射
;-----------------------------
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;发射关中断
MOV DPTR,#1000H;第1扇区
CALL FFSS;红外发射
KEY0OUT:
RET
XUEXI0:;学习
MOV DPTR,#0;第1扇区
CALL ERASE;扇区擦除,做好写入准备
MOV DPTR,#1;第1扇区第2字节
CALL XIEXI;红外接收,存入第1扇区
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扇区
CALL FFSS;红外发射
KEY1OUT:RET
XUEXI1:;学习
MOV DPTR,#200H;第2扇区
CALL PDSQ;读数判断扇区是否为空
MOV DPTR,#201H;第2扇区第2字节
CALL XIEXI;红外接收,存入第2扇区
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扇区
CALL FFSS;红外发射
KEY2OUT:RET
XUEXI2:;学习
MOV DPTR,#300H;第2扇区
CALL PDSQ;读数判断扇区是否为空
MOV DPTR,#301H;第2扇区第301字节
CALL XIEXI;红外接收,存入第2扇区
RET
;***********************
PDSQ:;读数判断扇区是否为空,是空就擦除
MOV R1,#200;读200个字节
ZDKA:;
CALL EEPROMR
INC DPTR
CJNE A,#0FFH,RESA;跳到扇区擦除
DJNZ R1,ZDKA;是否读完
RET
RESA:
CALL ERASE;扇区擦除
RET
;*********************
;-----------------------
OPEN_T0INT:;打开T0中断
CLR 0;清长按标志位
MOV 2FH,#0;清计数,每计一次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;中断计数,
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;高电平和低电平总数
CLR TR0;停止计时
X0: JB IR,X0;等待接收头,无信号返回等待
MOV TH0,#0;;定时器初值归0
MOV TL0,#0
SETB TR0;有信号开始计数
;-------------------
WAIT0:JBC TF0,XOUT;等待超时;超过70MS退出
JNB IR,WAIT0;等待高电平到来
CLR TR0;停止计数,存低电平时长
;-------------------
BAOCUN:;存低(高)电平时长
MOV A,TH0;高位
CPL A;取反计数值就是定时初值
CALL EEPROMW;写一字节EEPROMW大约60US
INC DPTR;下一地址
MOV A,TL0;低位
CPL A;取反
CALL EEPROMW;写一字节EEPROMW大约60US
;-------------------
MOV TH0,#0;定时器初值归0
MOV TL0,#6EH;补偿120US
SETB TR0;开始计数
INC DPTR;下一地址
INC R1;电平个数加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字节地址;用来保存电平总数
MOV A,R1;电平总数
CALL EEPROMW;写入扇区第1个地址
SETB LED;关灯
RET
;***************************
;***************************
FFSS:;红外发射
CLR LED;;开灯
MOV A,#0;
MOVC A,@A+DPTR
MOV R1,A;从第1扇区第1地址取出电平总数
CLR TR0;停止计数
INC DPTR;下一地址开始为发射数据时长
FFSS0:
MOV INT_CLKO,#02H;发射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;数据修正,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;停止发射
SETB P3.5;熄灭红外管
CLR TF0;清溢出位
CLR TR0;停止计数
;-----------------------
DJNZ R1, FFSS1;电平数-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;数据修正
ADD A,#10
MOV TL0,A
MOV A,#0
ADDC A,TH0
MOV TH0,A
;***************************
SETB TR0;开始计数
INC DPTR;下一地址
JNB TF0,$;等待溢出
CLR TF0
CLR TR0;停止计数
;-----------------------
DJNZ R1,FFSS0;电平数-1是否完毕
;***************************
MOV INT_CLKO,#00H;停止发射
SETB P3.5;熄灭红外管
SETB LED;关灯
RET
;******************
;EPPROM读写
;******************
ERASE:;擦除
MOV IAP_CONTR,#83H;允许IAP/IAP操作
MOV IAP_CMD,#3 ;扇区擦除
MOV IAP_ADDRH,DPH ;送高地址
MOV IAP_ADDRL,DPL ;送低地址
ACALL IAPXX ;触发
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是要写入的数据
ACALL IAPXX ;触发
RET
;************************
EEPROMR:;读
MOV IAP_CONTR,#83H;允许IAP/IAP操作
MOV IAP_CMD,#1 ;送读命令
MOV IAP_ADDRH,DPH ;送高地址
MOV IAP_ADDRL,DPL ;送低地址
ACALL IAPXX ;触发
MOV A,IAP_DATA ;读出的数据放到A
RET
;************************
IAPXX:;触发
;CLR EA ;关中断在触发之前
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
|
|