红外线遥控在生活中有着广泛的应用,比如空调,电视,音响,机顶盒等。红外线遥控实际上就是一种通信方法,利用LED发射红外线,接收器接收到数据,进行处理后就可以得到发送端的信号。利用一个简单的红外线发光二极管,我们可以制作万能遥控器。众所周知,电视机的遥控不能控制空调,甚至不同的电视机遥控只能控制自己的电视。这是因为红外遥控都遵循了一个协议,从而保证稳定和可靠。最常见的是日本的NEC芯片下的协议。在该协议下,红外信号以38Khz的红外波作为载波信号,以9ms的高电平和4.5毫秒的低电平作为引导码,然后是8位客户码1,8位客户码2,8位操作码,8位操作反码(如图)。
这些信号的作用分别如下:客户码1、2:用于区分不同的设备,比如不同品牌的电视遥控之间有着不同的客户码,因而可以相互识别,不至于产生干扰。操作码:包含了遥控正在所要传输的操作信息;操作码反码就是操作码取反后的数据,作用在与对操作码进行校验,收到信号后对操作码和操作码反码进行比较,如果发现差异,这说明数据传输过程中出现了干扰,这次接收就要忽略。
接收的原理是采用光敏二极管,受红外线照射产生电信号。实际中使用红外一体化接收头,只能选择性接收38Khz的红外信号,增加了抗干扰的能力,其内部有增益电路和滤波电路,直接输出高低电平。需要注意的是接收头输出的信号和发射信号反相了。如下图所示:
可以看到,接收到的信号无论是0还是1,都首先是一个下降沿,只不过是间隔的时间不同罢了,因此,我们可以将接受头接到P3.2口,用中断的方法得到每个位,记录下间隔时间,再写程序判断是0还是1即可。
讲完理论知识,回到我们最初的目标:用单片机制作遥控器。那么首先面临的问题就是要获取配套遥控器的编码信息。本文将讲述如何用单片机接收NEC协议下的编码信号,然后在数码管上显示出来。
我们的思路是首先识别引导码,确认接下来是一个发射的信号后将4个8位信号(共32位)储存起来。这可以利用中断来实现,实际上记录的是中断间隔时间(用计时器周期来表示)在void int0 () interrupt 0中定义了数组bitnum[],存储一个引导码和32位信号数据。
然后通过中断时间的判断,得知是0还是1。这一部分在void irpros(void)中实现。将处理后的结果放到ircode[]里去。
第三步:将ircode[]里的数据转化为16进制,便于在数码管上显示。
配套数码管显示函数,将以上几步用main函数串起来就实现了红外编码的获取。
#include
#define uchar unsigned char
#define uint unsigned int
sbit ir=P3^2;
sbit beep=P2^3;
uchar irtime;
uchar irdata[33];
uchar bitnum;
uchar startflag;
uchar irok;
uchar ircode[4];
uchar irprosok;
uchar disnum[8]={0,0,0,0,0,0,0,0};
sbit dula=P2^6;
sbit wela=P2^7;
uchar code table_du[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,
0x7d,0x07,0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar code table_we[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
void timer0init(void) //256*(1/12m)*12=0.256ms
{
TMOD=0x02;
TH0=0x00;
TL0=0x00;
ET0=1;
EA=1;
TR0=1;
}
void irpros(void) // 红外码值处理
{
uchar mun,k,i,j;
k=1;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
mun=mun>>1;
if(irdata[k]>5)
{
mun=mun | 0x80;
}
k++;
}
ircode[j]=mun;
}
irprosok=1;
}
void irwork(void) // 红外码值转换
{
disnum[0]=ircode[0]/16;
disnum[1]=ircode[0]%16;
disnum[2]=ircode[1]/16;
disnum[3]=ircode[1]%16;
disnum[4]=ircode[2]/16;
disnum[5]=ircode[2]%16;
disnum[6]=ircode[3]/16;
disnum[7]=ircode[3]%16;
}
delay(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=200;b>0;b--);
}
display()
{
uchar i;
for(i=0;i<6;i++)
{
//P0=0xff;
wela=1;
wela=0;
P0=table_du[disnum[i]];
dula=1;
dula=0;
P0=table_we[i];
wela=1;
wela=0;
delay(10);
}
}
void int0init(void)
{
IT0=1;
EX0=1;
EA=1;
}
void main()
{
timer0init();
int0init();
while(1)
{
if(irok==1)
{
irpros();
irok=0;
}
if(irprosok==1)
{
irwork();
irprosok=0;
}
// display();
}
}
void int0 () interrupt 0 //中断服务
{
if(startflag)
{
if(irtime>32&&irtime<63) //8-16ms
{ beep=1;
bitnum=0;
}
irdata[bitnum]=irtime;
irtime=0;
bitnum++;
if(bitnum==33)
{ beep=~beep;
bitnum=0;
irok=1;
}
}
else
{
irtime=0;
startflag=1;
}
}
void timer0 () interrupt 1
{
irtime++;
}
现在,离制作万能遥控只有一步之遥了,只需要把得到的编码用二极管输出就大功告成。
附获取编码的全部代码
—————————————————————————————————————