搜索
bottom↓
回复: 3

关于AVR接收红外遥控编码的若干问题

[复制链接]

出0入0汤圆

发表于 2013-11-11 15:48:27 | 显示全部楼层 |阅读模式
本人是阿莫电子论坛新人,做红外遥控时碰到了几个问题。遥控遵守NEC的协议。引导码是9000us(L)+4500us(H),数据位:560us(L)+560us(H)='0',560us(L)+1680us(H)='1'。引导码+8bit机器源码+8bit机器源码反码+8bit用户源码+8bit用户源码反码。
用了三种方法:1)普通IO口;2)外部INT0中断;3)PD6捕捉
第一种和第二种无法得到正确的码。但移植到S52硬件上却可以得到正确的码。第三种可以得到正确的码,但有个问题,就是用户源码得到的竟然是超过255的,接收以上波码的变量可都是声明为unsigned char cod[4]的。这让我很奇怪,后来只能cod[n]&0xff得到正确的码。
不知大家用第三种方法的时候有没有碰到数据溢出,第一种和第二种方法有没有得到正确的码。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2013-11-12 01:39:40 | 显示全部楼层
这个是捕捉方法
/*
//-------------------------------------------------------------------
//捕捉方式的红外遥控可以正检测到键值和及其码
//在2013-11-08AM01:00实验通过
//编译器:WinAvr2010
//遥控器为NEC协议
//-------------------------------------------------------------------
ISR(TIMER1_CAPT_vect)
{       
        static uint oldCapt;//旧捕捉时间
        uint newCapt;                //新捕捉时间
        static uchar bitcnt;//接收的数据位数总长度
        static uchar kk[4];
        uint temp=0;//用来存贮newCapt和oldCapt的时间差
        uchar x;
       
        newCapt=ICR1;
        temp=newCapt-oldCapt;
        oldCapt=newCapt;

        //数据位'0'的判断,低电平(565us)+高电平(560us) =1125us表示0
        if(temp>1025&&temp<1225)
                x=0;
               
        //数据位'1'的判断,低电平(565us)+高电平(1685us)=2250us表示1
        else if(temp>2150&&temp<2350)
                x=0x80;
       
        //起始信号判断,低电平(9000us)+高电平(4500us)  =13500us表示headcode
        else if(temp>13400&&temp<13600)
        {
                bitcnt=TCNT1=oldCapt=newCapt=0;
                kk[0]=kk[1]=kk[2]=kk[3]=0x00;
                return;//返回等待下次继续接收
        }
       
        //高低电平总和都不在以上的值则为干扰信号
        else return;

        if(bitcnt<8)
        {
                kk[0]>>=1;
                kk[0] |=x;
        }
        if(7<bitcnt&&bitcnt<16)
        {
                kk[1]>>=1;
                kk[1] |=x;
        }
        if(15<bitcnt&&bitcnt<24)
        {
                kk[2]>>=1;
                kk[2] |=x;
        }
        if(23<bitcnt&&bitcnt<32)
        {
                kk[3]>>=1;
                kk[3] |=x;
        }
        bitcnt++;
        if((kk[0]==((~kk[1])&0XFF))&&(kk[2]==((~kk[3])&0XFF)))//校验,必须有&0xff,否则会有数据溢出,比如开关机的码值是0x00-0xff-0x45-0xba,若无则会变成0x00-0xff-0x2ba-0xba
        {
                IRKEY[0]=kk[0];
                IRKEY[1]=kk[1];
                IRKEY[2]=kk[2];
                IRKEY[3]=kk[3];
        }
}
*/

中断法
//--------------------------------------------------------------------
//下降沿中断
//--------------------------------------------------------------------
ISR(INT0_vect)
{
        uchar i,j,dat,temp;
        uint n=2;
        //Lcd1602ShowString(0,0,"fuck");
        cli();
        _delay_ms(6);
        if(IR_RD())
        {
                sei();
                return;
        }//确定无干扰,有干扰跳出
        n=2;
        while(!IR_RD()) _delay_us(1);//跳过前导9ms低电平
        if(n==1)//电平持续时间过长,出错跳出
        {
                sei();
                return;
        }
        n=2;
        while(IR_RD()&&n++) _delay_us(1);//跳过前导4.5ms高电平
        if(n==1)//电平持续时间过长,出错跳出
        {
                sei();
                return;
        }
        for(i=0;i<4;i++)
        //搜集4组数据,每组8位
        {
                dat=0;
                for(j=0;j<8;j++)
                {
                        n=2;
                        while(!IR_RD()&&n++) _delay_us(1);//以为数据开始前的低电平
                        if(n==1)//电平持续时间过长,出错跳出
                        {
                                sei();
                                return;
                        }
                        _delay_us(2000);
                        temp=0;
                        if(IR_RD())//若700us后端口仍然是高电平,说明读到的数据是'1'
                                temp=0x80;
                        n=2;
                        //while(IR_RD()&&n++) _delay_loop_1(1);//等待高电平变为低电平
                        if(n==1)//电平持续时间过长,出错跳出
                        {
                                sei();
                                return;
                        }
                        dat>>=1;
                        dat|=temp;
                }//end for j/
                key[i]=dat;
        }//end for i
        sei();       
}
中断法和普通IO差不多。就不贴出来了。

出0入0汤圆

发表于 2017-6-30 15:55:31 | 显示全部楼层
菜鸟飞过学习~~~~为什么没高手来评论一下呢?

出0入0汤圆

发表于 2017-7-17 08:15:33 | 显示全部楼层
本帖最后由 rjx 于 2017-7-17 08:20 编辑

用普通IO口做轮询方式和中断方式都可以得到正确的码值,只要程序是对的。但很多人都失败了,这是为什么呢?
我也曾经碰到过这些问题,后经多次试验摸索,发现主要原因是其中的延时函数的延时时间不正确所致。大多程序我们都是从书本上或网上抄来的,原来的程序是在特定的晶振频率下实现的,如原来的程序是在8M晶振下的延时时间,如果我们移植后是在4M晶振下运行,那么延时时间肯定是不对的,因为红外接收函数就是靠延时时间来判断码值的,延时时间不对,当然就无法得到正确的码值。
还有,即使和原来的晶振用的一样有时也还是不行,因为这些延时函数都是大概的时间,并不严格。我的办法是将延时程序用AVR Studio仿真软件单独测试,设定延时软件的延时时间分别为10MS,100ms,200MS进行测试,看看误差多大,再重新调整延时软件的参数,直到正确为止。如要要延时10MS,说不定参数要设成13MS才行!所以你把遥控程序里的几个用到的延时时间都仔细测试,弄到准确的延时时间,一般问题都能解决。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-25 12:37

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

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