接: 51红外遥控解码(一)
;============================================
DELAY_MS:
MOV R6,#250
DELAY_MS_NEXT:
NOP
NOP
DJNZ R6,DELAY_MS_NEXT
DJNZ R7,DELAY_MS
RET
;============================================
;INPUT: R7
DELAY:
DJNZ R7,$
RET
;============================================
;向LCD写一个命令字节
;INPUT: ACC
SEND_COMMAND_BYTE:
CLR RS
CLR RW
MOV P0,A
SETB E
NOP
NOP
NOP
NOP
NOP
NOP
CLR E
MOV R7,#100
ACALL DELAY
RET
;===============================================
;向LCD写一个数据字节
;INPUT: ACC
SEND_DATA_BYTE:
SETB RS
CLR RW
MOV P0,A
SETB E
NOP
NOP
NOP
NOP
NOP
NOP
CLR E
MOV R7,#100
ACALL DELAY
RET
;======================================================
;初始化LCD
INIT_LCD:
MOV A,#30H
ACALL SEND_COMMAND_BYTE
ACALL SEND_COMMAND_BYTE
ACALL SEND_COMMAND_BYTE
MOV A,#38H ;设置工作方式
ACALL SEND_COMMAND_BYTE
MOV A,#0CH ;显示状态设置
ACALL SEND_COMMAND_BYTE
MOV A,#01H ;清屏
ACALL SEND_COMMAND_BYTE
MOV A,#06H ;输入方式设置
ACALL SEND_COMMAND_BYTE
RET
;=======================================================
;在第一行显示
;INPUT: DPTR指向要显示的内容
DISPLAY_LINE1:
MOV A,#080H
DISPLAY_LINE1_A:
ACALL SEND_COMMAND_BYTE ;设置DDRAM地址
MOV R6,#20
DISPLAY_LINE1_NEXT:
CLR A
MOVC A,@A+DPTR
ACALL SEND_DATA_BYTE
INC DPTR
DJNZ R6,DISPLAY_LINE1_NEXT
MOV R7,#100
ACALL DELAY
RET
;=======================================================
;在第二行显示
;INPUT: DPTR指向要显示的内容
DISPLAY_LINE2:
MOV A,#0C0H
AJMP DISPLAY_LINE1_A
;=======================================================
END
下面是一个用C写的遥控器程序.能在数码管上显示键码.
#include <reg52.h>
#define c(x) (x*110592/120000)
sbit Ir_Pin=P3^3;
unsigned char code Led_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,
0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极数码显示码0-F.
unsigned char code Led_Sel[]={0xe,0xd,0xb,0x7};
unsigned char Led_Buf[4]; //显示缓冲区
char Led_Index; //位选
unsigned char Ir_Buf[4]; //用于保存解码结果
//==============================================================
//数码管扫描
timer0() interrupt 1 using 1
{
TL0=65536-1000;
TH0=(65536-1000)/256; //定时器0设定约1000us中断一次,用于数码管扫描
P0=0xff;
P2=Led_Sel[Led_Index]; //位选
P0=Led_Tab[Led_Buf[Led_Index]]; //段选
if(++Led_Index>3) Led_Index=0; //四个扫描完了,到第一个数码管
}
//==============================================================
unsigned int Ir_Get_Low()
{
TL1=0;
TH1=0;
TR1=1;
while(!Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//=============================================================
unsigned int Ir_Get_High()
{
TL1=0;
TH1=0;
TR1=1;
while(Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//==============================================================
main()
{
unsigned int temp;
char i,j;
Led_Index=1;
TMOD=0x11;
TL0=65536-1000;
TH0=(65536-1000)/256; //定时器0设定约1000us中断一次,用于数码管扫描
EA=1;
ET0=1;
TR0=1;
Led_Buf[0]=0;
Led_Buf[1]=0;
Led_Buf[2]=0;
Led_Buf[3]=0; //显示区设成0
do{
restart:
while(Ir_Pin);
temp=Ir_Get_Low();
if(temp<c(8500) || temp>c(9500)) continue;//引导脉冲低电平9000
temp=Ir_Get_High();
if(temp<c(4000) || temp>c(5000)) continue;//引导脉冲高电平4500
for(i=0;i<4;i++) //4个字节
for(j=0;j<8;j++) //每个字节8位
{
temp=Ir_Get_Low();
if(temp<c(200) || temp>c(800)) goto restart;
temp=Ir_Get_High();
if(temp<c(200) || temp>c(2000)) goto restart;
Ir_Buf[i]>>=1;
if(temp>c(1120)) Ir_Buf[i]|=0x80;
}
Led_Buf[0]=Ir_Buf[2]&0xf;
Led_Buf[1]=(Ir_Buf[2]/16)&0xf;
Led_Buf[2]=Ir_Buf[3]&0xf;
Led_Buf[3]=(Ir_Buf[3]/16)&0xf; //显示结果
}while(1);
}