最近做一个项目,遥控器用的是PHILIP的RC6格式。这种格式跟NEC格式相比,解码的难度比较大。编码格式采用的是曼彻斯特码。想了两天,总算把解码的思路理清了,但是感觉这种解码方式并不好。写出来大家讨论一下。呵呵
RC6格式属于PPM(脉冲位置调制)方式,以发射载波的位置表示“0”和“1”。根据每1位的中间跳变沿来确定是1还是0,从高到低跳变是0,从低到高跳变是1.每1位的占空比都是50%,这点和NEC格式不同。
RC6模式0遥控码由1位头码,4位固定码1000,1位奇偶码(按一次遥控键,该位为1,再按一次,该位为0)。8位用户码和8位键值组成。如下图:
“1”“0”位如下图:
遥控数据读法如下:
用HT48F50E,下面是程序:
#define RF1 3 //一位数据的中部跳变沿后的采样时间点300us
#define RF2 9 //奇偶校验码的采样点
void Isr_Timer0()
{
ir_time++;
if(ir_head)
{
if((ir_time >= RF1) && (bit_edge))
{
if(IR_IN)
_c = 1;
else
_c = 0;
_rlc(&ir_data0);
_rlc(&ir_data1);
_rlc(&ir_data2);
io_level = IR_IN;
ir_time = 0;
ir_bit++;
bit_edge = 0;
bit_over = 1;
if(ir_bit == 5)
{
ir_sample_time = RF2; //奇偶校验位采样的时间
if((ir_data0 != 0x10) && (ir_data0 != 0x11))
goto Err_Ir; //如果接收的头5位不等于10h或11h,认为是错误码
}
else
ir_sample_time = RF1;
if(ir_bit == 21)
{
ir_ok = 1;
Err_Ir:
ir_bit = 0;
ir_head = 0;
bit_over = 0;
_t1e = 1; //下一次检测下降沿中断
ir_data0 = 0;
ir_data1 = 0;
ir_data2 = 0;
ir_time = 0;
}
}
else if((ir_time >= ir_sample_time) && (!bit_edge) && (bit_over))
{
ir_time = 0;
if(io_level != IR_IN)
{
bit_over = 0; //读io状态后,经过ref1时间,io状态改变,中断方式保持不变
}
else
{
_t1e = !_t1e; //读io状态后,经过ref时间,io状态仍然不变,中断方式改变
bit_over = 0;
}
}
if(ir_time > 16)
goto Err_Ir;
}
}
void Isr_Timer1()
{
if(!_t1e) //上升沿产生中断
{
if(!ir_head)
{
if((ir_time > 22) && (ir_time < 32))
{
ir_head = 1; //检测到一个在2200us,3200us之间的低电平,认为接收到头码
//中断方式不变,下一次仍然是上升沿中断
ir_time = 0;
}
}
else
{
ir_time = 0; //在一位数据的中部跳变沿同步时钟,把ir_time清0
bit_edge = 1;
}
}
else //下降沿产生中断
{
if(!ir_head)
{
ir_time = 0;
_t1e = 0; //改为上升沿中断
}
else
{
ir_time = 0;
bit_edge = 1;
}
}
}
简单说下解码原理:
timer0设置成100us中断,timer1的设置成外部计数,初值设置成0xFFFFh,红外信号接到单片机的一个I/O口和timer1外部计数脚TMR1,这样就把timer1扩展成了一个同时又上升沿和下降沿中断的外部中断。
1位数据“0”“1”的周期是888us,高低电平分别是444us,奇偶位的周期是2*888us,高低电平分别是2*444us。
解码的关键是要找到1位数据的中部跳变沿。因为头码是固定的1000,可以确定第一个数据的跳变沿是上升沿,在timer1中断检测到这个跳变后,延时300us,读IR_IN的电平就得到了这一位的数据,然后再延时300us,读IR_IN的状态,如果IR_IN的状态和上一次读的状态不一样,timer1的中断触发方式保持不变。否则,改变中断方式,如果现在时上升沿中断,就改为下降沿中断,以保证timer1的每次中断都是1位数据的中间跳变沿,这就是同步。
因为奇偶校验位的电平时间是普通位的1倍,所以采样点要延长到900us。
文章评论(0条评论)
登录后参与讨论