一直对红外遥控很好奇,这次总算测试通过了。再看完红外遥控的原理后,我大概想了一下该如何实现解码,在参考了网上一些资料后,我发现原来有些想法是过于严苛的,实际解码是很简单的事情,只要适当采样就可以正确解码了。在本程序中,将忽略不同遥控器的干扰,不考虑其他协议的遥控器,红外遥控使用最广泛的协议时NEC协议,这次只是就如何实现NEC协议的遥控器实现解码。我相信只要会了NEC解码,其他协议也就不是问题,只要改动采样时间就好了。
本遥控器型号:KM-001,采用的是NEC协议。
实现功能:按住不同的遥控数字键,在开发板的数码管上显示按住的数字。
一、红外遥控原理
1>红外遥控的发送和接收
将要发送的二进制码调制到38KHZ的载波上通过红外线发送出去,对于为什么要使用载波,这是因为信号源不能传输的很远,而载波能远距离传送,所以要使用载波。原理图示:
![](data/attach/1904/65paq07l6uuqmypx57whgh74cbovmzo0.jpg)
左边是经过调制的编码经过发射器发送出去,右边是红外接收头通过解调,将发送过来的二进制码解调出来后的波形。这就是发送和接收的大概思路了。
***********************************************************************************************************************
详情请咨询: http://shop108408772.taobao.com/
******************************************************************************************************************
2>NEC协议
发送桢格式如下:
一个完整的全码=引导码+用户码+用户反码+数据码+数据反码。
![](data/attach/1904/qdk77pmsh6qcfhygboyul0zn56bmrkdb.jpg)
13.5ms引导码 1字节 1字节 1字节 1字节
在对引导码进行识别后,程序需要将后面的4字节解码出来。NEC协议中规定的0和1波形如下:
(图形来自changing)
发送端未调制之前波形:
![](data/attach/1904/3n551hfqbejqg6wr76z9p176icheoj6x.jpg)
接收端调制出来后波形:
![](data/attach/1904/6v1marmisfnm1nf6jj1f53wu20loqew7.jpg)
注意我们需要解码的是接收端调制出来后波形,而这跟发送端之前的波形是反向的。
3>控制器按键与控制码对应图
![](data/attach/1904/tmneaj7222m7z5dmlcse1wrioswt81tp.jpg)
(这个图全部数字键经过测试是正确的)
***********************************************************************************************************************
详情请咨询: http://shop108408772.taobao.com/
******************************************************************************************************************
二、解码程序
因为引导码在接收端是9ms的低电平在加上4.5ms的高电平,而单片机各引脚在初始状态时为高电平。所以使用中断方式下触发方式采用跳变沿触发。
#include
sbit IRPORT = P3^2;
unsigned char ircode[4];
// 此表为 LED 的字模(共阴极) 0 1 2 3 4 5 6 7 8 9 a b c d e f
unsigned char code LED7Code[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char key[10]={0x16,0x0C,0x18,0x5E,0x08,0x1C,0x5A,0x42,0x52,0x4A};
// 0 1 2 3
4 5 6 7 8 9
void delayms1()//延时1ms
{unsigned int i=100;
while((i--)!=1);
}
void delayus842()//延时842us
{unsigned int i=105;
while(--i);
}
void inter() interrupt 0 //中断服务子程序
{unsigned char i,j;
unsigned char temp;
EX0=0;//中断关闭,防止后续在同一个桢的跳变沿干扰中断
delayms1(); //延时2ms
delayms1();
while(IRPORT!=0)
{EX0=1;//中断打开
return;
}
while(IRPORT==0);
while(IRPORT==1);//跳过引导4.5ms
for(i=0;i<=3;i++)
{temp=0;
for(j=0;j<=7;j++)
{
while(IRPORT==0);
temp=temp>>1;
delayus842();//延时842us判断是0还是1?
if(IRPORT==1)
{delayms1();
temp=temp|0x80;//先接受低位数据
}
}
ircode[i]=temp;
}
EX0=1;//中断打开
}
***********************************************************************************************************************
详情请咨询: http://shop108408772.taobao.com/
******************************************************************************************************************
void main()
{
unsigned char i,temp=0xFF;
EA=1; //中断总开关
EX0=1; //外部中断打开
IT0=1; //负跳变促发方式
do
{
if(ircode[2]=~ircode[3])//判断接收到的控制码是否正确
{
for(i=0;i<=9;i++)
{if(ircode[2]==key[i])
temp=i;
}
P2=(temp<<2)&0x1c;//使用LED动态显示,LED数码的片选控制,使用了38译码器
P1=(LED7Code[temp])&0x7f; //LED数据送入,使用了锁存器
//将数据送往LED显示
for(i=0;i<=100;i++);//短暂延时
}
}while(1);
}
三、测试结果
![](data/attach/1904/h5hbjdw1xqqtwdgrx0w0jucyqu69lmtv.jpg)
***********************************************************************************************************************
详情请咨询: http://shop108408772.taobao.com/
******************************************************************************************************************