//***************************************************************************
// Ray_Deode_Ser.h
//***************************************************************************
#ifndef Ray_Decode_Ser
#define Ray_Decode_Ser
extern void Ray_Decode_Init(); //红外解码初始化定时器
extern void Ray_Decode_Drive(); //红外解码分析33位数据
extern u8 xdata Ray_Read_Buffer[6]; //机器正码,反码,用户正码,反码,长按计数,连接计数。遥控小车直接使用。
#endif
//***************************************************************************
// Ray_Deode_Ser.c
//***************************************************************************
#include"all.h"
static u8 xdata Ray_bit_timer_Buffer[33]=0; //33个时间长度保存
u8 xdata Ray_Read_Buffer[6]=0; //机器正码,反码,用户正码,反码,长按计数,连按计数
u8 xdata Ray_Read_bit_timer=0;
u8 xdata Ray_Read_bit_count=0;
bit Ray_Read_ok=0;
//***************************************************************************
// 红外解码初始化定时器
//***************************************************************************
void Timer0_INT0_Init() //256*0.4us=102.4us(8位)
{
AUXR&=0x7f;//0111 1111 12分频。一个脉冲0.4us
EA=1; //总中断
EX0=1; //外部中断允许位
IT0=1; //下降沿中断
TMOD&=0xf0; //1111 0000
TMOD|=0x02; //0000 0010 M1 M0:1 0 8位自动重装载定时器,当溢出时将TH0存放的值自动重装入TL0。
TH0=0;
TL0=0;
ET0=1; //T0的溢出中断允许位。1为允许T0中断。
TR0=0; //定时器0的运行控制位。1为允许定时器0开始计数。
} //总中断控制开关闭合EA=1;
//***************************************************************************
// 红外解码初始化
//***************************************************************************
void Ray_Decode_Init()
{
Timer0_INT0_Init();
}
//***************************************************************************
// 红外解码分析33位数据 解析机器码正码,机器码反码,按键值正码,按键值反码。
//***************************************************************************
void Ray_Decode_Drive()
{
u8 idata i,j,k=1,Value;
if(Ray_Read_ok==1) //必须是接收完33位时间值才能解码
{
Ray_Read_ok=0;
TR0=0; //关闭定时器,节约CPU资源,排除干扰,保证数据稳定性。
for(i=0;i<4;i++) //解码4个字节
{
for(j=0;j<8;j++)
{
Value>>=1; //先右移,低位在先
if(Ray_bit_timer_Buffer[k]>=17) //如果高电平时间大于低电平2倍,那么解码成1
{
Value=Value|0x80; //最高位赋值为1
}
else
{
Value=Value&0x7f;//0111 1111 否则最高位赋值为0
}
k++; //8次
}
if(i==3) //当解码第三字节数据按键码的时候
{
if(Value!=Ray_Read_Buffer[i]) //如果按键码发生改变
{
Ray_Read_Buffer[4]=255; //长按清零
Ray_Read_Buffer[5]=255; //连按清0
}
if(Value==Ray_Read_Buffer[i]) //否则,按键码不改变可能是长按
{
Ray_Read_Buffer[4]--;//保持数字不动
// Ray_Read_Buffer[4]=255; //让Ray_Read_Buffer[4]清零,防止和连按一起联动
Ray_Read_Buffer[5]++; //连按计数器增加
}
}
Ray_Read_Buffer[i]=Value; //再把解码的值分别发送到4个数据字节
}
}
}
//***************************************************************************
// 红外解码,外部下降沿中断。红外线定时器0计数次数为两个下降沿间隔时间,一个低电平加一个高电平。红外线接收头再 P3.2口,也就是外部中断端口。
//***************************************************************************
void INTO_Routine() interrupt 0
{
static bit Ray_Flag=0;
TR0=1; //启动定时器0,开始计时
if(Ray_Read_bit_timer>=117) //如果时间大于11.5ms,说明是引导码
{
Ray_Read_bit_count=0; //计数器清零
Ray_Flag=1; //允许33个时间长度的保存
Ray_Read_Buffer[4]++; //长按计数器增加
}
if(Ray_Flag==1)
{
Ray_bit_timer_Buffer[Ray_Read_bit_count]=Ray_Read_bit_timer; //0-32。33次保存。定时器0已有计数字,就是0位的引导码。
Ray_Read_bit_count++;
Ray_Read_bit_timer=0; //定时器清0,测量下一个时间长度
if(Ray_Read_bit_count>=33) //33个全部接收完毕。
{
Ray_Read_bit_count=0; //计数器清0
Ray_Read_bit_timer=0;
Ray_Read_ok=1; //允许解码分析数据含义
Ray_Flag=0; //禁止下降沿保存。排除干扰
}
}
}
//***************************************************************************
// 红外解码,定时器0中断服务函数,每次中断就是增加103us
//***************************************************************************
void Timer0_Routine() interrupt 1 //102.4us增加
{
Ray_Read_bit_timer++;
}