这篇文章是我学习红外模块的时候的一些心得和体会,并附带个人对于这块的理解,希望能够对大家有帮助。
首先一点的就是红外发射信号后,单片机上接受数据部分
这是常见的接收模块,负责接受发射出的调制波,还有整个遥控部分的示意图
这个就是调制后的波,我们可以看到,最开始有一个引导码,这个是由NEC协议决定的,然后是客户码,可以类比为钥匙,这个对孔后就可以开门了,最重要的就是操作码,这个就是要发送的信息,最后有一个操作反码,用于校验操作码是否正确。
接着就到了红外接收部分,先看一下流程:
引导码出现以后,进行一下延时判断(代码没有判断,因为比较简单),
然后,重点就来了
主要过程看下边信号的时间轴,发生事件后去看timer0的时间轴,很容易就能理解了
一开始的跳变沿产生一次中断,但这时候flag = 0,所以就进入timer0 = 0,flag = 1,注意!!!!这时候信号已经在传输了,timer0正在计时,当下一个跳变沿产生,也就是这一位信号传输完成时,又一次进入中断,这时候flag = 1,所以就进入到保存timer0的值,i++,然后把timer0重新置零,然后timer0 重新计时,传输下一位数据,再产生一次跳变沿,再读走时间,重复下去,直到i=33,也就是传了33位数据之后,停止接受,并将接受完成位置一。
之后对数据进行解码,也就是根据时间长短,判断数据是0还是1,并将数据按8位,一字节存入之前定义的数组中,这时候数组中第三个就是要传输的数据了,整个过程完成。
#include
#define uchar unsigned char
#define uint unsigned int
sbit IR=P3^2;
#define DataPort P0 //定义数据端口
sbit du=P2^6;// 段锁存
sbit we=P2^7;// 位锁存
uchar table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
uchar irtime;//红外用全局变量,存储红外带宽
bit ir_ok;//存储完成标志位
bit irpro_ok; //解码完成标志位
uchar irdata[33];
uchar irbyte[4];
void inter0_init() //定时器0初始化 ok
{
TMOD |= 0X02;
TH0 = TL0 = 0;
ET0 = 1;
TR0 = 1;
}
void timer0() interrupt 1 using 1 //ok
{
irtime++;
}
void inter0_ex() //外部中断0初始化函数
{
EA = 1;
IT0 = 1;
EX0 = 1; //开外部中断0
}
void ex0_play()interrupt 0 //外部中断0处理函数 ok
{
static bit flag;//开始处理标志位
static uchar i;//存储33位数据
if(flag)
{
if(irtime<63&&irtime>=33)//开始标志信号持续时间,这个和具体晶振频率有关
i = 0;
irdata[i] = irtime;
irtime=0;
i++;//处理下一位
if(i == 33)
{
ir_ok = 1;
i = 0;
}
}
else
{
flag = 1; //开始标志位置1
irtime = 0; //重新计时
}
}
void Ir_work(void)//红外键值码 //ok
{
switch(irbyte[2])//判断第三个数码值,第三个为数据位,第四个是数据码取反校验位
{
case 0x0c:DataPort=table[1];break;//1
case 0x18:DataPort=table[2];break;//2
case 0x5e:DataPort=table[3];break;//3
case 0x08:DataPort=table[4];break;//4
case 0x1c:DataPort=table[5];break;//5
case 0x5a:DataPort=table[6];break;//6
case 0x42:DataPort=table[7];break;//7
case 0x52:DataPort=table[8];break;//8
case 0x4a:DataPort=table[9];break;//9
default:break;
}
irpro_ok=0;//处理完成标志
}
void Ircordpro(void)//解码函数 //ok
{
unsigned char i, j, k;
unsigned char byte,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
byte=irdata[k];
if(byte>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
value|=0x80;
if(j<8)
{
value>>=1;
}
k++;
}
irbyte[i]=value; //存储解码值
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
void main()
{
inter0_init();
inter0_ex();
we = 1;
P0 = 0x00;
we = 0;
while(1)
{
if(ir_ok)
{
Ircordpro();
ir_ok = 0;
}
if(irpro_ok)
{
Ir_work();
}
}
}