搜索
bottom↓
回复: 167

红外遥控的输入捕捉实现~~~~搞一个周刚成功!发个给同我一样的初学者

[复制链接]

出0入0汤圆

发表于 2007-11-22 13:47:01 | 显示全部楼层 |阅读模式
电路图:
点击此处下载ourdev_215975.rar(文件大小:15K)

程序:
//包含所需头文件
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>

#include "chuankou.h"

/*------宏定义------*/
#define uchar        unsigned char
#define uint        unsigned int
#define BIT(x)        (1<<(x))
#define NOP()        asm("nop")
#define WDR()         asm("wdr")

//一般说来,volatile用在如下的几个地方:
//1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
//2、多任务环境下各任务间共享的标志应该加volatile;
//3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
volatile uint data0;           //前16个脉冲存放地址
volatile uint data1;           //后16个脉冲存放地址
volatile uint Flag=0;          //接收完成一帧标志位
volatile float oldFall=0,newFall=0;  //时间的先后纪录
volatile uint bitcnt=0;        //脉冲个数纪录

//端口初始化
void port_init(void)
{
        PORTB = 0x01;
        DDRB  = 0x00;
}

//定时T1初始化
//系统时钟为8M内频,64分频,最大定时时长524.228MS
void timer1_init(void)
{
        TCCR1B = 0x00;//停止定时器
        TIMSK |= 0x20;//中断允许
        ICR1H  = 0xFF;
        ICR1L  = 0xFF;//输入捕捉匹配值
        TCCR1A = 0x00;
        TCCR1B = 0x83;//启动定时器
}


void init_devices(void)
{
        cli(); //禁止所有中断
        MCUCR  = 0x00;
        MCUCSR = 0x80;//禁止JTAG
        GICR   = 0x00;
        port_init();
        timer1_init();
        sei();//开全局中断
}
//主函数
int main(void)
{
        init_devices(); //端口初始化
        uart_init();    //串口初始化
        //在这继续添加你的代码
        while(1)
        {
                if(Flag)
            {
              Flag=0;  //清除标志位
                  bitcnt=0;   //计数标志位清0
                  _delay_ms(5);
                  put_char((uchar)((data0&0xff00)>>8));//机器码
                  _delay_ms(5);
                  put_char((uchar)(data0&0x00ff));//机器反码
                  _delay_ms(5);
                  put_char((uchar)((data1&0xff00)>>8));//用户码
                  _delay_ms(5);
                  put_char((uchar)(data1&0x00ff));//用户反码
                  _delay_ms(5);
            }
        }
        return 0;
}


//数据头的时间:Th=9+4.5=13.5ms
//数据“0”的时间:T0=0.565+0.56=1.125ms
//数据“1”的时间:T1=1.685+0.56=2.245ms
//定时器T1输入捕捉中断服务程序
//#pragma interrupt_handler timer1_capt_isr:6
//void timer1_capt_isr(void)
SIGNAL(SIG_INPUT_CAPTURE1)
{
        //timer 1 input capture event, read (int)value in ICR1 using;
        // value=ICR1L;            //Read low byte first (important)
        // value|=(int)ICR1H << 8; //Read high byte and shift into top byte
        // TIFR|=BIT(ICF1);//软件写1清中断标志
        float time=0;
        unsigned int temp=0;
        newFall=ICR1;         //读取当前时间
        time=newFall-oldFall; //计算脉冲加间隔的时间
        oldFall=newFall;      //存放上一次的时间
        if(time<0)  time=newFall-oldFall+0xffff;  //定时周期交叉的情况
    temp=(unsigned int)time; //取整
        //T0的8分频,即(1.125*1000)/8 = 140.625us ;正负20宽范围判断
        if((temp>120) && (temp<160)) // "0"信号
        {
            temp=0;
        }
        //T1的8分频为280.625us
        else if((temp>260) && (temp<300)) //“1”信号
        {
            temp=1;
        }
        //Th的8分频为1687.5us
        else if((temp>1660) && (temp<1700)) //header头信号
        {
            bitcnt=0;
                data0=0;
                data1=0;
                return; //返回,等待下次开始接收
        }
        else //干扰信号
        {
            bitcnt=0;
                data0=0;
                data1=0;
            return;
        }
        bitcnt++;
        if(bitcnt<16) //开始接收前16位
        {
            data0=data0|temp;
                data0=data0<<1;
        }
        else if(bitcnt==16)
        {
            data0=data0|temp;
        }
        else if(bitcnt<32) //开始接收后16位
        {
            data1=data1|temp;
            data1=data1<<1;
        }
        else if(bitcnt==32) //接收完最后一位
        {
           data1=data1|temp;
           Flag=1;       //接收完一帧,标志位置1
        }
}


/*头文件中的串口通讯子程序chuankou.h*/
#include <avr/io.h>

#define fosc 8000000
#define baud 4800

/*字符串输出函数*/
void put_char(unsigned char c)
{         
       while (!(UCSRA&(1<<UDRE)));
       UDR=c;     
}

/*字符输入函数*/         
unsigned char getchar(void)
{
       while(!(UCSRA& (1<<RXC)));
       return UDR;
}

/*字符串输出函数*/
void put_s(unsigned char *s)
{
      while (*s)
      {
           put_char(*s);
           s++;
       }         
       // put_char(0x0a);//回车换行
       // put_char(0x0d);
              
}

/*UART初始化*/         
void uart_init(void)
{
       UCSRB=(1<<RXEN)|(1<<TXEN);//允许发送和接收
       UBRRL=(fosc/16/baud-1)%256;
       UBRRH=(fosc/16/baud-1)/256;
       UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8位数据+1位STOP位
}


谢谢21楼 kv2004提供的解码思路:(注:此图不代表与上面的程序对应)

出0入0汤圆

发表于 2007-11-22 13:51:28 | 显示全部楼层
好。

顺便再详细说说的 解码的红外遥控器的 编码格式,和你解码的思路,这样就比较有价值了。

光放个程序感觉就像一堆字母,呵呵。

出0入0汤圆

 楼主| 发表于 2007-11-22 17:07:21 | 显示全部楼层
回楼上的:
1、红外编码格式在此不做解析了,提供几个相关连接吧
http://www.avrw.com/article/art_105_816.htm
http://hi.baidu.com/silencecoyote/blog/item/0d5b9b3d7130d800bba167ec.html
2、思路跟提供的连接里面的差不多,只是我发现很多我找到的资料都是同一个版本而且是不全的资料(估计都对抄的)
3、在此提供一个简单的解码过程,相关注解个人认为都蛮清楚的了
4、提几点自己发现的小问题吧:
(1)许多网上的解码做法都是1M内频加不分频解码,导致定时器1的最大定时只有65.536ms,假设全1码的时候就会出现:13.5ms+2.245ms*32=85.34ms  大于一个定时周期了,何况大于的状态并没有给出如何处理!
(2)此次为通过串口测试,发送时中间加点必要延时,免出多余的码

出0入8汤圆

发表于 2007-11-22 17:13:08 | 显示全部楼层
阿莫应该发裤子

出0入0汤圆

发表于 2007-11-22 19:31:08 | 显示全部楼层
其实如果不是要求十分严格的应用。可以不用校验红外的反码,99.9%不会出错的。这样可以简化程序。

出0入0汤圆

发表于 2007-11-23 13:10:42 | 显示全部楼层
正想学学

出0入0汤圆

发表于 2007-11-23 13:46:53 | 显示全部楼层
学习了,哈哈

出0入0汤圆

 楼主| 发表于 2007-11-24 16:15:09 | 显示全部楼层
本次只是给出红外解码的输入捕捉实现办法……至于应用于哪方面那应该是大虾们的爱好了,有了实现的办法参考,用途上还不是随心所欲??
什么那么少人顶楼啊?有点悲哀啊……本想多帖点自己的东西的,没多大心情了,这会儿!

出0入0汤圆

发表于 2007-11-25 08:04:57 | 显示全部楼层
学习中........

出0入0汤圆

发表于 2007-12-13 13:00:17 | 显示全部楼层
我顶你一个

出0入0汤圆

发表于 2007-12-13 16:49:56 | 显示全部楼层
这只是一种比较常用的32位红外码,还有好多种编码,LZ要加油哦,一种一种搞。。。

出0入0汤圆

发表于 2007-12-13 19:12:40 | 显示全部楼层
我也顶你一个

出0入0汤圆

发表于 2007-12-13 19:49:49 | 显示全部楼层
ding yi ge

出0入0汤圆

发表于 2007-12-13 22:41:07 | 显示全部楼层
继续哦

出0入0汤圆

发表于 2007-12-14 07:46:26 | 显示全部楼层
好!帮顶一下!

出0入0汤圆

发表于 2007-12-14 08:53:37 | 显示全部楼层
支持一下!

出0入0汤圆

发表于 2007-12-14 10:37:41 | 显示全部楼层
顶一个!

出0入0汤圆

发表于 2007-12-14 12:32:27 | 显示全部楼层
顶一下!!

出0入0汤圆

发表于 2007-12-15 10:03:39 | 显示全部楼层
支持一下楼主

出0入0汤圆

发表于 2007-12-17 14:16:13 | 显示全部楼层
attiny13可以使用吗

出0入0汤圆

发表于 2007-12-30 19:27:24 | 显示全部楼层
我跟用了楼主的程序,但是我总找不到head啊,怎么回事呢?会不会LC7461的和其他的head不一样呢,但我看了芯片资料是一样的啊

出0入12汤圆

发表于 2007-12-30 23:30:46 | 显示全部楼层
也做了一个,原理和楼主的一样,只是用了定时器0和中断0两个中断。没有判断脉冲占和空的宽度,只是靠下降沿的间隔来判断状态。效果不差。只上个图吧。

出0入0汤圆

发表于 2007-12-31 10:13:59 | 显示全部楼层
顶一下,正需要呢!
头像被屏蔽

出0入0汤圆

发表于 2007-12-31 10:22:13 | 显示全部楼层
抱歉由于本贴没有上传电路图,不能置COOL。

刚在论坛的后台管理界面增加了这一个提示的功能。 以后版主们就能很方便地提醒了。

出0入0汤圆

发表于 2008-1-30 14:44:55 | 显示全部楼层
顶一下!

出0入0汤圆

 楼主| 发表于 2008-2-19 18:06:19 | 显示全部楼层
点击此处下载ourdev_215975.rar(文件大小:15K)
为了有裤子穿而不至于裸奔街头,现把简陋的原理图贴上,画得粗糙望请见谅了……
对本原理图的一点说明:
总的来说电路其实很简单,跟单片机接口就三跟线而已,其他的就是单片机工作的一些基本外围电路!
目前个人应用过:(见笑了)
时钟遥控调节、配合上位机遥控电脑的一些软件(如音乐播放)、遥控你的小车

出0入0汤圆

 楼主| 发表于 2008-2-19 18:08:38 | 显示全部楼层
差点忘了!
armok 阿莫发条裤子不?裤衩也行……(莫大的鼓励了!)
(*^__^*) 嘻嘻……!

出0入0汤圆

发表于 2008-2-19 19:20:01 | 显示全部楼层
电路图啊

出0入0汤圆

发表于 2008-2-19 19:33:00 | 显示全部楼层
用51的也做了个红外解码,刚刚完成 拿家里电视机遥控器来调时间。

出0入0汤圆

发表于 2008-2-20 14:45:01 | 显示全部楼层
这个好象不难!!

出0入0汤圆

发表于 2008-2-22 10:27:24 | 显示全部楼层
刚试用了楼主的程序,很不错。
强烈建议在AVR中不要使用float数据,将float改为int32_t后代码量减少2KB多。

出0入0汤圆

发表于 2008-2-22 14:17:36 | 显示全部楼层
我们用的方法和21楼的一样,用单片机的一个定时器和一个中断实现红外接收解码,也可以作为无线电的接收解码(频率不是很高).

出0入0汤圆

发表于 2008-2-22 17:28:12 | 显示全部楼层
强帖 学习学习

出0入0汤圆

发表于 2008-2-23 23:48:58 | 显示全部楼层
我最近也在做这个,用电视遥控控制机器人小车的,开始一直不成功,用的CVAVR,库里没有ICR1,后来才发现ICR1L和ICR1H读写是有顺序的,要先读ICR1L,再读ICR1H.

出0入0汤圆

发表于 2008-3-12 11:29:22 | 显示全部楼层
多谢楼主,学习中,有空我也去搭个电路试下.

出0入0汤圆

发表于 2008-3-12 16:50:20 | 显示全部楼层
好东东,相见恨晚!

出0入0汤圆

发表于 2008-3-14 20:06:00 | 显示全部楼层
遥控解码程序编写是有个问题,请教大家一下:
就是每种遥控器发射的数据编码格式不一样,要是知道某个遥控器的编码格式才有办法写程序啊,
如何获取遥控器的编码?如按键1 2 。。。。。。的编码?
谢谢!

出0入0汤圆

发表于 2008-4-10 19:23:02 | 显示全部楼层
.

出0入46汤圆

发表于 2008-4-10 19:41:37 | 显示全部楼层
好东西!

出0入0汤圆

发表于 2008-4-10 20:49:42 | 显示全部楼层
好东西!

出0入0汤圆

发表于 2008-4-10 21:01:12 | 显示全部楼层
看看。

出0入0汤圆

 楼主| 发表于 2008-4-28 14:27:27 | 显示全部楼层
好久后的回顾:

首先感谢21楼提供的解码思路图解,解码思路基本一致;
方法上有点不同的是图中为定时器解码,偶的是输入捕捉方法实现,原理上是等效的;

回【36楼】 haizaolan    如何获取遥控器的编码?如按键1 2 。。。。。。的编码?

偶的串口通信子程序就是用来查询各个按键的对应编码的啊,
每按任意一个按键都会读出四个码值(机器码、机器反码、用户码、用户反码):
机器码:对应不同的遥控板(类似的VCD遥控板)
机器反码:就是机器码取反
用户码:不同按键对应的编码,读取这个值就可区分是哪个按键
用户反码:用户码取反

至于按键功能就是你自己定义了,关键在读取~~~

出0入0汤圆

 楼主| 发表于 2008-4-28 14:27:28 | 显示全部楼层
好久后的回顾:

首先感谢21楼提供的解码思路图解,解码思路基本一致;
方法上有点不同的是图中为定时器解码,偶的是输入捕捉方法实现,原理上是等效的;

回【36楼】 haizaolan    如何获取遥控器的编码?如按键1 2 。。。。。。的编码?

偶的串口通信子程序就是用来查询各个按键的对应编码的啊,
每按任意一个按键都会读出四个码值(机器码、机器反码、用户码、用户反码):
机器码:对应不同的遥控板(类似的VCD遥控板)
机器反码:就是机器码取反
用户码:不同按键对应的编码,读取这个值就可区分是哪个按键
用户反码:用户码取反

至于按键功能就是你自己定义了,关键在读取~~~

出0入0汤圆

 楼主| 发表于 2008-4-28 14:31:22 | 显示全部楼层
33楼的建议很不错,这个确实需要注意~~~~~~
先读低位字节再读高位字节

出0入0汤圆

发表于 2008-4-28 16:11:02 | 显示全部楼层
利用定时器的捕捉中断功能解码是最简单效率最高的,偶的做法是依次记录脉冲间隔时间,接收完毕后置位中断标志主程序解码,不喜欢在中断干跟多事情,节省效率!

出0入0汤圆

发表于 2008-4-28 16:16:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-4-28 22:54:25 | 显示全部楼层
但是,我觉得,这种方式解。不太通用。如果程序中又有其它部分用到TC1的话,怎么处理?

出0入0汤圆

发表于 2008-4-28 22:59:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-4-29 00:14:16 | 显示全部楼层
好东西!

出0入0汤圆

发表于 2008-4-29 08:38:59 | 显示全部楼层
不错

出0入0汤圆

发表于 2008-4-29 08:55:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-5-7 08:10:19 | 显示全部楼层
非常感谢楼主,因为我原来的红外解码代码是从51下移植过来的,在外部中断进行解码。
解码时必须关闭所有中断,CPU占用相当严重。而AVR自带的捕捉功能,没有好好利用。

所以试了一下楼主的代码,说下感受。楼主的解码原理是正确的,应该可以正常工作。
但楼主的代码相当地不够优化,建议改进:
1、例如前些楼有朋友提到的,使用了float变量问题。
2、中断中的变量数也太多了,不需要这么多。
3、中断中代码还可以优化。

我按照楼主的代码进行了修改,没有做串口输出部分。
编译后代码不到500字节,内存使用了8个字节。

出0入0汤圆

发表于 2008-5-31 13:54:38 | 显示全部楼层

出0入0汤圆

发表于 2008-5-31 14:20:47 | 显示全部楼层
学习

出0入0汤圆

发表于 2008-5-31 16:51:22 | 显示全部楼层
做个记号

出0入0汤圆

发表于 2008-5-31 22:23:08 | 显示全部楼层
好东西,做个记号先。

出0入0汤圆

发表于 2008-6-1 19:58:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-6-8 16:53:35 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-6-9 09:59:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-6-26 14:48:17 | 显示全部楼层
mark个先

出0入0汤圆

发表于 2008-6-27 10:20:28 | 显示全部楼层
是个好东西,支持

出0入0汤圆

发表于 2008-7-11 11:10:22 | 显示全部楼层
mark

同意51楼的,代码风格,哈哈

出0入0汤圆

发表于 2008-7-17 09:23:23 | 显示全部楼层
支持你

出0入0汤圆

发表于 2008-7-18 13:36:11 | 显示全部楼层
好东西 要学习学习

出0入0汤圆

发表于 2008-7-19 13:39:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2008-7-31 09:42:26 | 显示全部楼层
郁闷,还没成功,接收头总是受外界干扰,捕捉解码不成功,在开了日光灯或节能灯情况下不知道楼主捕捉解码成功的灵敏度如何?

出0入0汤圆

发表于 2008-12-25 17:41:44 | 显示全部楼层
我也顶一下..

出0入0汤圆

发表于 2008-12-26 09:56:14 | 显示全部楼层
如果受到干扰,把接受头的灵敏度降低。
用硬件

出0入0汤圆

发表于 2008-12-26 10:27:33 | 显示全部楼层
支持你

出0入0汤圆

发表于 2008-12-26 10:27:36 | 显示全部楼层
支持你

出0入0汤圆

发表于 2008-12-26 16:39:24 | 显示全部楼层
我顶!

出0入0汤圆

发表于 2008-12-26 18:28:29 | 显示全部楼层
我也顶一下..&nbsp;

出0入0汤圆

发表于 2008-12-27 21:05:23 | 显示全部楼层
虽然暂时用不上,不过一定要顶!

出0入0汤圆

发表于 2008-12-30 00:16:14 | 显示全部楼层
做过记号!

出0入0汤圆

发表于 2008-12-30 20:59:15 | 显示全部楼层
用数字存储示波器捕捉下来慢慢看,也是一种方法,不一定要搞一个专用的。

出0入0汤圆

发表于 2009-1-4 09:55:19 | 显示全部楼层
记号~~极好...

出0入0汤圆

发表于 2009-3-2 12:32:59 | 显示全部楼层
学习

出0入0汤圆

发表于 2009-3-2 13:37:24 | 显示全部楼层
MARK一下!

出0入0汤圆

发表于 2009-3-2 23:48:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-3-3 08:18:51 | 显示全部楼层
好东西啊,谢谢分享啊

出0入0汤圆

发表于 2009-3-3 14:06:12 | 显示全部楼层
我也顶你一个

出0入0汤圆

发表于 2009-3-3 19:41:40 | 显示全部楼层
那.记个号

出0入0汤圆

发表于 2009-3-10 17:02:11 | 显示全部楼层
学习

出0入0汤圆

发表于 2009-3-10 17:05:36 | 显示全部楼层
用51 搞出来过 现在没兴趣了啊

出0入0汤圆

发表于 2009-3-20 09:35:44 | 显示全部楼层
极好

出0入0汤圆

发表于 2009-3-20 09:54:53 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2009-3-20 15:57:51 | 显示全部楼层
看看這個, 原始紅外遙控碼分析 : (使用 ATmega8/ATmega168 @16MHz)

http://www.arduino.cc/playground/Code/InfraredReceivers

也是用定时器T1输入捕捉中断服务程序, 能輸出時序數據, 再配合gnuplot,
能繪出原始紅外遙控碼. 適合初學者了解不同格式的紅外遙控碼. 實用啊.

出0入0汤圆

发表于 2009-3-20 17:36:48 | 显示全部楼层
做个记号

出0入0汤圆

发表于 2009-5-7 09:31:46 | 显示全部楼层
为什么要把
//#pragma interrupt_handler timer1_capt_isr:6
//void timer1_capt_isr(void)
两行注释掉

出0入0汤圆

发表于 2009-5-7 10:59:08 | 显示全部楼层
是不是应该在完成一次32位解码后,应停止TC1 捕捉,在处理完后再开捕捉啊,如果一直处于捕获状态,是不是对前一次的32位数据有影响,特别是在处理速慢的时候

出0入0汤圆

发表于 2009-5-11 20:36:58 | 显示全部楼层
我收下了,谢谢!

出0入0汤圆

发表于 2009-5-12 15:53:10 | 显示全部楼层
兄弟,有没有试过,同时有几个编码差不多的摇控器,一同发射,你的接收会正常吗?

出200入0汤圆

发表于 2009-5-12 16:58:04 | 显示全部楼层
支持一下~~~

出0入0汤圆

发表于 2009-5-13 17:25:49 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-5-15 01:34:56 | 显示全部楼层
ding

出0入0汤圆

发表于 2009-5-16 14:15:37 | 显示全部楼层
好的

出0入0汤圆

发表于 2009-5-27 10:55:45 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-5-28 14:25:52 | 显示全部楼层
也学习下

出0入0汤圆

发表于 2009-5-31 13:35:54 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-6-6 15:25:59 | 显示全部楼层
LZ 能否留下联系方式,小弟在调试中遇到了问题想请教,我也是用捕获功能来解码,下降沿触发,但总是捕获不到13.5ms的引导码!  ~我的QQ 416066411   希望其它知道原因的朋友能赐教,谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 23:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表