打印
[牛人杂谈]

几种比较流行和成熟的红外解码程序做一下研究和总结

[复制链接]
3926|33
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mintspring|  楼主 | 2016-6-13 22:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面对以下几种比较流行和成熟的红外解码程序做一下研究和总结
 
/*-----------------------------------------------------------------------------------------

                  定时器0中断处理

-----------------------------------------------------------------------------------------*/

void tim0_isr (void) interrupt 1 using 1

{

irtime++;  //用于计数2个下降沿之间的时间

}

/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(startflag)                        

{

if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

i=0;

}            

                      irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                      irtime=0;

                      i++;

                        if(i==33)

                        {

                                       irok=1;

                                          i=0;

                            }

}

           else

              {

                            irtime=0;

                            startflag=1;

              }

}



沙发
mintspring|  楼主 | 2016-6-13 22:16 | 只看该作者
先来分析一个这个程序,这个程序用了两个中断,一个定时器中断,一个外断中断,程序的算法是让定时器中断不停的记数,外部中断在下降没来临的时候将这个记数值并将上一次记的数值存在一个数组中,不过这个程序有一个小Bug,就是那个startflag是没有起到关键性的作用的啊?!其实编这个程序的程序员想的是用startflag,这个方法可以过滤过那一个引导码,但是如果你足够细心就会发现他没有做startflag清0的操作,不过诡异的事情是即使这样也没有影响正常的解码程序的运行,其实只要你认真分析一下就会发现有没有startflag清0这一个判断的条件其实没有多大的意义,我的意思是有没有这一条语句都不会影响正常的解码,首先来分析原程序,也就是没有startflag清0这一语句的情况,第一个引导码来的时候,进入else语句,将第一个引导码过虑掉,进入else语句的就是后面有用的解值了,第一次会执行到if(irtime<54&&irtime>=50)这一条语句,因为引导码的长度刚好在这个范围内,所以会执行下会的一条i=0,也就是会把数组的下标清0,然后会把相应的32个红外编码存到数组中,注意这里的数组的长度是33,而不是32,因为irdata[0]是用来存放引导码的,还有一点非常值很注意,就是这32个有效的红外数据接收完了之后,会有一个重复码,这个重复码和引导码长得很相似,这个我用示波器看过,这个重复码可以看作是第34个波形,而且有一点非常值很注意,就是这个重复码只要你按键不松手的话是一直会发的,所以如何处理这个重复码的问题也是很关键的,至于这个问题我后面会有讲到,现有我们先来将这个重复码看成是第34个红外码,他的意义在于可以提供一个下降沿,有了这个下降沿就会将第32个红外码值存入data[32]中,所以最终的结果就是33个红外编码全部存入了容量为33的数组中,但是这时还有一个问题就是如果按键按下不放的话,后面还会有无数的波形啊,这时解码程序还在不停的处理,后面的红外编码会存入第34,35,36……等后面的数组中,这是不希望看到的,这也会导致一个更加可怕的问题,那就是程序的溢出,那天在防真器上出现了这个问题决对就是这个原因.因为数组只有33个元素,而在接收到这33个元素之后还没有停止对红外码的接收,后面的元素继续存入只有33个元素的数组中,必定会导致数据的溢出,也就是会弹出那样的一个溢出的界面,我还记得当天没有接红外接收管硬件的时候也会有这个溢出的窗口,那是因为当时没有在中断进入这后将中断标志位清0,所以会一直有中断进来,从而这33个元素的数组就会很快存满了,然后还在进入不停的进入中断,最后导致这33个元素的数组全部存满了还在不停的往里面存数据,所以也会导致程序的溢出.所以以后就有了一条经验,那就是如果程序溢出了有一种可能性就是往一个固定长度的数组中存入了大于其长度的数据.那么如何解决这个问题呢,一种可行的方法是这样的,待33个红外数据全部存完以后,置一个标志,后面接收到的数据只要不是引导码就做一次函数返回,当接收到这个正确的引导码以后才可以进行下一轮数据的接收.

              上面的这个问题暂且放下(只要摇控器发出的波形只有34个脉冲就不会出现上面的问题 ,这种摇控器的特点就是只要你按下一个按键不论你是不松手,它都只会发出一帧数据,不会有后面的故虑),下面考虑第二帧数据的接收情况,当第二帧数据来临的时候,由于没有清0 startflag,程序会进入if(startflag)这一个分支,也就是会处理引导码的情况,这里会到下面的一条语句if(irtime<63&&irtime>=33),而这时irtime是一个随机的数,所以说这条语句有可能能被执行到也有可能不会被执行到,无论其是否能被执行到,都无所谓,等下一个下降沿到来的时候那个时候irtime存入的才是引导码的数据,也就是直到第二个下降沿到来的时候,irdata的下标才会清0,这时才会将引导码存入irdata的第0个格子里面.而后的数据会将先前的数据覆盖掉,也就消除了第一次接收到的数据的不稳定因素.

              如果有接收到第33个元素后将startflag清0.每次接收红外的时候就和第一次的一样了,还过即使是这样也不能摆脱那个接收到重复码的问题.下面是有startflag清0的程序.

使用特权

评论回复
板凳
mintspring|  楼主 | 2016-6-13 22:17 | 只看该作者
/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(startflag)                        

{

if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

i=0;

}            

                      irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                      irtime=0;

                      i++;

                        if(i==33)

                        {

                                       irok=1;

                                          i=0;

                                          startflag=0;

                            }

}

           else

              {

                            irtime=0;

                            startflag=1;

              }

}


使用特权

评论回复
地板
mintspring|  楼主 | 2016-6-13 22:18 | 只看该作者
下面做一个解决重复码问题的程序:
/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(statflag==1)

{

              if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

                                                       i=0;

                                                        ir_flag=0;                                                                               //接收到正确的引导码,开始接收数据

}

else

{

                                          return;                                                                                    //这个是33个红外码后面的重复码,过滤掉他

}

If(ir_flag==0)                                                                        //如果接收到引导码才开始解码

{            

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                                    irtime=0;

                                    i++;

                                                    if(i==33)

                                                    {

                                                                   irok=1;

                                                                      i=0;

                                          startflag=0;

                                                                      ir_flag=1;                                                                               //接收完33个数据,清0接收数据位,即不再接收数据

                                                        }

}

else

{

startflag==1

i=0;

                            return;

}

}


使用特权

评论回复
5
mintspring|  楼主 | 2016-6-13 22:18 | 只看该作者
这个程序有一个关键的地方,那就是那个引导码的时间,程序就是通过这个时间来确定是否开始接收一帧数据的,真到接收到33个数据后将关闭数据的接收功能,直到有第二个引导码的到来,才开始接收第二帧数据.如果重复码我这个引导码很像,那么这个一点的时间的差别也是很关键的了,所以必须把握好这个时间,比如13.5ms,12M的晶振定时器计一次时间是256us比如把这个时间卡在13ms到14ms之间就应该是13000/256=50,14000/256=54,也就是说应该把两个时间卡在50和54之间,这样的精度才能保证将那些个重复码的脉冲过滤掉,这个卡的越准越好越小越好.也就这在逻辑上也是可行完美合理的程序.逻辑上就是要让一帧数据接收完成之后停止数据的接收功能.上面各全局变量的初始化情况为ir_flag=0;startflag=0;

              想一想如果这个程序像下面这样会有什么后果,即去掉startflag这个标置,会有什么后果?

使用特权

评论回复
6
mintspring|  楼主 | 2016-6-13 22:19 | 只看该作者
/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

                                         i=0;

ir_flag=0;                                                                               //接收到正确的引导码,开始接收数据

}

else

{

                                          return;                                                                                    //这个是重复码,过滤掉他

}

If(ir_flag==0)

{            

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                      irtime=0;

                      i++;

                        if(i==33)

                        {

                                       irok=1;

                                          i=0;

                                          ir_flag=1;                                                                               //接收完33个数据,清0接收数据位,即不再接收数据

                            }

}

}


使用特权

评论回复
7
mintspring|  楼主 | 2016-6-13 22:21 | 只看该作者
这个程序没有用startflag这个标置,也就不能保证接收到的第一个脉冲是引导码了,这时会有一个随机的数存入irtime,如果这个随机数是和引导码的irtime相似的话,就会造成解码的开启,第二个码,也就是引导码会存入irdata[1]中,后面所有的码就会依次往后推移一次,这样的话第33个红外码就会丢失掉,也就去直接导致解码的失败.所以说完美的程序应该是上面的那个程序.(这段话说的不对,那个i=0的操作会把数组的下标做一下清0,也就不存在移位的问题了.)

          特别纠正一下本文的错误之处,上面的两个程序都是有问题的,正确的程序应该是下面的程序,看完这个程序再来说明上面程序不正确的地方.
/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

                                         i=0;

ir_flag=0;                                                                               //接收到正确的引导码,开始接收数据

}

if(ir_flag==1)

{

                            irtime=0;

                                          return;                                                                                    //这个是重复码,过滤掉他

}

If(ir_flag==0)

{            

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                      irtime=0;

                      i++;

                        if(i==33)

                        {

                                       irok=1;

                                          i=0;

                                          ir_flag=1;                                                                               //接收完33个数据,清0接收数据位,即不再接收数据

                            }

}

}


使用特权

评论回复
8
mintspring|  楼主 | 2016-6-13 22:22 | 只看该作者
上面的那两个程序都不能按照正常的算法实现,关键在于有一个原因,那个else语句没有做irtime清零的操作,这样就会导致一个问题,就是下一个下降沿到来的时候不能反正确的两个下降沿之间的时间存入数中,存入的是不确定的数,所以说irtime清零这一步操作还是很有必要的,试想下一个正确的引导码到的的时候,没有irtime清0的操作也就不能识别能正确的引导码,也就不能够实现解码的开启,也就不能够实现正确的解码,不过上面的程序还是有一个问题,那就是他没有用startflag,也就会存在上面提到的那个问题,也说是说当有一个随机数,也就是下一帧数据开始接收时的第一个码,那个数就是一个随机数,如果那个数刚好是在引导码的时间区间内,那么就是恶梦的开始,也就是说会和上面的错误一样,这个随机数会存入irdata[0],引导码会存入irdata[1]中,下面的所有码都依次往下移一位,也说是说会有一位码没有存入这33个数据码中(包括引导码). (这段话说的不对,那个i=0的操作会把数组的下标做一下清0,也就不存在移位的问题了.)所以说这个程序可以说是一个比效完美的程序了
  下面是另一种编程的方法.
/*-----------------------------------------------------------------------------------------

                  外部中断0中断处理

-----------------------------------------------------------------------------------------*/

void EX0_ISR (void) interrupt 0 //外部中断0服务函数

{

           static unsigned char  i;            //接收红外信号处理

           static bit startflag;                //是否开始处理标志位

if(statflag==1)

{

              if(irtime<=54&&irtime>=50)//引导码 TC9012的头码,9ms+4.5ms

{

                                                       i=0;

                                                        ir_flag=0;                                                                               //接收到正确的引导码,开始接收数据

}

if(ir_flag==0)

{

                            irtime=0;

                            startflag=0;

                                          return;                                                                                    //这个是33个红外码后面的重复码,过滤掉他

}

If(ir_flag==1)                                                                        //如果接收到引导码才开始解码

{            

irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1

                                    irtime=0;

                                    i++;

                                                    if(i==33)

                                                    {

                                                                   irok=1;

                                                                      i=0;

                                          startflag=0;

                                                                      ir_flag=1;                                                                               //接收完33个数据,清0接收数据位,即不再接收数据

                                                        }

}

else

{

startflag==1

i=0;

                            return;

}

}
这个程序的算法是那些重复码会隔一个进入解码程序一个,进处解码程序的那个又会被过滤掉,也说是说第一个重复码的下降沿会进入else   starflag=1……的那个语句.下一个重复码的下降沿会被过滤掉,因为他不满足那个引导码时间的那个条件.所以他会被过滤掉.这就要求那个引导码的时间要足够的准确,范围也要足够的小,如果重复码和引导码比效相似的话那么事情就不妙了,那个条件就起不到过滤的作用了.这个严酷的条件也是这个程序的精髓.

使用特权

评论回复
9
mintspring|  楼主 | 2016-6-13 22:23 | 只看该作者
下面说一说第二种过滤重复码的方法,(这个方法是老板告诉我的,呵呵,不解释)废话不多说,直接上程序:
/*-----------------------------------------------------------------------------------------
                  定时器0中断处理
-----------------------------------------------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
       irtime++; //用于计数2个下降沿之间的时间,256us进一次定时器中断
         if(irtime>=1000)//irtime>=1000说明按键已经松天有1000*256=256ms了,故可以使能红外接收功能
         {
                  ir_flag=0;//使能红外接收功能
         }
}
/*-----------------------------------------------------------------------------------------
                  外部中断0中断处理
-----------------------------------------------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中断0服务函数
{
       static unsigned char  i;            //接收红外信号处理
       static bit startflag;                //是否开始处理标志位
if(irtime<=54&&irtime>=50)//接收到引导码 TC9012的头码,9ms+4.5ms
{
         i=0;
}
if(ir_flag==1)
{
         irtime=0;                             //清零计数器
         return;
}
if(ir_flag==0)
{
                   irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
             irtime=0;//清零irtime变量(老板习惯叫做寄存器)
             i++;//数组下标自增1
               if(i==33)
                {
                         irok=1;//接收完33个红外数据
                            i=0;//数组下标清零
                            ir_flag=1;//失能红外接收功能
                   }
         }
}
        
下面研究第二种红外解码的程序,这个程序没有用到任何中断,非常有意思啊,直接上源码.不解释.
/*----------------------------------------------------------------------------------------------------
                               红外解码处理函数
----------------------------------------------------------------------------------------------------*/
void ir(void)
{
         if(ir_check_flag==1)
         {
                   ir_check_flag=0;

                   if(PB.0==1)
                   {
                            if(irisH_bit==0)
                            {
                                     irisH_bit= 1;
                                     //这里可以添加上升沿到时时,做相应的处理
                            }
                   }
                   else
                   {
                            if(irisH_bit==1)
                            {
                                     irisH_bit= 0;
                                     if(irtime<=110&&irtime>=102)             //引导码TC9012的头码,9ms+4.5ms
                                     {
                                               ramaddr1= irdata;
                                               num= 0;
                                               ir_en_flag=0;
                                     }
                                     if(ir_en_flag==1)
                                     {
                                               irtime=0;                  //如果是重复码就将irtime清零,然后退出函数
                                               return;
                                     }
                                     if(ir_en_flag==0)
                                     {
                                               *ramaddr1= irtime;
                                               ramaddr1++;
                                               irtime= 0;
                                               num++;
                                               if(num==33)
                               {
                                   irok=1;          //32个数据全部存储完毕,一帧数据接收完毕
                                                        num=0;
                                                        ramaddr1= irdata;
                                                        ir_en_flag=1;
                               }
                                     }
                            }
                   }
                   irtime++;
         }
         else
         {
                   return;
         }
}
分析一下这个程序的算法,其思路类似于原来中断函数的方法,也是记录两个下降沿之间的时间,并将其存入33个元素的一个数组中,数组的第一个位置存入的是那个**的引导码,后面的32个位置存入的是32个红外编码.这个算法关键的一点就是那个irisH_bit位变量的作用.那个位变量是用来记录边沿的,无论是下降沿还是上升沿都能记录,这个记录的作用就是只能使相关的处理只在相应的上升沿还是下降沿作用一次.这个函数每128us扫描一次.每128us计数器irtime增加一次.先来分析程序运行时的情况,当没有下降沿的时候,一直是高电平一直执行if(PB.0==1)下面的语句irtime一直做叠加的操作.当加到最大值时又变为0做新一轮的叠加操作.这个是没有意义的,等到第一个下降沿到来的时候进入else语句由于是第一个下降沿那个这个irtime就是随机的了,这时ir_en_flag=0,因为是初始化时的值,下面分两种情况来说明这时的情况,如果这个irtime的时间刚好在引导码的区间,那么就会清零num,数组下标清0然后进入if(ir_en_flag==0)语句将这个值取入数组的第一个位置,然后下一个下降沿来到了,这时这个时间就是实实在在的引导码的时间,同样会进入if(irtime<=110&&irtime>=102)那一个分支,这时将数组下标清零,同时进入下一条分支语句if(ir_en_flag==0),这时将先前存入数组的每一个元素覆盖掉,那个也就不存在了,而后是32个红外数据的存入,这里有一个值得注意的问题在第32个红外数据接收完成之后,会有一个下降沿,这个是不属于那32个数据的电平.是多出来的一个下降沿,当这33个数据接收完成的时候,会关断数据的存储,只有下一次再接收到引导码才会再次开启数据的存储功能,这样做可以有效的把后面的重复码干掉,这个程序的关键仍然是那个引导码的时间只有这个时间足够准确,足够狭窄才能和那个重复码区别开来.

使用特权

评论回复
10
mintspring|  楼主 | 2016-6-13 22:24 | 只看该作者
下面提供另一个过滤重复码的方法,直接上源代码,不解释.
/*----------------------------------------------------------------------------------------------------
                                    红外解码处理函数
----------------------------------------------------------------------------------------------------*/
void ir(void)
{
         if(ir_check_flag==1)
         {
                   ir_check_flag=0;
                   if(PB.0==1)
                   {
                            if(irisH_bit==0)
                            {
                                     irisH_bit= 1;
                            }
                   }
                   else
                   {
                            if(irisH_bit==1)
                            {
                                     irisH_bit= 0;
                                     if(irtime<=110&&irtime>=102)   //引导码 TC9012的头码,9ms+4.5ms
                                     {
                                               ramaddr1= irdata;
                                               num= 0;
                                     }
                                     if(ir_en_flag==1)
                                     {
                                               irtime=0;           //如果是重复码就将irtime清零,然后退出函数
                                               return;
                                     }
                                     if(ir_en_flag==0)
                                     {
                                               *ramaddr1= irtime;
                                               ramaddr1++;
                                               irtime= 0;
                                               num++;
                                               if(num==33)
                               {
                                   irok=1;          //32个数据全部存储完毕,一帧数据接收完毕
                                                        num=0;
                                                        ramaddr1= irdata;
                                                        ir_en_flag=1;
                               }
                                     }
                            }
                   }
                   irtime++;
                   if(irtiem>=10000)              //如果长时间没有按下摇控的按键,就重新接收下一帧数据
                   {
                            ir_en_flag=0;
                   }
         }
         else
         {
                   return;
         }
}


使用特权

评论回复
11
mintspring|  楼主 | 2016-6-13 22:24 | 只看该作者
这个程序去除重复码的方法就是老板告诉我的去除重复码的方法.这里一帧新的数据的接收使能是松开按键的时间超过128ms,算法就是这样的,不过和上面的那个程序相比这个程序没有上面的那个好,第一个是这个时间如果设置的太短的话,过滤的作用,时间设置的太短,如果这个时间小于两个重复之间的时间间隔那会就会再次使能中断的接收,从而把原来的数据覆盖掉,导致程序的出错.如果这个时间设置的太长,那个一次按键按下去又得等待十年的时间才能再次开启红外的接收,是不是很坑爹啊!!!,即使这个时间设置的恰到好处,也还是有一个时间的延迟的,相比上面的那个没有时间延迟的程序还是有一点瑕疵啊!所以说上面那个程序,也就是我编的那处程序才是最好的算法和程序.

使用特权

评论回复
12
落叶行健ywm| | 2016-6-14 08:20 | 只看该作者
mark一下,以后用到来探讨下

使用特权

评论回复
13
Thethree| | 2016-6-14 15:22 | 只看该作者
延时如果想要精准的话还得用到定时器吧

使用特权

评论回复
14
mintspring|  楼主 | 2016-6-20 20:47 | 只看该作者
Thethree 发表于 2016-6-14 15:22
延时如果想要精准的话还得用到定时器吧

看延时多久的了,有些是个范围就对的,那就不用太精确。

使用特权

评论回复
15
643757107| | 2016-6-20 22:37 | 只看该作者
第二种红外解码的程序,这个程序没有用到任何中断,非常有意思

使用特权

评论回复
16
wahahaheihei| | 2016-6-21 10:38 | 只看该作者
红米手机现在都带红外功能了,内置多种遥控协议,各种红外遥控的设备全支持。

使用特权

评论回复
17
mintspring|  楼主 | 2016-6-28 15:39 | 只看该作者
红外功能非常使用,感觉比蓝牙还使用,好多东西可以遥控。

使用特权

评论回复
18
wahahaheihei| | 2016-6-29 18:02 | 只看该作者
万能遥控器应该是固化进了国际的若干种标准,好多厂商应该都是从这些标准里选择。

使用特权

评论回复
19
zhuomuniao110| | 2016-6-29 20:48 | 只看该作者

1.导言

1838一体化红外接收头是我们最常用的红外接收元器件。它被广泛的应用于电视机、空调、电冰箱以及电视机顶盒等需要红外遥控的电器上。当然,所有带红外遥控功能的单片机开发板上,也有它的身影。瑞生的LPC1114开发板上也没有放过它。

2.红外接收头与单片机的硬件连接

上图中,CON3代表红外接收管,1 2 3引脚定义分别为OUT、GND和VCC。其中,VCC可以接5V,也可以接3.3V,主要看与其连接的单片机工作电压是多少。电路中,R12用于给连接OUT引脚的单片机引脚上拉电阻,C16用于电源滤波,提高红外遥控稳定性。电路连接很简单吧。一看就知道,它与单片机之间采用单总线通信方式。


使用特权

评论回复
20
zhuomuniao110| | 2016-6-29 20:48 | 只看该作者

3.接收红外信号的流程

当你拿着一个红外遥控器对准红外接收头按时,红外接收头的OUT引脚将会如何变化?这个是由遥控器决定的,因为它只是起到一个解码的作用。在当下,我国,基本上是用的遥控器都是遵循NEC的编码方式。所以,我们就需要知道NEC红外遥控的编码方式了。

NEC红外遥控编码方式:它的指令格式依次为,码头+定制码高位+定制码低位+数据码+数据反码。码头用于通知红外遥控信号的来临,由9毫秒的低电平加4.5毫秒的高电平组成;定制码高位、定制码低位、数据码、数据反码都是1个字节。定制码高位与定时码低位组成一个16位的定制码,一般用来识别红外遥控器,就是说,假如你的空调的遥控器定制码是88,你家的电视遥控定制码是55,你用电视的遥控对空调就不起作用,如果你家的电视遥控和空调遥控的定制码相同,那你拿上电视的遥控对着空调按一番,说不定就出什么乱子了。数据码用于识别用户的功能,如加减声音、换台等按键发出的数据码都是不一样的。数据反码与数据码是反码的关系,用于校验数据码接收正确与否。

口述一下红外遥控按下以后,接收头OUT引脚的变化:首先是9ms的低电平,然后是4.5ms的高电平,然后将会出现定制码高位,定制码低位,数据码,数据反码,这4个码的逻辑1是560us低电平+1680us高电平,逻辑0是560us低电平+560us高电平。

上图是遥控器发出的脉冲信号,仔细的童鞋会看出,它的电平和我刚才口述的接收头接收到的信号电平刚好是相反的。

此外,用户如果一直按着一个键不放,将会发送重发码。重发码是跟在按键码后面的,它由9ms低电平+2.5ms高电平+560us低电平+97ms高电平组成,由重发码的规律,我们可以看出,当单片机观察到9ms低电平时,后面如果是4.5ms高电平,就是第一次按的按键码,如果9ms后面跟的是2.5ms高电平,就是重发码。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

298

主题

4931

帖子

24

粉丝