(1)发送程序
#include <reg52h>
static bit OP; //红外发射管的亮灭
static unsigned int count; //延时计数器
static unsigned int endcount; //终止延时计数
static unsigned int temp; //按键
static unsigned char flag; //红外发送标志
static unsigned char num;
sbit ir_in=P3^4;
char iraddr1; //十六位地址的第一个字节
char iraddr2; //十六位地址的第二个字节
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 2009-8-11 <br>4 <br>红外数据传输 <br>0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳数码管 0~~f
void SendIRdata(char p_irdata);
void delay(unsigned int);
void keyscan();
/主函数/
void main(void)
{
num=0;
P2=0x3f;
count = 0;
flag = 0;
OP = 0;
ir_in= 0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFF;
TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
TR0 = 1;//开始计数
iraddr1=3;//00000011
iraddr2=252;//11111100
do{keyscan(); <br>}while(1);
}
/定时器0中断处理 /
void timeint(void) interrupt 1
{
TH0=0xFF;
TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次
count++;
if (flag==1)
{
OP=~OP;
}
else
{
OP = 0;
}
ir_in= OP;
}
void SendIRdata(char p_irdata)
{ 2009-8-11
5
红外数据传输
int i;
char irdata=p_irdata;
//发送9ms的起始码
endcount=223;
flag=1;
count=0;
do{}while(count<endcount);
/发送45ms的结果码/
endcount=117;
flag=0;
count=0;
do{}while(count<endcount);
/发送十六位地址的前八位/
irdata=iraddr1;
for(i=0;i<8;i++)
{
/先发送056ms的38KHZ红外波(即编码中056ms的低电平)/
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
/停止发送红外信号(即编码中的高电平)/
if(irdata-(irdata/2)2) //判断二进制数个位为1还是0
{
endcount=41; //1为宽的高电平
}
else
{
endcount=15; //0为窄的高电平
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
/发送十六位地址的后八位/
irdata=iraddr2;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{ 2009-8-11
6
红外数据传输
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
/发送八位数据/
irdata=p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
/发送八位数据的反码/
irdata=~p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
if(irdata-(irdata/2)2)
{
endcount=41;
}
else
{
endcount=15;
}
flag=0;
count=0;
do{}while(count<endcount);
irdata=irdata>>1;
}
2009-8-11
7
红外数据传输
endcount=10;
flag=1;
count=0;
do{}while(count<endcount);
flag=0;
}
void delay(unsigned int z)
{
unsigned char x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/4×4键盘扫描按下按键发射数据/
void keyscan()
{
P1=0xfe;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
P2=table[num-1];
SendIRdata(table[num-1]);
}
P1=0xfd;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed:num=5;
break;
case 0xdd:num=6;
break;
case 0xbd:num=7;
break;
case 0x7d:num=8; 2009-8-11
8
红外数据传输
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
P2=table[num-1];
SendIRdata(table[num-1]);
}
P1=0xfb;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xeb:num=9;
break;
case 0xdb:num=10;
break;
case 0xbb:num=11;
break;
case 0x7b:num=12;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
P2=table[num-1];
SendIRdata(table[num-1]);
}
P1=0xf7;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7:num=13;
break;
case 0xd7:num=14;
break;
case 0xb7:num=15;
break;
case 0x77:num=16;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
} 2009-8-11
9
红外数据传输
P2=table[num-1];
SendIRdata(table[num-1]);
}
}
(2)接收程序
#include"reg52h"
#define uchar unsigned char
#define uint unsigned int
uchar dis_num,num,num1,num2,num3;
sbit led=P1^0;
unsigned char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e}; //共阳数码管 0~~f
sbit prem =P3^2; //定义遥控头的接收脚
uchar ram[4]={0,0,0,0};//存放接受到的4个数据 地址码16位+按键码8位+按键码取反的8位
void delaytime(uint time) //延迟90uS
{
uchar a,b;
for(a=time;a>0;a--)
{
for(b=40;b>0;b--);
}
}
void rem()interrupt 0 //中断函数
{
uchar ramc=0; //定义接收了4个字节的变量
uchar count=0; //定义现在接收第几位变量
uint i=0; //此处变量用来在下面配合连续监测9MS 内是否有高电平
prem=1;
for(i=0;i<1100;i++) //以下FOR语句执行时间为8MS左右
{
if(prem) //进入遥控接收程序首先进入引导码的前半部判断,即:是否有9MS左右的低电平
return; //引导码错误则退出
}
while(prem!=1); //等待引导码的后半部 45 MS 高电平开始的到来。
delaytime(50); //延时大于45MS时间,跨过引导码的后半部分,来到真正遥控数据32位中
//第一位数据的056MS开始脉冲
for(ramc=0;ramc<4;ramc++)//循环4次接收4个字节
{ for(count=0;count<8;count++) //循环8次接收8位(一个字节)
{
while(prem!=1); //开始判断现在接收到的数据是0或者1 ,首先在这行本句话时,
//保已经进入数据的056MS 低电平阶段
//等待本次接受数据的高电平的到来。
delaytime(9);//高电平到来后,数据0 高电平最多延续056MS,而数据1,高电平可 2009-8-11
10
红外数据传输
//延续166MS大于08MS 后我们可以再判断遥控接收脚的电平,
if(prem) //如果这时高电平仍然在继续那么接收到的数据是1的编码
{
ram[ramc]=(ram[ramc]<<1)+1;//将目前接收到的数据位1放到对应的字节中
delaytime(11); //如果本次接受到的数据是1,那么要继续延迟1MS,这样才能跨入
//下个位编码的低电平中(即是开始的056MS中)
}
else //否则目前接收到的是数据0的编码
ram[ramc]=ram[ramc]<<1; //将目前接收到的数据位0放到对应的字节中
} //本次接收结束,进行下次位接收,此接收动作进行32次,正好完成4个字节的接收
}
if(ram[2]!=(~(ram[3]&0x7f))) //本次接收码的判断
{
for(i=0;i<4;i++) //没有此对应关系则表明接收失败,清除接受到的数据
ram[i]=0;
return ;
}
dis_num=ram[2]; //将接收到的按键数据赋给显示变量
}
main()
{
IT0=1; //设定INT0为边沿触发
EX0=1; //打开外部中断0
EA=1; //全局中断开关打开
while(1)
{
switch(dis_num)
{
case 0x81: num=0; break;
case 0xcf: num=1; break;
case 0x92: num=2; break;
case 0x86: num=3; break;
case 0xcc: num=4; break;
case 0xa4: num=5; break;
case 0xa0: num=6; break;
case 0x8f: num=7; break;
case 0x80: num=8; break;
case 0x84: num=9; break;
case 0x88: num=10;break;
case 0xe0: num=11;break;
case 0xb1: num=12;break;
case 0xc2: num=13;break;
case 0xb0: num=14;break;
case 0xb8: num=15;break;
}
P2=table[num];
P1=0x01;
delaytime(5);
}
}
首先,检查红外遥控器是否被正确连接到Arduino上,并确保正确的电源供应。其次,检查红外遥控器的编码是否正确。如果没有正确的编码,可以使用特定的红外遥控器编码库,或者使用红外遥控器编码器程序来实现正确的编码。最后,确保你的代码正确地发送和接收红外信号。
这是采用STC12C5A60S2单片机的红外解码程序及其说明。
;采用脉宽调制的串行码,以脉宽为0565ms、间隔056ms、周期为1125ms的组合表示二进制的"0";
;以脉宽为0565ms、间隔1685ms、周期为225ms的组合表示二进制的"1
;上述"0"和"1"组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,
;达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射
;遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,
;防止不同机种遥控码互相干扰。该芯片的用户识别码固定为十六进制01H
;后16位为8位 *** 作码(功能码)及其反码。
;当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),
;一个结果码(45ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)
;和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,
;接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(25ms)组成。
;
;解码的关键是如何识别"0"和"1",接收端而言,"0"是056ms的高+056ms的低。"1"是168ms的高+056ms的低。
;所以可以根据高电平的宽度区别"0"和"1"。当高电平出现时开始延时,056ms以后,若读到的电平为低,
;说明该位为"0",反之则为"1",为了可靠起见,延时必须比056ms长些,但又不能超过112ms,否则如果该位为"0",
;读到的已是下一位的高电平,因此取(112ms+056ms)/2=084ms最为可靠,一般取084ms左右均可。
;为了共用引导部分延时程序,这里用09ms延时。
;-------------红外解码程序---------------------------
EXINT0:
PUSH ACC
PUSH PSW
PUSH 1
PUSH 2
PUSH 6
CLR EA ;暂时关闭中断请求
MOV R6,#10
EXINT10:
LCALL DELAY09MS ;调用900us延时子程序
JB IRIN,INTOUT1 ;判断P32是否有高电平,如果有就退出解码程序
DJNZ R6,EXINT10 ;循环10次,检测在900微妙中是否存在高电平。以上完成对遥控信号的9000微秒的初始低电平信号的识别。
JNB IRIN,$ ;等待高电平避开9毫秒低电平引导脉冲
LCALL DELAY45MS ;延时45毫秒
;-------------接受32位代码--------------------------
MOV R1,#IRUSERL
MOV R2,#04H
EXINT101:
MOV R6,#08H ;每组数据位8位
EXINT102:
JNB IRIN,$ ;等待地址码第一组数据的高电平信号
LCALL DELAY09MS ;高电平开始后延时判断信号此时的高/低状态
MOV C,IRIN ;将P32引脚此时的电平状态0或1存入C中
JNC INT1OUT ;如果为0跳出
LCALL DELAY1MS
INT1OUT:
MOV A,@R1
RRC A ;将C中的数据0/1移入A中最低位
MOV @R1,A ;将A中的数据暂存在R1
DJNZ R6,EXINT102 ;接受完8位代码
INC R1
DJNZ R2,EXINT101 ;接受完4组32位代码
;--------------数据码比较-------------------------------
MOV A,IRDATAL
; LCALL SENDRXDAT
MOV A,IRDATAL
CPL A
CJNE A,IRDATAH,INTOUT1 ;判断数码正误,不等退出
MOV IR_DAT,IRDATAL ;相等则保存正确数据
MOV A,IR_DAT
; LCALL SENDRXDAT
SETB IRBIT
INTOUT1:
LCALL DELAY45MS
SETB EA ;允许中断
POP 6
POP 2
POP 1
POP PSW
POP ACC
RETI
;;110592900=9953
DELAY09MS: ;6
PUSH 4 ;4
PUSH 3 ;4
MOV R4,#20 ;2
DLY900:
MOV R3,#122 ;2
DJNZ R3,$ ;4
DJNZ R4,DLY900 ;4
MOV R4,#11 ;2
DJNZ R4,$ ;4
POP 3 ;3
POP 4 ;3
RET ;4
;TOTAL=9952
;;110592560=6193
DELAY056: ;6
PUSH 4 ;4
PUSH 3 ;4
MOV R4,#12 ;2
DLY5600:
MOV R3,#122 ;2
DJNZ R3,$ ;4
DJNZ R4,DLY5600 ;4
MOV R4,#71 ;2
DJNZ R4,$ ;4
POP 3 ;3
POP 4 ;3
RET ;4
;TOTAL=6194
;;1105924500=49766
DELAY45MS: ;6
PUSH 4 ;4
PUSH 3 ;4
MOV R4,#52 ;2
DLY45:
MOV R3,#236 ;2
DJNZ R3,$ ;4
DJNZ R4,DLY45 ;4
MOV R4,#85 ;2
DJNZ R4,$ ;4
POP 3 ;3
POP 4 ;3
RET ;4
;;TOTAL=49768
;;1105921000=11059
DELAY1MS: ;6
PUSH 4 ;4
PUSH 3 ;4
MOV R4,#20 ;2
DLY1MS:
MOV R3,#136 ;2
DJNZ R3,$ ;4
DJNZ R4,DLY1MS ;4
MOV R4,#8 ;2
DJNZ R4,$ ;4
POP 3 ;3
POP 4 ;3
RET ;4
;TOTAL=11060
;;
DELAY100US: ;6
PUSH 4 ;4
MOV R4,#140 ;2
DJNZ R4,$ ;4
MOV R4,#131 ;2
DJNZ R4,$ ;4
POP 4 ;3
RET ;4
;TOTAL=1105
;;
,空调器的遥控码比较长,达100多位,分析其规律比较难,但是先要会记录其主要代码,用定时器记录其高低电平的时间依次存入RAM中,待一帧数据结束后,再存入EEPROM中,可以发往上位机进行分析
也可以不加识别地再次调用,这样会占用较大的EEPROM空间
因此不能记录其所有的按键状态 同样是开机按键,制冷和制热状态下的遥控码是不同的
//////////////////////////////////////
//晶振频率为6MHz 一个机器周期2us //
//实现按键地址码、指令码的数码管显示//
//2010-06-01 //
//////////////////////////////////////
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
bit overflag,dataover;//开始接收数据,数据处理完毕
uchar timedata;//定时器0溢出次数
uchar chubus[33];//33Byte数据 timedata组成的数组
uchar jieguos[4];//地址码,地址反码,数据码,数据反码;
void initial()//初始化
{
IT0=1;EX0=1;//负边沿触发
TMOD=0x01;ET0=1;TR0=1;//模式1,十六位定时器
TH0=0xff;TL0=0x06;//05ms溢出
EA=1; //开总中断
}
void time0() interrupt 1//定时器0中断
{TH0=0xff;TL0=0x06;
timedata++;
}
void ex0() interrupt 0//外部中断0,接收数据
{
static bit startflag;//开始接收
static uchar i;
if(startflag)
{
if(timedata<32&&timedata>=16) i=0;
chubus[i]=timedata;
timedata=0;
i++;
if(i==33){overflag=1;i=0;}
}
else
{
startflag=1;
timedata=0;
}
}
void chulidata()
{
uchar chubu;//初步数据
uchar jieguo;//结果数据
uchar x,y,z=1;
for(x=0;x<4;x++)//处理四组数据
{
for(y=1;y<=8;y++)//处理一组数据8Byte
{
chubu=chubus[z];
jieguo=jieguo>>1;
if(chubu>3) jieguo=jieguo|0x80;//大于15mS为1
z++;
}
jieguos[x]=jieguo;
jieguo=0;
}
dataover=1;
}
void delay(uint z)
{
uint x ,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display()
{
uchar gao,gao1;
uchar di,di1;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
gao1=table[jieguos[0]/16];
di1=table[jieguos[0]%16];
gao=table[jieguos[2]/16];
di=table[jieguos[2]%16];
dula=1;
P0=gao1;
dula=0;
P0=0xff;
wela=1;
P0=0x7e;
wela=0;
delay(2);
dula=1;
P0=di1;
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(2);//地址码
dula=1;
P0=gao;
dula=0;
P0=0xff;
wela=1;
P0=0x77;
wela=0;
delay(2);
dula=1;
P0=di;
dula=0;
P0=0xff;
wela=1;
P0=0x6f;
wela=0;
delay(2);//指令码
}
void main()
{
initial();//初始化
while(1)
{
if(overflag)//数据接收完毕
{
chulidata();//处理数据,完成标志dataover
overflag=0;
}
if(dataover)
{
display();//数码管显示
}
}
}
以上就是关于急求红外发射与解码的c程序全部的内容,包括:急求红外发射与解码的c程序、arduino红外遥控器编码错误、51单片机红外接收端的程序怎么写,我想知道写的方法和原理,最好有一个具体的模版,好让我参考.等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)