little4_su 发表于 2013-11-11 15:48:27

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

本人是阿莫电子论坛新人,做红外遥控时碰到了几个问题。遥控遵守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的。这让我很奇怪,后来只能cod&0xff得到正确的码。
不知大家用第三种方法的时候有没有碰到数据溢出,第一种和第二种方法有没有得到正确的码。

little4_su 发表于 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;
        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=kk=kk=kk=0x00;
                return;//返回等待下次继续接收
        }
       
        //高低电平总和都不在以上的值则为干扰信号
        else return;

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

中断法
//--------------------------------------------------------------------
//下降沿中断
//--------------------------------------------------------------------
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=dat;
        }//end for i
        sei();       
}
中断法和普通IO差不多。就不贴出来了。

1125526801 发表于 2017-6-30 15:55:31

菜鸟飞过学习~~~~为什么没高手来评论一下呢?

rjx 发表于 2017-7-17 08:15:33

本帖最后由 rjx 于 2017-7-17 08:20 编辑

用普通IO口做轮询方式和中断方式都可以得到正确的码值,只要程序是对的。但很多人都失败了,这是为什么呢?
我也曾经碰到过这些问题,后经多次试验摸索,发现主要原因是其中的延时函数的延时时间不正确所致。大多程序我们都是从书本上或网上抄来的,原来的程序是在特定的晶振频率下实现的,如原来的程序是在8M晶振下的延时时间,如果我们移植后是在4M晶振下运行,那么延时时间肯定是不对的,因为红外接收函数就是靠延时时间来判断码值的,延时时间不对,当然就无法得到正确的码值。
还有,即使和原来的晶振用的一样有时也还是不行,因为这些延时函数都是大概的时间,并不严格。我的办法是将延时程序用AVR Studio仿真软件单独测试,设定延时软件的延时时间分别为10MS,100ms,200MS进行测试,看看误差多大,再重新调整延时软件的参数,直到正确为止。如要要延时10MS,说不定参数要设成13MS才行!所以你把遥控程序里的几个用到的延时时间都仔细测试,弄到准确的延时时间,一般问题都能解决。
页: [1]
查看完整版本: 关于AVR接收红外遥控编码的若干问题