新闻中心

EEPW首页>嵌入式系统>设计应用> PIC单片机的红外遥控与解码

PIC单片机的红外遥控与解码

作者: 时间:2016-11-09 来源:网络 收藏
今天玩红外遥控解码

先了解红外接收的原理:

本文引用地址://m.amcfsurvey.com/article/201611/317656.htm

遥控器使用方便,功能多.目前已广泛应用在电视机、VCD、DVD、空调等各种家用电器中,且价格便宜,市场上非常容易买到。如果能将遥控器上许多的按键解码出来.用作单片机系统的输入.则解决了常规矩阵键盘线路板过大、布线复杂、占用I/O口过多的弊病。而且通过使用遥控器,操作时可实现人与设备的分离,从而更加方便使用。

一、编码格式
1、0和1的编码
遥控器发射的信号由一串O和1的二进制代码组成.不同的芯片对0和1的编码有所不同。通常有曼彻斯特编码和脉冲宽度编码。TC9012的O和1采用PWM方法编码,即脉冲宽度调制,其O码和1码如图1所示(以遥控接收输出的波形为例)。O码由O.56ms低电平和0.56ms高电平组合而成.脉冲宽度为1.12ms.1码由0.56ms低电平和1.69ms高电平组合而成.脉冲宽度为2.25ms。在编写解码程序时.通过判断脉冲的宽度,即可得到0或1。
2、按键的编码

当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)组成。

当我们按下遥控器的按键时,遥控器将发出如图2的一串二进制代码,我们称它为一帧数据。根据各部分的功能。可将它们分为5部分,分别为引导码、地址码、地址码、数据码、数据反码。遥控器发射代码时.均是低位在前。高位在后。由图2分析可以得到.引导码高电平为4.5ms,低电平为4.5ms。当
接收到此码时.表示一帧数据的开始。单片机可以准备接收下面的数据。地址码由8位二进制组成,共256种.图中地址码重发了一次。主要是加强遥控器的可靠性.如果两次地址码不相同.则说明本帧数据有错.应丢弃。不同的设备可以拥有不同的地址码.因此。同种编码的遥控器只要设置地址码不同,也不会相互干扰。图中的地址码为十六进制的0EH(注意低位在前)。在同一个遥控器中.所有按键发出的地址码都是相同的。数据码为8位,可编码256种状态,代表实际所按下的键。数据反码是数据码的各位求反,通过比较数据码与数据反码.可判断接收到的数据是否正确。如果数据码与数据反码之间的关系不满足相反的关系.则本次遥控接收有误.数据应丢弃。在同一个遥控器上.所有按键的数据码均不相同。在图2中,数据码为十六进制的0CH,数据反码为十六进制的0F3H(注意低位在前).两者之和应为0FFH。

连续码


二、单片机遥控接收电路
红外遥控接收可采用较早的红外接收二极管加专用的红外处理电路的方法。如CXA20106,此种方法电路复杂,现在一般不采用。较好的接收方法是用一体化红外接收头,它将红外接收二极管、放大、解调、整形等电路做在一起,只有三个引脚.分别是+5V电源、地、信号输出。常用的一体化接收头的外形及引脚见图3和图4。红外接收头的信号输
出接单片机的INTO或INTl脚.典型电路如图5所示.图中增加了一只PNP型三极管对输出信号进行放大。

针对遥控器端(解码端,接收端对对此取反即可)
引导码:9ms高+4.5ms低
系统码:系统码1+系统码2(由定义高低电平的"0"和"1"组成)
数据码:数据码1+数据反码(由定义高低电平的"0"和"1"组成)
剩余码:108ms-引导码占用时间-系统码占用时间-数据码占用时间.
如果按"键"的时间超过108ms,遥控器还会发射重发码:
重发码(108ms)的格式如下:
9ms高+2.25ms低+0.56ms高+96.19ms低

连接电路图:

下面开始写程序:

#ifndef MAIN_H
#define MAIN_H
#include

#define bitset(var,bitno)(var |=1< #define bitclr(var,bitno)(var &=~(1<


#define uint unsigned int
#define uchar unsigned char

//定义接受帧状态
#define IR_IDLE 0x01
#define IR_START 0x02
#define IR_ADD 0x03
#define IR_ADDINV 0x04
#define IR_DATA 0x05
#define IR_DATAINV 0x06


#define ms_168 0x0600
#define ms_th 0x08CA
#define ms_9 0x0800
#define ms_306 0x0B00
#define ms_125 0x1300
#define ms_15 0x15F9
//void DelayMS(uint ms);//毫秒级延时函数
//void Delay10US(uint us);//10微秒级延时函数
void init_all() ;

#endif


#include "main.h"
#include "t232.h"

typedef struct frame1
{
uint add ;
uint addinv ;
uchar data ;
uchar datainv ;
uchar ir_state ;
uint count ;
uint temp ;
uchar ready ;
} ir_frame ;

void int_delay(uint count)
{
while(count--) ;
}
//define global variable
ir_frame frame ;

voidinterruptmain_int()
{

if(INTF&INTEDG)
{
GIE=0 ;
INTF=0 ;
TMR1ON=0;
frame.count=TMR1H*256+TMR1L;
TMR1H=0;
TMR1L=0;
TMR1ON=1;

switch(frame.ir_state)
{
case IR_IDLE :
if(frame.count>0x2000)//防止干扰
frame.ir_state=IR_START ;
break ;
case IR_START :
if(frame.ready==1)//没有处理,等待
{
frame.ir_state=IR_IDLE ;
return ;
}
if((frame.count>ms_125)&&(frame.count {
frame.add=0 ;
frame.addinv=0 ;
frame.data=0 ;
frame.datainv=0 ;
frame.ir_state=IR_ADD ;
frame.temp=1 ;
frame.ready=0 ;

}
else if((frame.count>ms_9)&&(frame.count {
frame.ready=1 ;
frame.ir_state = IR_IDLE ;

}
else//噪声?
{
frame.ir_state = IR_IDLE ;
}
break ;
case IR_ADD :
if(frame.count<0x280)//噪声?
return ;
if((frame.count>ms_168))//高电平?
frame.add|=frame.temp ;

frame.temp=frame.temp<<1 ;
if(frame.temp==0x2000)//13位OK?
{
frame.ir_state=IR_ADDINV ;
frame.temp=1 ;
}
break ;
case IR_ADDINV :
//int_delay(75) ;
//if(RB0)
if(frame.count<0x280)
return ;
if((frame.count>ms_168))
frame.addinv|=frame.temp ;

frame.temp=frame.temp<<1 ;
if(frame.temp==0x2000)//13位OK?
{
frame.ir_state=IR_DATA ;
frame.temp=1 ;
}
break ;
case IR_DATA :
if(frame.count<0x280)//噪声
return ;
if((frame.count>ms_168))//高电平
frame.data|=frame.temp ;

frame.temp=frame.temp<<1 ;
if(frame.temp==0x0100)//8位 finished ?
{
frame.ir_state=IR_DATAINV ;
frame.temp=1 ;
}
break ;
case IR_DATAINV :
if(frame.count<0x280)
return ;
if((frame.count>ms_168))
frame.datainv|=frame.temp ;

frame.temp=frame.temp<<1 ;
if(frame.temp==0x0080)//7 位 finished?
{
frame.temp=frame.temp<<1 ;
int_delay(75) ;//延时等待最后一位的电平
if(RB0)
frame.datainv|=frame.temp ;
if((frame.data|frame.datainv==0xff)&&(frame.add==0x011F))
{
frame.ready=1 ;
}
frame.ir_state=IR_IDLE ;
}
break ;
default :
break ;
}
GIE=1 ;
}
}


void init_all()
{
init_232() ;
//init_hongwai() ;
INTCON=0 ;
INTE=1;//开RB电平中断
PEIE=1;
INTEDG=1 ;
TRISB0=1;//RB4为输入
T1CON=0 ;
TMR1H=0xAA ;
TMR1L=0xBB ;
frame.ir_state=IR_IDLE ;
GIE=1 ;
ADCON0=0x06 ;
TRISA0=0 ;
}
void main()
{
const char str[]= "hello world !" ;

init_all() ;
send_str(str) ;//测试串口
while(1)
{

if(frame.ready==1)
{
put_char(frame.data) ;
frame.ready=0 ;
}

}
}



评论


技术专区

关闭