9418浏览
查看: 9418|回复: 5

Arduino入门套件的“红外接收程序”

[复制链接]
请教一个技术问题,


我从http://pan.baidu.com/s/17TJ9U 这里下载了Arduino入门套件的“红外接收程序”,里面的函数void pulse_deal(),说先解码地址码,再解码指令码,按照void pulse_deal()写的,默认地址码是0000 0000 1111 1101(低位在前),这16位bit的数据是怎么来的?按照NEC规则,这16bit应该是应该是地址码0000 0000+地址码反码1011 1111(高位在前),怎么不是呢?


谢谢


源代码如下:
#define BUZZER 10//蜂鸣器
#define LED_RED 11//红灯
#define IR_IN   8   //红外接收
int Pulse_Width=0;//存储脉宽
int   ir_code=0x00;//命令值
voidtimer1_init(void)//定时器初始化函数
{
TCCR1A = 0X00;
TCCR1B = 0X05;//给定时器时钟源
TCCR1C = 0X00;
TCNT1 = 0X00;
TIMSK1 = 0X00;  //禁止定时器溢出中断
}
voidremote_deal(void)//执行译码结果函数
{
switch(ir_code)
{
case 0xff00://停止
digitalWrite(LED_RED,LOW);//红灯不亮
digitalWrite(BUZZER,LOW);//蜂鸣器不响
break;
case 0xfe01://VOL+
digitalWrite(LED_RED,HIGH);//红灯亮
break;
case 0xf609://VOLdigitalWrite(BUZZER,HIGH);//蜂鸣器响
break;
}
}
char logic_value()//判断逡辑值“0”和“1”子函数
{
while(!(digitalRead(8))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//低电平560us
{
while(digitalRead(8));//是高就等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//接着高电平560us
return 0;
else if(Pulse_Width>=25&&Pulse_Width<=27) //接着高电平1.7ms
return 1;
}
return -1;
}
void pulse_deal()//接收地址码和命令码脉冲函数
{
int i; //0000 0000 1111 1101
//执行 8 个 0
for(i=0; i<8; i++)
{
if(logic_value() != 0) //不是 0
return;
}
//执行 6 个 1
for(i=0; i<6; i++)
{
if(logic_value()!= 1) //不是 1
return;
}
//执行 1 个 0
if(logic_value()!= 0) //不是 0
return;
//执行 1 个 1
if(logic_value()!= 1) //不是 1
return;
//解析遥控器编码中的 command 指令
ir_code=0x00;//清零
for(i=0; i<16;i++ )
{
if(logic_value() == 1)
{
ir_code |=(1<<i);
}
}
}
voidremote_decode(void)//译码函数
{
TCNT1=0X00;      
while(digitalRead(8))//是高就等待
{
if(TCNT1>=1563) //当高电平持续时间超过100ms,表明此时没有按键按下
{
ir_code = 0xff00;
return;
}  
}
//如果高电平持续时间不超过 100ms
TCNT1=0X00;
while(!(digitalRead(8))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=140&&Pulse_Width<=141)//9ms
{
while(digitalRead(8));//是高就等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=68&&Pulse_Width<=72)//4.5ms
{
pulse_deal();
return;
}
else if(Pulse_Width>=34&&Pulse_Width<=36)//2.25ms
{
while(!(digitalRead(8)));//低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//560us
{
return;
}
}
}
}
void setup()
{
unsigned char i;
pinMode(LED_RED,OUTPUT);//设置不红灯连接的引脚为输出模式
pinMode(BUZZER,OUTPUT);//设置不蜂鸣器连接的引脚为输出模式
pinMode(IR_IN,INPUT);//设置红外接收引脚为辒入
}
void loop()
{  
timer1_init();//定时器刜始化
while(1)
{
remote_decode();   //译码
remote_deal();    //执行译码结果
}  
}


0211liucheng  学徒
 楼主|

发表于 2014-2-4 23:59:41

0-7bit 和8-15bit 应该互为反码,可是0000 0000 和1111 1101并不互为反码啊
回复

使用道具 举报

Holiday  初级技匠

发表于 2014-2-7 22:10:42

NEC码应该是32位,是16位的地址+八位数据+八位数据反码,
至于程序里int i; //0000 0000 1111 1101,应该是遥控器的地址码,和遥控器本身有关
所以在识别接受的前16位是不是0000 0000 1111 1101后再将后十六位进行比较就可以了,在void remote_deal(void)//执行译码结果函数  这个函数里,
switch的三个数是0xff00,0xfe01,0xf609,换算成二进制就是前八位和后八位是反码了,这里才是数据码。地址码在NEC规则里没有规定要使用反码的

错误之处,还请指正:P
回复

使用道具 举报

0211liucheng  学徒
 楼主|

发表于 2014-2-8 08:45:06

Holiday 发表于 2014-2-7 22:10
NEC码应该是32位,是16位的地址+八位数据+八位数据反码,
至于程序里int i; //0000 0000 1111 1101,应该是 ...

百度 和 论坛资源里下载的教材里都写的:
NEC协议特点:8位地址和8位命令,为提高可靠性,地址和命令都传输2次。
所以说,NEC协议里面,地址位确实占了16bits,但是是把地址位的反码加在8bits地址位后面又发了一次。
但是0000 0000 的反码,不是 1111 1101 啊。。。

回复

使用道具 举报

Holiday  初级技匠

发表于 2014-2-8 23:27:22

按照这里说的NEC原理--百度文库Arduino入门套件的“红外接收程序”图1

个人理解应该是可以设置为反码,也可以不是,至于一定要是反码的规定,能贴个链接一起学习下吗?
回复

使用道具 举报

0211liucheng  学徒
 楼主|

发表于 2014-2-11 16:47:08

Holiday 发表于 2014-2-8 23:27
按照这里说的NEC原理--百度文库

个人理解应该是可以设置为反码,也可以不是,至于一定要是反码的规定,能 ...

是的,可以是反码,也可以不是。
问题是我们买的是红外收发模块,并不知道发射端是怎么设置的,只能在接收端按照例程处理也不是个事儿啊。
如果我想和别的红外端配对,我就没办法配了啊。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail