高效NEC遥控解码,任意IO(精简10行C语言)
以前刚学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; // 接收数据缓存
//下面为解码的关键部分,大家自己去分析。主思路就是计算下降沿间隔,其余什么高电平多少时间,低电平多少时间都不关心,因此代码比较精简。
//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 <<= 1;
if( irTime>15 ) IR_data++;// 大于15*125us=1.875ms的间隔为数据1
}
irTime = 0; // 下降沿处理完成,将时间清0
}
}
使用时只需查询codeCnt的值是否等于31(如果解码完成30ms后才去判断codeCnt==31,codeCnt将不会再是31,可以在程序中修改该标志的存活时间),是表示解码完成,解码数据放于IR_data[]数组中; 因为该解码的核心思想是检测两个下降沿相隔的时间,所以只要两个下降沿间隔符合,不管高低电平时间都会进行解码,所以如果要提高准确性,需把IR_data[]中的数据进行检验,
也就是看是否IR_data==IR_data,如果是,99%是正确的.
{:victory:}
不错,绑定 谢谢!以后有机会试试看 CTRL+D
LZ这个思路不错,标记下。 哈哈,自己写的比这个长好多,收下学习啦,谢谢LZ 这个任意IO口比较方便,哪天试试。 思路很好,代码页很简洁,收下了 以后试试 好东西收藏先~ 125us执行中断程序一次
也够利害的! 留个记号先 留个记号~~ markmarkmark 125us中断一次,51单片机,建议将计算部分移出来,然后中断就读几个数完了,否则很容易死机.加多几个中断的活,另外没有加长按哦.
不过挺不错的,一般够用了.
谢谢,手下了。
不错,绑定 {:lol:}谢谢,收下了。
nec高效10行代码遥控器解码 好东西,要收下 看不大懂C语言
有汇编的吗? 谢谢楼主这个真的不错 不错,学习。 收藏起了{:smile:} 简洁高效,好东西。 要是把“遥控控制RGB灯变色”全部程序发出来就好了{:tongue:} 记号,不错的程序 学习一下! 支持原创! 我用外部中断写的 好长啊
留个记号 有空试试 很不错,支持一个 {:smile:}下同是用外部中断写的也很简洁,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 |= 0x01;
}
else
{
if((IR_Code.bytes == 0x00)&&(IR_Code.bytes == 0xff)) //custor code
{
if(IR_Code.bytes | IR_Code.bytes == 0xffu) {OpCode = IR_Code.bytes;IR_OK_F=1;}
else {IR_OK_F=0;}
}
}
IR_Time80us = 0x00;
}
}
MARK,做个记号 果断收藏!!! {:handshake:}{:call:}收藏了 谢谢分享~~ 不用费这劲,串口1200或者2400波特率直接解码 收下学习!谢谢分享~ 真不错,学习了! 好东西,要收下
记号 收藏了 记号备用,谢谢! 不错,拿来试试看 收藏来学习,谢谢LZ。 一定要标记学习下 好东西,要收下
不错,学习学习 Garbage614 发表于 2013-3-6 09:20 static/image/common/back.gif
不用费这劲,串口1200或者2400波特率直接解码
有想法,占一个 好贴留名先 马克,,,,,,,, Mark 外部中断状态解码 MARK......... 不错 用到后再看看 果断收藏!!! {:smile:}感谢分享 好东西,要收下
Mark 不错,收下啦 最近刚做这方面的实验, 外部中断或是这种中断的方式都会让CPU没有时间再去处理其他的工作.
假如系统还有使用其他中断的话, 也会影响到遥控器信号的接收稳定性.不晓得是否还有其他的
解决方案? 谢谢楼主分享 不错,谢谢楼主 都不错,支持下 收藏先,留着备用. 支持,支持,学习,学习!!! 不错,学习学习 收藏先,学习中
谢谢,收藏 我来泼几瓢冷水,不过在泼水之前还是夸奖楼主几句:很认真!做得很精简!
但正是因为你做得很精简,所以……反而是有问题的。
这个问题的根本原因就在于……你将实际情况想象得太理想了。
你说灵敏度在99%以上,你跑到一个到处都是日光灯的环境试试?
1、对于红外遥控器来说,其实灵敏度和误码率,是一对矛盾的。
从你自己的描述和程序来看,你其实是牺牲了误码率的,也就是说,很可能外界的干扰(其它发红外线的东西或者类似的遥控器)会误操作你的接收设备的。在我看来,灵敏度很重要,其实误码率更重要。
2、这个程序,只适合移植到小项目中,如果项目稍微大一点,你分给遥控器的时间片还是太多了,系统开销会不够的。
Louis_Bright 发表于 2013-3-25 10:10 static/image/common/back.gif
我来泼几瓢冷水,不过在泼水之前还是夸奖楼主几句:很认真!做得很精简!
但正是因为你做得很精简,所以… ...
误码率肯定存在,不过不会像楼上说的那样不堪,这个程序是在一大片日光灯下调试的,没有存在乱接收的现象(以测试了很长时间),这个大家可以自己验证。
另外关于时间片开销大得问题,125us应该不算很大开销,因为设为125us还用来做时间计数用的。另外时间间隔可以调至400us一次,如果再大些的话就不能解码了。 好使,留个记号 Garbage614 发表于 2013-3-6 09:20 static/image/common/back.gif
不用费这劲,串口1200或者2400波特率直接解码
串口解码,求教? angler12 发表于 2013-4-1 22:31 static/image/common/back.gif
串口解码,求教?
你把IR的接收口街道串口的RX引脚 波特率设置在2400或者1200 就能收到数据了 mark 好帖 顶 忽略前导码,可以啊,呵呵 mark下来学习~~ Garbage614 发表于 2013-4-2 08:52 static/image/common/back.gif
你把IR的接收口街道串口的RX引脚 波特率设置在2400或者1200 就能收到数据了 ...
谢谢,不错的解决方法! 记号,谢谢 记号,留存 最近在研究这个 谢谢 红外采用中断方式来处理,我以前做过,是有很多缺点。看了楼主的定时方式,还是不错的。可以借鉴。 好东西,要收下 mark,mark,mark 有机会试试看 好东西,要收下
学习了 最近也要搞一个rgb灯,还没加遥控。 谢谢楼主分享,这个就是采样的原理
好东西,要记下 先收藏再说 哈哈,,明白了,,下次要移植试下,,,多谢LZ分享!! 试一下! if(irTime==240) {irTime--;codeCnt=0x3f;} // ir解码后码值存放时间, 240*125us = 30ms
这句什么时候能执行到?有空回复下,谢谢! 好热闹,很不错的代码 yh8637 发表于 2013-4-28 17:31 static/image/common/back.gif
if(irTime==240) {irTime--;codeCnt=0x3f;} // ir解码后码值存放时间, 240*125us = 30ms
这句什么时候能 ...
解码过后(或者没有下降沿后)30ms irTime就会加到240,然后会一直为240(如果没有下降沿过来),codeCnt就会变成0x3f(0011 1111),这样是为了方便 codeCnt++;codeCnt &= 0x1f;
这段代码,这样再次进入解码时,codeCnt又会自动从0开始计数 标记,这要用 很好的代码,最近自己写了一个, {:biggrin:}下来试了一下!真的是很不错! mark;万恶的7个字节; copy下来再研究 好东西,正在玩这个 本帖最后由 HeP028 于 2013-4-30 23:18 编辑
11.0592MHZ
误码率很搞啊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
void IRConfiguration(void)
{
T2MOD= 0X00; //16位自动重装
T2CON= 0X00;
RCAP2H = (65535-115) / 256;
RCAP2L = (65535-115) % 256;
ET2 = 1;
TR2 = 1;
EA = 1;
}
但为何老是误第二字节呢?
页:
[1]
2