搜索
bottom↓
回复: 161

高效NEC遥控解码,任意IO(精简10行C语言)

  [复制链接]

出0入0汤圆

发表于 2012-11-8 22:29:34 | 显示全部楼层 |阅读模式
以前刚学MCU时做过红外遥控解码,参考别人的程序写了老半天,总共几十行,用外部中断方式,而且还很不好使。
后来在做一个遥控控制RGB灯变色时,发现用外部中断方式解码在按键时RGB灯老闪(中断处理解码去了,PWM波程序被打断了,PWM用软件模拟的),
这时想可不可以不用中断来做呢,就在网上搜了搜,发现一个,就在这个基础上做了大量优化,最后的解码程序只有10行左右,且灵敏度也很好,给大家分享一下。

悄悄告诉你:这个代码相当好用!各种MCU移植都很方便
上源码:(只是核心部分)

sbit IR_IO = P1^6;          // IR管脚 任意IO

//定时器初始化为125uS中断一次
void IR_decode_init(void)
{
   TMOD |= 0x12;                     // T1定时方式2
//--------------设定中断时间------------------------
   TH0 = (-125);  TL0 = (-125); // 定时125us 12M晶振
    ET0 = 1;        TR0 = 1;        // 启动T1
    EA = 1;                              // 总中断允许
}
//解码的相关数据              
bit Irprot_LastState = 0;   // 端口状态位
uchar codeCnt = 0;          // 数据码位计数
uchar irTime;                   // 码时间,用于以125us时间计时
uchar IR_data[4];            // 接收数据缓存

//下面为解码的关键部分,大家自己去分析。主思路就是计算下降沿间隔,其余什么高电平多少时间,低电平多少时间都不关心,因此代码比较精简。
//125us执行中断程序一次
void Timer0(void) interrupt 1                                                            
{   
   irTime++;
   if(irTime==240) {irTime--;  codeCnt=0x3f;} // ir解码后码值存放时间, 240*125us = 30ms
   if(IR_IO)   Irprot_LastState=1; // 记录IO状态
   else if(Irprot_LastState)       // 有下降沿
   {
      Irprot_LastState = 0;        // 下降沿后IO状态记录为0
      if(irTime<24)                // 小于24*125us=3ms的间隔才进行处理
      {
         codeCnt++;  codeCnt &= 0x1f;
         IR_data[codeCnt>>3] <<= 1;
         if( irTime>15 )   IR_data[codeCnt>>3]++;  // 大于15*125us=1.875ms的间隔为数据1
      }
      irTime = 0;                  // 下降沿处理完成,将时间清0
   }
}

使用时只需查询codeCnt的值是否等于31(如果解码完成30ms后才去判断codeCnt==31,codeCnt将不会再是31,可以在程序中修改该标志的存活时间),是表示解码完成,解码数据放于IR_data[]数组中; 因为该解码的核心思想是检测两个下降沿相隔的时间,所以只要两个下降沿间隔符合,不管高低电平时间都会进行解码,所以如果要提高准确性,需把IR_data[]中的数据进行检验,
也就是看是否IR_data[2]==IR_data[3],如果是,99%是正确的.




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

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

出0入0汤圆

发表于 2012-11-8 22:39:59 | 显示全部楼层


不错,绑定

出0入0汤圆

发表于 2012-11-8 22:54:14 | 显示全部楼层
谢谢!以后有机会试试看

出0入4汤圆

发表于 2012-11-8 23:24:32 | 显示全部楼层
CTRL+D
  

出0入169汤圆

发表于 2012-11-8 23:33:44 | 显示全部楼层
LZ这个思路不错,标记下。

出0入0汤圆

发表于 2012-11-8 23:50:02 | 显示全部楼层
哈哈,自己写的比这个长好多,收下学习啦,谢谢LZ

出0入0汤圆

发表于 2012-11-9 07:21:09 | 显示全部楼层
这个任意IO口比较方便,哪天试试。

出0入0汤圆

发表于 2012-11-9 08:46:22 | 显示全部楼层
思路很好,代码页很简洁,收下了

出0入0汤圆

发表于 2012-11-9 09:29:39 | 显示全部楼层
以后试试

出0入0汤圆

发表于 2012-11-9 11:49:00 | 显示全部楼层
好东西  收藏先~

出0入0汤圆

发表于 2012-11-9 11:59:28 | 显示全部楼层
125us执行中断程序一次
也够利害的!

出0入0汤圆

发表于 2012-11-9 22:41:12 | 显示全部楼层
留个记号先

出0入0汤圆

发表于 2012-11-9 23:41:10 来自手机 | 显示全部楼层
留个记号~~

出0入0汤圆

发表于 2012-11-9 23:49:41 | 显示全部楼层
markmarkmark

出0入0汤圆

发表于 2012-11-9 23:54:59 | 显示全部楼层
125us中断一次,51单片机,建议将计算部分移出来,然后中断就读几个数完了,否则很容易死机.加多几个中断的活,另外没有加长按哦.

不过挺不错的,一般够用了.

出0入0汤圆

发表于 2012-11-10 13:26:21 | 显示全部楼层
谢谢,手下了。

出0入0汤圆

发表于 2012-11-10 13:46:20 | 显示全部楼层
不错,绑定                  

出0入0汤圆

发表于 2012-11-10 13:47:46 | 显示全部楼层
谢谢,收下了。

nec高效10行代码遥控器解码

出0入0汤圆

发表于 2012-11-10 13:49:16 | 显示全部楼层
好东西,要收下

出0入0汤圆

发表于 2012-11-10 15:02:14 | 显示全部楼层
看不大懂C语言
有汇编的吗?

出0入0汤圆

发表于 2012-11-10 15:21:03 | 显示全部楼层
谢谢楼主这个真的不错

出0入0汤圆

发表于 2012-11-10 16:02:59 | 显示全部楼层
不错,学习。

出0入0汤圆

发表于 2012-11-10 16:26:02 | 显示全部楼层
收藏起了

出0入0汤圆

发表于 2012-11-10 16:41:28 | 显示全部楼层
简洁高效,好东西。

出0入0汤圆

发表于 2012-11-11 17:03:05 | 显示全部楼层
要是把“遥控控制RGB灯变色”全部程序发出来就好了

出0入13汤圆

发表于 2012-11-11 17:18:25 | 显示全部楼层
记号,不错的程序

出0入0汤圆

发表于 2012-11-11 17:59:36 | 显示全部楼层
学习一下!

出0入0汤圆

发表于 2012-11-11 20:34:46 | 显示全部楼层
支持原创!

出0入0汤圆

发表于 2012-11-11 21:00:38 | 显示全部楼层
我用外部中断写的 好长啊
留个记号 有空试试

出0入0汤圆

发表于 2012-11-11 21:02:03 | 显示全部楼层
很不错,支持一个

出0入0汤圆

发表于 2012-11-11 21:33:17 | 显示全部楼层
下同是用外部中断写的也很简洁,MCU为sonix 的SN8P2501B :

/**************************************************************
                    Interrupt Program Zone
**************************************************************/
__interrupt intserv(void)
{
    if(FT0IRQ)
    {
            T0 = D_T0_Preset;
            FT0IRQ =0;
                IR_Time80us++;
           }
        //======================INT0 interrupt IR decode=======================
        if(FP00IRQ)
        {
                FP00IRQ = 0;

        //----------------------ir code receive-----------------------
            if ((IR_Time80us >= D_IR_HeadT_Min) && (IR_Time80us < D_IR_HeadT_Max))
                {
                        IR_bits = 0;
                }
                else if(IR_bits < 32)
                {
                    IR_bits++;
                        IR_Code.dwords <<=1;
                        if(IR_Time80us >= D_IR_TimeBitAs1) IR_Code.bytes[0] |= 0x01;
                }               
            else
            {
                        if((IR_Code.bytes[3] == 0x00)&&(IR_Code.bytes[2] == 0xff))                                        //custor code
                   {
                               if(IR_Code.bytes[0] | IR_Code.bytes[1] == 0xffu) {OpCode = IR_Code.bytes[1];IR_OK_F=1;}
                          else                                             {IR_OK_F=0;}
                   }   
        }
                IR_Time80us = 0x00;          
        }
}

出0入0汤圆

发表于 2013-3-5 22:43:53 | 显示全部楼层
MARK,做个记号

出0入0汤圆

发表于 2013-3-5 22:49:34 | 显示全部楼层
果断收藏!!!

出0入0汤圆

发表于 2013-3-5 23:09:37 | 显示全部楼层
收藏了

出0入0汤圆

发表于 2013-3-6 09:15:52 | 显示全部楼层
谢谢分享~~

出0入0汤圆

发表于 2013-3-6 09:20:35 | 显示全部楼层
不用费这劲,串口1200或者2400波特率直接解码

出100入0汤圆

发表于 2013-3-6 09:20:51 | 显示全部楼层
收下学习!谢谢分享~

出0入0汤圆

发表于 2013-3-7 10:07:52 | 显示全部楼层
真不错,学习了!

出0入0汤圆

发表于 2013-3-7 13:45:23 | 显示全部楼层
好东西,要收下

出0入0汤圆

发表于 2013-3-7 21:19:55 | 显示全部楼层
记号 收藏了
头像被屏蔽

出0入0汤圆

发表于 2013-3-7 21:57:11 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2013-3-7 22:16:51 | 显示全部楼层
记号备用,谢谢!

出0入0汤圆

发表于 2013-3-7 22:35:55 | 显示全部楼层
不错,拿来试试看

出0入0汤圆

发表于 2013-3-8 11:17:25 | 显示全部楼层
收藏来学习,谢谢LZ。

出0入0汤圆

发表于 2013-3-8 16:44:06 | 显示全部楼层
一定要标记学习下

出0入0汤圆

发表于 2013-3-8 16:45:55 | 显示全部楼层
好东西,要收下  

出0入0汤圆

发表于 2013-3-8 20:46:59 | 显示全部楼层
不错,学习学习

出0入0汤圆

发表于 2013-3-8 21:06:34 | 显示全部楼层
Garbage614 发表于 2013-3-6 09:20
不用费这劲,串口1200或者2400波特率直接解码

有想法,占一个

出0入0汤圆

发表于 2013-3-8 21:34:20 | 显示全部楼层
好贴留名先

出0入0汤圆

发表于 2013-3-8 22:04:35 | 显示全部楼层
马克,,,,,,,,

出0入0汤圆

发表于 2013-3-9 15:09:37 | 显示全部楼层
Mark 外部中断状态解码

出0入0汤圆

发表于 2013-3-9 15:21:30 | 显示全部楼层
MARK.........

出0入0汤圆

发表于 2013-3-11 16:49:55 来自手机 | 显示全部楼层
不错 用到后再看看

出0入0汤圆

发表于 2013-3-11 17:18:25 | 显示全部楼层
果断收藏!!!

出0入0汤圆

发表于 2013-3-11 17:21:49 | 显示全部楼层
感谢分享

出0入17汤圆

发表于 2013-3-11 17:46:55 | 显示全部楼层
好东西,要收下
Mark

出0入0汤圆

发表于 2013-3-11 17:57:08 | 显示全部楼层
不错,收下啦

出0入0汤圆

发表于 2013-3-11 23:36:04 | 显示全部楼层
最近刚做这方面的实验, 外部中断或是这种中断的方式都会让CPU没有时间再去处理其他的工作.
假如系统还有使用其他中断的话, 也会影响到遥控器信号的接收稳定性.不晓得是否还有其他的
解决方案?

出0入0汤圆

发表于 2013-3-12 08:36:10 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2013-3-12 09:59:42 | 显示全部楼层
不错,谢谢楼主

出0入0汤圆

发表于 2013-3-19 09:51:22 来自手机 | 显示全部楼层
都不错,支持下

出0入0汤圆

发表于 2013-3-19 10:38:11 | 显示全部楼层
收藏先,留着备用.

出0入0汤圆

发表于 2013-3-24 18:40:18 | 显示全部楼层
支持,支持,学习,学习!!!

出0入0汤圆

发表于 2013-3-24 18:51:48 | 显示全部楼层
不错,学习学习

出0入0汤圆

发表于 2013-3-24 21:20:30 | 显示全部楼层
收藏先,学习中

出0入0汤圆

发表于 2013-3-25 09:39:57 | 显示全部楼层
谢谢,收藏

出0入0汤圆

发表于 2013-3-25 10:10:42 | 显示全部楼层
我来泼几瓢冷水,不过在泼水之前还是夸奖楼主几句:很认真!做得很精简!

但正是因为你做得很精简,所以……反而是有问题的。
这个问题的根本原因就在于……你将实际情况想象得太理想了。
你说灵敏度在99%以上,你跑到一个到处都是日光灯的环境试试?

1、对于红外遥控器来说,其实灵敏度和误码率,是一对矛盾的。
从你自己的描述和程序来看,你其实是牺牲了误码率的,也就是说,很可能外界的干扰(其它发红外线的东西或者类似的遥控器)会误操作你的接收设备的。在我看来,灵敏度很重要,其实误码率更重要。
2、这个程序,只适合移植到小项目中,如果项目稍微大一点,你分给遥控器的时间片还是太多了,系统开销会不够的。

出0入0汤圆

 楼主| 发表于 2013-3-25 18:57:15 | 显示全部楼层
Louis_Bright 发表于 2013-3-25 10:10
我来泼几瓢冷水,不过在泼水之前还是夸奖楼主几句:很认真!做得很精简!

但正是因为你做得很精简,所以… ...

误码率肯定存在,不过不会像楼上说的那样不堪,这个程序是在一大片日光灯下调试的,没有存在乱接收的现象(以测试了很长时间),这个大家可以自己验证。
另外关于时间片开销大得问题,125us应该不算很大开销,因为设为125us还用来做时间计数用的。另外时间间隔可以调至400us一次,如果再大些的话就不能解码了。

出0入0汤圆

发表于 2013-3-25 20:16:56 | 显示全部楼层
好使,留个记号

出110入8汤圆

发表于 2013-4-1 22:31:38 | 显示全部楼层
Garbage614 发表于 2013-3-6 09:20
不用费这劲,串口1200或者2400波特率直接解码

串口解码,求教?

出0入0汤圆

发表于 2013-4-2 08:52:50 | 显示全部楼层
angler12 发表于 2013-4-1 22:31
串口解码,求教?

你把IR的接收口街道串口的RX引脚   波特率设置在2400  或者1200 就能收到数据了

出0入0汤圆

发表于 2013-4-2 10:01:03 | 显示全部楼层
mark 好帖 顶

出0入0汤圆

发表于 2013-4-2 10:20:19 | 显示全部楼层
忽略前导码,可以啊,呵呵

出0入0汤圆

发表于 2013-4-2 14:59:35 | 显示全部楼层
mark下来学习~~

出110入8汤圆

发表于 2013-4-3 08:40:48 | 显示全部楼层
Garbage614 发表于 2013-4-2 08:52
你把IR的接收口街道串口的RX引脚   波特率设置在2400  或者1200 就能收到数据了 ...

谢谢,不错的解决方法!

出0入0汤圆

发表于 2013-4-3 08:48:10 | 显示全部楼层
记号,谢谢

出0入0汤圆

发表于 2013-4-3 14:34:50 | 显示全部楼层
记号,留存

出0入0汤圆

发表于 2013-4-3 23:14:50 | 显示全部楼层
最近在研究这个 谢谢

出0入0汤圆

发表于 2013-4-4 17:32:40 | 显示全部楼层
红外采用中断方式来处理,我以前做过,是有很多缺点。看了楼主的定时方式,还是不错的。可以借鉴。

出0入0汤圆

发表于 2013-4-5 09:45:03 | 显示全部楼层
好东西,要收下

出0入0汤圆

发表于 2013-4-5 09:55:21 | 显示全部楼层
mark,mark,mark

出0入0汤圆

发表于 2013-4-5 09:57:40 | 显示全部楼层
有机会试试看

出0入0汤圆

发表于 2013-4-5 10:54:58 | 显示全部楼层
好东西,要收下

出0入0汤圆

发表于 2013-4-21 23:51:35 | 显示全部楼层
学习了            

出0入0汤圆

发表于 2013-4-22 03:11:41 来自手机 | 显示全部楼层
最近也要搞一个rgb灯,还没加遥控。

出0入0汤圆

发表于 2013-4-22 06:23:36 | 显示全部楼层
谢谢楼主分享,这个就是采样的原理

出0入0汤圆

发表于 2013-4-22 08:11:08 | 显示全部楼层

好东西,要记下

出0入0汤圆

发表于 2013-4-24 00:33:21 来自手机 | 显示全部楼层
先收藏再说

出0入0汤圆

发表于 2013-4-27 14:25:59 | 显示全部楼层
哈哈,,明白了,,下次要移植试下,,,多谢LZ分享!!

出0入0汤圆

发表于 2013-4-28 01:05:45 来自手机 | 显示全部楼层
试一下!

出0入0汤圆

发表于 2013-4-28 17:31:20 | 显示全部楼层
if(irTime==240) {irTime--;  codeCnt=0x3f;} // ir解码后码值存放时间, 240*125us = 30ms
这句什么时候能执行到?有空回复下,谢谢!

出0入0汤圆

发表于 2013-4-28 17:52:09 | 显示全部楼层
好热闹,很不错的代码

出0入0汤圆

 楼主| 发表于 2013-4-28 19:33:58 | 显示全部楼层
yh8637 发表于 2013-4-28 17:31
if(irTime==240) {irTime--;  codeCnt=0x3f;} // ir解码后码值存放时间, 240*125us = 30ms
这句什么时候能 ...

解码过后(或者没有下降沿后)30ms irTime就会加到240,然后会一直为240(如果没有下降沿过来),codeCnt就会变成0x3f(0011 1111),这样是为了方便 codeCnt++;  codeCnt &= 0x1f;
这段代码,这样再次进入解码时,codeCnt又会自动从0开始计数

出0入0汤圆

发表于 2013-4-28 21:57:41 来自手机 | 显示全部楼层
标记,这要用

出0入0汤圆

发表于 2013-4-29 22:35:56 | 显示全部楼层
很好的代码,最近自己写了一个,

出0入0汤圆

发表于 2013-4-30 11:56:45 | 显示全部楼层
下来试了一下!真的是很不错!

出0入0汤圆

发表于 2013-4-30 13:26:14 | 显示全部楼层
mark;万恶的7个字节;

出0入0汤圆

发表于 2013-4-30 15:06:31 | 显示全部楼层
copy下来再研究

出0入0汤圆

发表于 2013-4-30 15:35:33 | 显示全部楼层
好东西,正在玩这个

出0入0汤圆

发表于 2013-4-30 23:17:11 | 显示全部楼层
本帖最后由 HeP028 于 2013-4-30 23:18 编辑

11.0592MHZ

误码率很搞啊
  1. 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 01 3A C5 00 FF 3A C5 00 FF 3A C5 00 7F 3A C5 00 FF 3A C5 00 FF 3A C5 00 07 3A C5 00 FF 3A C5 00 FF 3A C5 00 7F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 03 3A C5 00 03 3A C5 00 FF 3A C5 00 1F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 7F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 0F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 01 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 0F 3A C5 00 0F 3A C5 00 07 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 01 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 03 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 1F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 1F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 7F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 3F 3A C5 00 FF 3A C5 00 7F 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 FF 3A C5 00 0F 3A C5 00 FF 3A C5 00 FF 3A C5

  2. void IRConfiguration(void)
  3. {
  4.         T2MOD  = 0X00;                                                                        //16位自动重装
  5.         T2CON  = 0X00;
  6.         RCAP2H = (65535-115) / 256;
  7.         RCAP2L = (65535-115) % 256;
  8.         ET2    = 1;
  9.         TR2    = 1;
  10.         EA     = 1;
  11. }

复制代码
但为何老是误第二字节呢?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-24 17:01

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

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