昨天,也就是大年初二,,我把遥控器的解码调试完毕.今天把程序上传,再写一下对自己调试遥控器的总结
遥控器的接收端一般用一体化接收头.我用的就是.呵呵,,,跟8050三极管样子差不多,稍大一些.
我所使用的接收器在没有接收的情况下是高电平的,这个在解码的时候也要注意一下.
我所使用的遥控器为NEC格式的码.通过我的接收头出来后电平是这个样子的:
引导码+16位系统码+8位按键码+8位按键反码
(这个地方有的说是8位系统码加上8位系统码反码,但是我用的这个遥控器不是这个样子,是16位系统码,所以在程序里有最后验证的时候不验证系统码)
引导码由9ms的低电平和4.5ms的高电平组成,
数据码为一段560us低电平,后引一段高电平,高电平长度为1680us时为1,560us时为0
如果按着键不放,则遥控器则发送一段重复码, 重复码由9ms的低电平,2.25ms的高电平,跟着是一个短脉冲
当然还有其他的格式,有飞利浦的,有东芝的,,呵呵,,不过NEC的最多啦,,我看网上的资料,有的也说是引导码的低电平是4.5ms,这个我没有试过,,也有可能..呵,,
我手头上没有示波器,仅有一个万用表没电了,,搞的我一个工具都没有,只有一个串口调试,,呵呵,,用这个也调试出来了,,哈哈,,,
首先也得感谢网友冰棍的ltisn2008@msn.com的参考程序,这个程序写的很好,要不是这个程序,我也不能在没有工具的前提下这么快的调试出来,,,
先是这个100us的延时程序的确定,,费了好大的劲,,呵呵,,在这介绍一个好用的办法,我们是确定引导的低电平是9ms了,用低电平中断跟串口助手就可以很容易的确定100us的延时的正确性.
那么如何知道后续的电平是怎么样子的呢,,这个也好办啊,,,有了100us的单位,就每100us用串口返回一个数据,高电平就返回"-",低电平就返回"_",这样一个波形图就有了,,呵呵,,,简易的示波器,,嘿嘿嘿
有了这些就可以解码了,,下面就是解码程序,参考了网上的程序,再次感谢网友冰棍.
这段程序,只使用了一个外部低电平中断的资源,没有使用定时器.速度还是可以的,
程序返回的按键有三种按键类型,初次按下,长按,和连发按键,跟我上一篇里的程序是一样子的,,这里就不赘述.看程序如下
/*********************************Copyright (c)*****************************
**
** 飞鹏电子工作室
** 嵌入式项目
** http://xpstudio2003.blog.163.com
**
**项目名称: xp51InfraredDecoder
**编译环境: KEIL 2
**--------------------------------------------------------------------------
**文 件 名: Decoder.C
**作 者: 曹香鹏
**创建日期: 2008年12月04日
**描 述: 代码参考网友冰棍的解码程序,在此致谢.
**功能说明: 可以返回 单按键长按键连发键, 不占用定时器,只用一个外部中断资源.
**--------------------------------------------------------------------------
**维护记录:
2009年1月27日,添加程序,NEC解码格式,
引导码+16位系统码+8位按键码+8位按键反码
引导码由9ms的低电平和4.5ms的高电平组成,
数据码为一段560us低电平,后引一段高电平,高电平长度为1680us时为1,560us时为0
如果按着键不放,则遥控器则发送一段重复码,
重复码由9ms的低电平,2.25ms的高电平,跟着是一个短脉冲
2009年1月27日20:00,解码成功,
关键问题:
100US的延时要精确,我是试出来的.通过测试前面的9ms引导低电平
2009年1月28日16:09,添加按键的分类
加入按下,长按,连发.
****************************************************************************/
#include "xp51HDF.H"
#include "Uart.h"
#include "Decoder.H"
BOOL IR_Flag=FALSE; //有键标志
INT8U IR_SysDat; //系统码
INT8U IR_KeyDat; //按键码
static INT8U IR_KeyTmp; //储存按键的原始值
//延时约100us
//晶振11.0592MHz
//一定要算准了,,呵呵,,
void Delay100us(void)
{
INT16U i="78";
while(--i);
}
void DropExInt0(void) interrupt 0
{
static INT8U IR_Repeat; //有重复键标志的次数
INT8U dataIR[4];
INT8U IR_Data;
INT8U width="0";
INT8U i="0" ;
IR_INT_CLOSE(); //禁止再次中断.
//--------------------------------------------
//计算引导电平的宽度
//引导电平长9.45ms
while(!IR_PIN)
{
Delay100us();
width ++;
}
// SendComm(width);return;//test code
// 测试代码,返回值.一般返回为0X5A=90D为正确,再注释掉上面的程序行就可以了.
//
// 8ms=80*100us 如果不到8ms视为干扰信号
if(width<80)
{
IR_INT_OPEN();
return ;
}
//--------------------------------------------
// 计算后续高电平宽度
width = 0;
while(IR_PIN)
{
Delay100us();
width ++;
}
//--------------------------------------------
//判断是否是重复信号2.5ms
//3ms=30*100us 如果不到3ms即视为2.5ms重复信号
if(width<30)
{
IR_Repeat ++; //接收到一次按键
//判断"连发"键
if(IR_Repeat > IR_REPEAT_LONG + IR_REPEAT_STEP)
{
IR_KeyDat = IR_KeyTmp | KEY_LIAN;
IR_Repeat -= IR_REPEAT_STEP;
IR_Flag = TRUE;
}
//判断"长按"键
else if(IR_Repeat == IR_REPEAT_LONG)
{
IR_KeyDat = IR_KeyTmp | KEY_LONG;
IR_Flag = TRUE;
}
IR_INT_OPEN();
return;
}
IR_Repeat = 0 ;
//--------------------------------------------
//4.5ms新键码引导电平
//4ms=40*100us 如果不到4ms视为错误信号,放弃接收
if(width<40)
{
IR_INT_OPEN();
return ;
}
//--------------------------------------------
//接收系统码和数据码,一共32位
//接收32位数据
while(i++<32)
{
//数据准备
width = 0;
IR_Data >>= 1;
//等待低电平过去.
while(!IR_PIN);
//数高电平长度: 1=1680us 0=560us
while(IR_PIN)
{
Delay100us();
width++;
}
if(width > 9)
{
IR_Data |= 0x80;
}
//数据分类
if(i==8)
dataIR[0] = IR_Data ;
else if(i==16)
dataIR[1] = IR_Data ;
else if(i==24)
dataIR[2] = IR_Data ;
else if(i==32)
dataIR[3] = IR_Data ;
}
//--------------------------------------------
//纠错校验
if(dataIR[2] != ~dataIR[3])
{
IR_INT_OPEN();
return ;
}
//--------------------------------------------
//保存键值.
IR_SysDat = dataIR[1]; //保存遥控器类型
IR_KeyTmp = dataIR[2];
IR_KeyDat = KEY_DOWN | IR_KeyTmp; //保存键值及类型
IR_Flag = TRUE; //标记有键按下
IR_INT_OPEN();
}
用户377235 2012-7-26 09:28