` 本帖最后由 oyl 于 2013-7-19 16:15 编辑
-------------------------------------写在前面的废话-----------------------------------------------
2012年暑假在学校没回家,参加了2012ti杯湖北省电子设计大赛。比赛的时候,看到大家在比赛之前都准备了各种模块(显示模块,电源模块,矩阵键盘...)显然他们比赛的时候就轻松多了,而我就是一个菜鸟,没什么经验,第一次参加比赛。也没准备什么模块。导致后来三天两夜的比赛中吃了大亏。所以平时要准备各种模块,和写好的程序。
--------------------------------------------------------------------------------------------------
学习红外解码的步骤:
1,搜索相关资料。我已经帮你们搜索好了。
2,理解红外解码的原理。
弄清怎么发射的和怎么接收的,主要是怎么接收的。
3,编写程序,调试,应用。
第一部分
原理:
我们先要弄清它是怎么发射的,和怎么接收的。
一、编码
遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC的uPD6121G组成发射电路为例说明编码原理。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:
采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如下图所示。
上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射。编码数据,载波,发射,接收解码如下图所示:
UPD6121G产生的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。该芯片的用户识别码固定为十六进制01H;后16位为8位操作码(功能码)及其反码。UPD6121G最多额128种不同组合的编码。
遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。一组码本身的持续时间随它包含的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,发射波形图如下图所示。
当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)组成。
这是最重要的:引导码+用户识别码+用户识别码(反码)+操作码+操作码(反码)
二、接收部分
P32 连着外部中断0
单片机上的外部中断 0
来一个下降沿就进入中断。
#include
#define uchar unsigned char
#define uint unsigned int
int irtime;
uchar disp[8];
uchar startflag;//开始标志
uchar irdata[33];//数据一共33位加上引导码
uchar bitnum;
uchar irreceok;//接收一帧数据完成
uchar ircode[4];//4个字节的数据
uchar irprosok;//处理完成
***it SH_CP=P2^4;
***it DS=P2^5;
***it ST_CP=P1^5;
uchar code wei[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
uchar code duan[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0123456789abcdef
void send_dat(unsigned dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DS=dat&0x80;
SH_CP=1;
SH_CP=0;
dat<<=1;
}
}
void timer0init(void)
{
TMOD=0X02;
TH0=0;
TL0=0;
ET0=1;
EA=1;
TR0=1;
}
void int0init(void)
{
IT0=1;
EX0=1;
EA=1;
}
void irwork()
{
//disp[0]=ircode[0]/16;
//disp[1]=ircode[0];
//disp[2]=ircode[1]/16;
//disp[3]=ircode[1];
// disp[4]=ircode[2]/16;
// disp[5]=ircode[2]/100;
// disp[6]=ircode[2]0/10;
// disp[7]=ircode[2];
switch (ircode[2])
{
case 6 : disp[6]=0;disp[7]=1;break;
case 12 :disp[6]=0;disp[7]=2 ;break;
case 47 :disp[6]=0;disp[7]=3;break;
case 4 : disp[6]=0;disp[7]=4;break;
case 14 :disp[6]=0;disp[7]=5 ;break;
case 45 :disp[6]=0;disp[7]=6;break;
case 33: disp[6]=0;disp[7]=7;break;
case 41 :disp[6]=0;disp[7]=8 ;break;
case 37 :disp[6]=0;disp[7]=9;break;
default : disp[5]=0;
disp[6]=15;
disp[7]=15 ;
}
}
void irpros(void) //处理函数
{
uchar k,i,j;
uchar value;
k=1;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
if(irdata[k]>10)//时间长度等于1.125ms就是0 等于2.25ms就是1;
{
value=value|0x80;
}
else
{
value=value;
}
if(i<8)
{
value=value>>1;
}
k++;
}
ircode[j]=value;//ircode[j]返回的是十六进制数。
value=0;
}
irprosok=1;
}
void display(void)
{
uchar i;
for(i=5;i<8;i++)
{
send_dat(duan[disp]); //定义段 0亮
send_dat(wei); //定义位 1亮
ST_CP=1;
ST_CP=0;
//delay(2);
}
}
void main()
{
timer0init();
int0init();
while(1)
{
if(irreceok)
{
irpros();
irreceok=0;
}
if(irprosok)
{
irwork();
irprosok=0;
}
display();
}
}
void timer0 () interrupt 1
{
irtime++;
}
void int0 () interrupt 0
{
if(startflag)
{
if(irtime<126&&irtime>=66)//检测引导码9ms
{
bitnum=0;
}
irdata[bitnum]=irtime;
irtime=0;
bitnum++;
if(bitnum==33)
{
bitnum=0;
irreceok=1;
}
}
else
{
startflag=1;
irtime=0;
}
}
大家有什么疑问可以提出来(QQ:1874934688)。
资料:
源码:
希望发烧友的新手们早点能学会红外解码,有什么不明白的可以问我。
`
|