本文来自电子工程师之家:http://www.eehome.cn/read.php?tid=5893
红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空
凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。现在工业设备中,也已经广泛在使用。
1 红外遥控系统
通用红外遥控系统由发射和接收两大部分组成,应用编/解码专用集成电路芯片来进行控制操作,如图1所示。发射部分包括键盘矩阵、编码调制、LED红外发送器;接收部分包括
光、电转换放大器、解调、解码电路。
2 遥控发射器及其编码
遥控发射器专用芯片很多,根据编码格式可以分成脉冲宽度调制和脉冲相位调制两大类,这里我们以运用比较广泛,解码比较容易的脉冲宽度调制来加以说明,现以3310组成发射
电路为例说明编码原理。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:
采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”
上述“0”和“1”组成的42位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射。
3310产生的遥控编码是连续的42位二进制码组,其中前26位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。后16位为8位的操作码和8位的操作
反码用于核对数据是否接收准确。
目前使用的遥控器有大部分采用32位编码方式,其中前16位为用户识别码,后16位为8位的操作码及其反码。
当遥控器上任意一个按键按下超过36ms时,LC7461芯片的振荡器使芯片激活,将发射一个特定的同步码头,对于接收端而言就是一个9ms的低电平,和一个4.5ms的高电平,这
个同步码头可以使程序知道从这个同步码头以后可以开始接收数据。
连续发完42位(或32位)编码后,如果该键仍然被按下,则每隔110ms发射一个重复码,对于接收端而言就是一个9ms低电平+2.25ms高电平+0.56ms低电平,而不再发射操
作码。
解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度
区别“0”和“1”。如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否
则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右即可。
根据红外编码的格式,程序应该等待引导码(9ms低电平+4.5ms的高电平)完成后才能读码。
//============================================================
// 红外遥控解码程序
// 硬件连接: P3.0、P3.1接串口便于调试;
// P3.2接红外接收管的数据线
// 适用于32位码字红外接收头及宏科万能遥控器
// =======本程序引自:谷雨工作室========
//============================================================
#include
#define uint unsigned int
#define uchar unsigned char
uint time=0,flag=0;
uint First_INT=0,Star_Flag=0,CodeNum=0,Code[33]={0};
void init_serial();
void Tranfer(char Data);
uint getkey(void);
//============================================================
//函数名称:int main(void)
//函数功能:系统主函数,主要包括一个用串口做的测试部分
//入口参数:无
//出口参数:无
//============================================================
int main()
{
uint keyvalue;
TMOD=0x22; //设置定时器0为工作方式2
TH0=0xd1; //定时0.05ms
TL0=0xd1;
TR0=1;
IT0=1; //设置INTR0为边沿触发,负跳变产生中断
EX0=1; //外中断0允许
ET0=1; //定时中断允许
EA=1; //开总中断
init_serial();
while(1)
{
keyvalue=getkey();
switch(keyvalue)
{
case 0x01: Tranfer('1');break;
case 0x02:Tranfer('2');break;
case 0x03:Tranfer('3');break;
case 0x04:Tranfer('4');break;
case 0x05:Tranfer('5');break;
case 0x06:Tranfer('6');break;
case 0x07:Tranfer('7');break;
case 0x08:Tranfer('8');break;
case 0x10:Tranfer('J');Tranfer('Y');break;//静音
case 0x12:Tranfer('K');Tranfer('G');break;//开关
case 0x0b:Tranfer('-');Tranfer('-');break;// -/--
case 0x52:Tranfer(' @ ');break;//转圈的那个
case 0x51:Tranfer('H');Tranfer('Z');Tranfer('H');break;//画中画
case 0x58:Tranfer('Z');Tranfer('S');break;//制式
case 0x16:Tranfer('P');Tranfer('X');break;//屏显
case 0x0e:Tranfer('S');Tranfer('M');break;//左
case 0x1b:Tranfer('P');Tranfer('1');break;//频道(上)
case 0x1e:Tranfer('Y');Tranfer('1');break;//音量(左)
case 0x1f:Tranfer('P');Tranfer('2');break;//频道(下)
case 0x1a:Tranfer('Y');Tranfer('2');break;//音量(右)
case 0x0f:Tranfer('S');Tranfer('P');break;//视频
case 0x1d:Tranfer('B');Tranfer('Y');break;//伴音
case 0x13:Tranfer('L');Tranfer('Y');break;//丽音
case 0x56:Tranfer('U');Tranfer('P');break;//上
case 0x57:Tranfer('D');Tranfer('N');break;//下
case 0x5b:Tranfer('L');break;//左
case 0x5f:Tranfer('R');break;//右
case 0x5c:Tranfer('M');break;//菜单
default:break;
}
}
}
//============================================================
//函数名称:uint getkey(void)
//函数功能:获得红外遥控器键值
//入口参数:无
//出口参数:无
//说明:适用于32位码字红外接收头及宏科万能遥控器
//============================================================
uint getkey(void)
{
uint j=0;
uint DateCode=0,key=0;
if(flag==1) //判断头部是否是5;防止误接收
{
for(j=8;j<=10;j++)
{
if(Code[j]==1&&Code[j+1]==1&&Code[j+2]==1&&Code[j+3]==1&&Code[j+4]==1&&Code[j+5]==1&&Code[j+6]==0&&Code[j+7]==1)
{ //判断用户识别码是不是1111 1101
for(DateCode=0;DateCode<8;DateCode++)//若是,则开始接收八位数据码
{
Code[j+8+DateCode]<<=DateCode;
key|=Code[j+8+DateCode]; //将八位二进制数倒序转成16进制
}
break;
}
}
flag=0; //将头部清零
return key; //返回键值
}
else return(0);
}
//=============================================================
//函数名称:void init_serial()
//函数功能:初始化串口
//入口参数:无
//出口参数:无
//============================================================
void init_serial()
{
// TMOD=0x22; //定时器T1使用工作方式2
TH1=250; //设置初值
TL1=250;
TR1=1; //开始计时
PCON=0x80; //SMOD=1;
SCON=0x50; //工作方式1,波特率9600bit/s,允许接收
TI=1;
}
//============================================================
//函数名称:void Tranfer(char Data)
//函数功能:发送数据程序
//入口参数:Data 要发送的数据
//出口参数:无
//============================================================
void Tranfer(char Data)
{
while(TI==0);
SBUF=Data;
TI=0;
}
//============================================================
//函数名称:void timer0_int()
//函数功能:定时器0中断服务函数
//入口参数:无
//出口参数:无
//============================================================
void timer0_int() interrupt 1 using 2 //定时器0中断
{
time++;
}
//============================================================
//函数名称:void intr0_int()
//函数功能:外中断0中断服务函数
//入口参数:无