搜索
bottom↓
楼主: BXAK

发一个红外线解码程序+仿真文件(可定义任意I/O作接收脚,支持长/短按,自适应主频6MHz~40

  [复制链接]

出0入0汤圆

发表于 2012-5-11 17:29:53 | 显示全部楼层
好好学习

出0入0汤圆

发表于 2012-5-20 21:21:25 | 显示全部楼层
你好,我想问问,
  else while(1)                            //38KHz脉冲,占空比5:26
         {
              IR = 0;
              if(TF0)break;
              if(TF0)break;
              IR = 1;
                if(TF0)break;
                 if(TF0)break;
                 if(TF0)break;
              if(TF0)break;
                 if(TF0)break;
                 if(TF0)break;
                 if(TF0)break;
                 if(TF0)break;
                 if(TF0)break;
              if(TF0)break;
                 }
怎么就实现了占空比为 5:26 啊,不解?

出0入0汤圆

 楼主| 发表于 2012-5-20 21:27:46 | 显示全部楼层
本帖最后由 BXAK 于 2012-5-20 21:29 编辑
fanjian224 发表于 2012-5-20 21:21
你好,我想问问,
  else while(1)                            //38KHz脉冲,占空比5:26
         {


看36、43、44楼回复

出0入0汤圆

发表于 2012-5-20 21:33:36 | 显示全部楼层
BXAK 发表于 2012-5-20 21:27
看36、43、44楼回复

楼主谢谢啦

出0入0汤圆

发表于 2012-5-20 21:37:38 | 显示全部楼层
过些天也要弄一下红外,看看

出0入0汤圆

发表于 2012-5-20 21:54:05 | 显示全部楼层
楼主,我想问问怎么才能增加红外发送距离,老师让我们做个红外,要发送距离为50米,我看了看网上,最多就是10米
楼主,你给点建议吧

出0入0汤圆

 楼主| 发表于 2012-5-20 22:49:27 | 显示全部楼层
fanjian224 发表于 2012-5-20 21:54
楼主,我想问问怎么才能增加红外发送距离,老师让我们做个红外,要发送距离为50米,我看了看网上,最多就是 ...

红外不可见光,还是红外激光?
通信点对点,还是像家用遥控器那样广角度?

我们平时用的红外发射二极管是 20多mW(压降约1.4v,工作平均电流一般小于20mA),较好环境下遥控>=10米,
如果是红外不可见光广角度遥控更远距离,
要用大功率红外发射二极管,淘宝有卖0.3W、0.5W的,1元多,
50米也就是用于室外了,也就不可能像室内那样随意方向都可以遥控电视,
要选着发射角度较小的,信号才不会过于分散,保证距离远时信号强度;但发射角度太小信号过于集中遥控角度就小了,根据需要(有10、30、45、60度角的),
室外的强光环境,接收头型号、滤光、聚光也要考虑(还是一句话,根据实际需要增减,实验如果不加滤光、聚光也OK那最好),
其它的看看43、44楼回复



出0入0汤圆

发表于 2012-5-20 23:42:25 来自手机 | 显示全部楼层
mark           .

出0入0汤圆

发表于 2012-5-23 21:53:27 | 显示全部楼层
BXAK 发表于 2012-2-5 22:42
回复【34楼】tzsteel
-----------------------------------------------------------------------

楼主,想问问哪种红外一体接收头比较好,最好接收距离比较远的

出0入0汤圆

 楼主| 发表于 2012-5-23 23:00:11 | 显示全部楼层
fanjian224 发表于 2012-5-23 21:53
楼主,想问问哪种红外一体接收头比较好,最好接收距离比较远的

接触有限,就不推荐了,你暂时用一般的一体化接收管实验,把发射部分搞好,尽量试试看能多远,
那个发射管要>=0.3W的,发射角度小些10度、20度角,直径>=5mm,淘宝有卖自己搜索

另:2~3只发射管串联发射,供电源的电容量也要够大

出0入0汤圆

发表于 2012-5-24 13:04:43 | 显示全部楼层
BXAK 发表于 2012-5-23 23:00
接触有限,就不推荐了,你暂时用一般的一体化接收管实验,把发射部分搞好,尽量试试看能多远,
那个发射 ...

嘻嘻,非常感谢楼主!!!

出0入0汤圆

发表于 2012-5-30 15:55:36 | 显示全部楼层
楼主,麻烦问下,发射用的PNP什么型号比较合适?

出0入0汤圆

 楼主| 发表于 2012-5-30 16:06:35 | 显示全部楼层
fanjian224 发表于 2012-5-30 15:55
楼主,麻烦问下,发射用的PNP什么型号比较合适?

S8550挺合适的,没有就9012之类

出0入0汤圆

发表于 2012-5-30 19:12:14 | 显示全部楼层
BXAK 发表于 2012-5-30 16:06
S8550挺合适的,没有就9012之类

嗯,谢谢啦

出0入0汤圆

发表于 2012-5-31 19:50:47 | 显示全部楼层
楼主,我想问问,你拿这个程序做过实物没,想问问你用的红外接收管的型号是多少?
我用的红外发射管是遥控上的l,接收头不知道什么型号,是不是型号不一样接收不到啊?

出0入0汤圆

发表于 2012-5-31 19:54:13 | 显示全部楼层
收藏了,慢慢看!

出0入0汤圆

发表于 2012-5-31 19:54:37 | 显示全部楼层
收藏了,慢慢看!        

出0入0汤圆

发表于 2012-5-31 19:54:56 | 显示全部楼层
收藏了,慢慢看!        

出0入0汤圆

发表于 2012-5-31 19:55:12 | 显示全部楼层
收藏了,慢慢看!        

出0入0汤圆

发表于 2012-5-31 19:55:33 | 显示全部楼层
收藏了,慢慢看!        

出0入0汤圆

发表于 2012-5-31 19:56:00 | 显示全部楼层
收藏了,慢慢看!        

出0入0汤圆

 楼主| 发表于 2012-5-31 20:22:20 | 显示全部楼层
fanjian224 发表于 2012-5-31 19:50
楼主,我想问问,你拿这个程序做过实物没,想问问你用的红外接收管的型号是多少?
我用的红外发射管是遥控 ...

自然做过,也用很久了,
你发射、接收所用的单片机具体是什么型号,晶振多少

出0入0汤圆

发表于 2012-6-2 17:51:30 | 显示全部楼层
BXAK 发表于 2012-5-31 20:22
自然做过,也用很久了,
你发射、接收所用的单片机具体是什么型号,晶振多少 ...

楼主,现在能用了,发射用的是89C52,接收用的是90C51

出0入0汤圆

发表于 2012-6-2 18:04:02 | 显示全部楼层
BXAK 发表于 2012-5-20 22:49
红外不可见光,还是红外激光?
通信点对点,还是像家用遥控器那样广角度?

楼主,你好,我用的红外线不可见光点对点通信,角度10度的就行
想问问红外用的聚光镜一般用什么啊,我想用这个东西让红外平行发射,不至于太过分散。
楼主,你一般做红外时用聚光镜吗?

出0入0汤圆

发表于 2012-6-2 18:10:47 | 显示全部楼层
这个现在正需要!记号!

出0入0汤圆

 楼主| 发表于 2012-6-2 19:18:17 | 显示全部楼层
fanjian224 发表于 2012-6-2 18:04
楼主,你好,我用的红外线不可见光点对点通信,角度10度的就行
想问问红外用的聚光镜一般用什么啊,我想 ...

我用来遥控家里的小电器,用不上这么小得角度。

红外线发射管 + 一般的放大镜就行(注意:发射管要散光类的,放大镜的焦距要小),不过自己弄挺麻烦的,像:调节、固定……都不方便,
钱包鼓的话,建议买现成的,不过挺贵的,好像便宜的也要几十元,其实也就是我平常看到的(可见光)红外激光笔,只是把发光管换成了真正的红外线发射管(不可见光),
如果还是打算自己弄的话,可以买(可见光)红外激光笔(就2元钱)拆了用里面的放大镜

PS:
相同直径下,放大镜焦距小放大倍数大,放大镜焦距大放大倍数小。
红外不可见光可以用手机的摄像头观察。

出0入0汤圆

发表于 2012-6-4 16:14:51 | 显示全部楼层
BXAK 发表于 2012-2-2 19:32
回复【18楼】tzsteel
-----------------------------------------------------------------------
else wh ...

楼主,你好,这个程序的载波频率为38.461kHz
如何能让频率变为38Khz呢

出0入0汤圆

发表于 2012-6-4 16:15:55 | 显示全部楼层
楼主,你好,这个程序的载波频率为38.461kHz
如何能让频率变为38Khz呢

出0入0汤圆

 楼主| 发表于 2012-6-4 19:14:05 | 显示全部楼层
fanjian224 发表于 2012-6-4 16:15
楼主,你好,这个程序的载波频率为38.461kHz
如何能让频率变为38Khz呢

19楼、20楼、36楼回复有说明

出0入0汤圆

发表于 2012-6-4 20:44:08 | 显示全部楼层
BXAK 发表于 2012-6-4 19:14
19楼、20楼、36楼回复有说明

我还是闹不懂nop()需要多少时间,
如果是12Mhz的话,应该是1us吧,不知道我说的对不对
如果是1us的话,那就达不到38Khz啦
楼主,麻烦你给解释一下吧,谢谢啦

出0入0汤圆

 楼主| 发表于 2012-6-4 21:39:17 | 显示全部楼层
本帖最后由 BXAK 于 2012-6-4 21:41 编辑

38KHz周期:26.315789473684210526315789473684us
老51(如:AT89C52、STC89C52……)指令速度以机器周期来算:1机器周期(us) = 12个时钟 = 12/频率(MHz)
增强型高速51(如:STC 1T系列……)指令速度直接以时钟来算,时钟(us) = 1/频率(MHz)

老51很难生成26.315789473684210526315789473684us,除非用特殊频率的晶振,STC 12T系列@12MHz时只能用最接近的26us,也就是38.461KHz
高速51可以接近很接近,STC 1T系列@12MHz时可以用最接近的26.333333333333333333333333333333us,也就是37.974KHz


出0入0汤圆

发表于 2012-6-5 10:14:35 | 显示全部楼层
tzsteel 发表于 2012-2-2 19:04
回复【楼主位】BXAK
-----------------------------------------------------------------------

大侠,你好,我想问问你怎么用软件实现载波频率为38Khz的微调的,楼主的载波频率38.46Khz,我想实现38Khz,怎么微调啊?

出0入0汤圆

 楼主| 发表于 2012-6-5 10:23:14 | 显示全部楼层
fanjian224 发表于 2012-6-5 10:14
大侠,你好,我想问问你怎么用软件实现载波频率为38Khz的微调的,楼主的载波频率38.46Khz,我想实现38Khz ...

看132楼的说明

出0入0汤圆

发表于 2012-6-5 10:34:13 | 显示全部楼层
BXAK 发表于 2012-6-4 21:39
38KHz周期:26.315789473684210526315789473684us
老51(如:AT89C52、STC89C52……)指令速度以机器周期来 ...

楼主,谢谢你啦

出0入0汤圆

发表于 2012-7-5 19:07:01 | 显示全部楼层
请问一下楼主红外解码部份,好像只是解点按的,要解连按的话要咋弄啊?连按的话,是连着发9MS+2.25MS的码。谢谢

出0入0汤圆

发表于 2012-7-7 19:03:44 | 显示全部楼层
很不错      

出0入0汤圆

发表于 2012-7-7 20:10:41 | 显示全部楼层
MARK!人都说好!我也马克。

出0入0汤圆

发表于 2012-7-21 15:49:57 | 显示全部楼层
请问解码程序中的#define    Boot_Limit            (((9000+4500) +2000)/Step)          //引导码周期上限   
#define    Boot_Lower            (((9000+4500) -2000)/Step)          //引导码周期下限   
#define    Bit1_Limit       ((2250 +800)/Step)                  //“1”周期上限
#define    Bit0_Limit       ((1125 +400)/Step)                          //“0”周期上限
是怎么得出来的,看不明白,上限和下限是根据什么计算出来的。

出0入0汤圆

发表于 2012-7-21 18:24:33 | 显示全部楼层
BXAK 发表于 2012-6-5 10:23
看132楼的说明

请问BXAK解码程序中引导码和bit 0发送和bit 1发送怎么有上下限啊,这点不明白Boot_Limit,Boot_Lower,Bit1_Limit, Bit0_Limit这几个是什么意思。我明白数据码中一字节数据会有时间长短不一样。但是引导码在不是9ms高电平和4.5ms 低电平吗,是怎样计算出来的

出0入0汤圆

 楼主| 发表于 2012-7-21 18:45:08 | 显示全部楼层
就是做个阀门,不过允许误差2000us有点大了,改成1000吧,
说白了,就是设置允许误差范围,
理论引导码周期9000+4500,单片机不可能每次检测到的引导码周期准准是13500ms,尤其是程序里用的是定时器中断查询下降沿,实际测出的值有些波动在所难免,

13500 -1000<时间<13500 +1000,就可以认为是引导码到了,同步置位开始尝试解码

出0入0汤圆

 楼主| 发表于 2012-7-21 18:46:15 | 显示全部楼层
c475301174 发表于 2012-7-21 18:24
请问BXAK解码程序中引导码和bit 0发送和bit 1发送怎么有上下限啊,这点不明白Boot_Limit,Boot_Lower,Bi ...

就是做个阀门,不过允许误差2000us有点大了,改成1000吧,
说白了,就是设置允许误差范围,
理论引导码周期9000+4500,单片机不可能每次检测到的引导码周期准准是13500ms,尤其是程序里用的是定时器中断查询下降沿,实际测出的值有些波动在所难免,

13500 -1000<时间<13500 +1000,就可以认为是引导码到了,同步置位开始尝试解码

出0入0汤圆

发表于 2012-7-21 18:58:59 | 显示全部楼层
BXAK 发表于 2012-7-21 18:46
就是做个阀门,不过允许误差2000us有点大了,改成1000吧,
说白了,就是设置允许误差范围,
理论引导码周 ...

谢谢BXAK的解答,我还以为是数据码中那种全0或全1而导致一字节数据时间有一个范围,现在明白了,谢谢~^~

出0入0汤圆

发表于 2012-7-26 14:52:27 | 显示全部楼层
#include "INC\MY_SET.H"
#include "INC\IR_NEC.H"     //调用NEC解码头文件

这两个文件有么?

出0入0汤圆

 楼主| 发表于 2012-7-26 17:06:04 | 显示全部楼层
huangpeifeng 发表于 2012-7-26 14:52
#include "INC\MY_SET.H"
#include "INC\IR_NEC.H"     //调用NEC解码头文件

都在压缩包里面

出0入0汤圆

发表于 2012-7-26 20:32:54 | 显示全部楼层
BXAK 发表于 2012-7-26 17:06
都在压缩包里面

找到了,不过收到会有时乱码,如果长按一次就在P1++;怎么改呢?程序反应有点慢

出0入0汤圆

发表于 2012-7-30 15:39:14 | 显示全部楼层
谢谢楼主,正要学习这个,还有个问题想请教下,就是你现在的那按连按处理,是达到了时间后才动作的,但是如果要改成你电视那种音量控制那种方式要怎么改动呢

出0入0汤圆

发表于 2012-8-17 09:59:42 | 显示全部楼层
mark 一下

出0入0汤圆

发表于 2012-8-17 16:03:43 | 显示全部楼层
收藏之

出0入0汤圆

发表于 2012-8-17 16:05:00 | 显示全部楼层
支持下,楼主辛苦

出0入0汤圆

发表于 2012-8-17 16:50:21 | 显示全部楼层
写的不错~~~~~~~                       

出0入0汤圆

发表于 2012-8-20 19:51:56 | 显示全部楼层
本帖最后由 hubaixdl123 于 2012-8-21 19:49 编辑

用VU2联合PROTEUS进行仿真发送部分没有问题。
但是用VU2联合PROTEUS进行接收解码仿真时,出现了指针跑乱的情况,用其它版本也是一样。我将接收解码的程序从
IR_NEC.H中考到主程序后,程序可以运行,但是相应的发送部分无法同时进行,依据是发送一边的LED没有显示。
如果有可以仿真接收部分的大侠,请告知解决方法。谢谢!

出0入0汤圆

发表于 2012-8-21 20:14:36 | 显示全部楼层
学习学习,谢谢

出0入0汤圆

发表于 2012-8-31 10:59:13 | 显示全部楼层
好东西。不过没装仿真软件,打不开.DSn文件,楼主位的图太小,看不清电阻值多少,请问发射功能单片机电路中三个电阻分别是多少?

出0入0汤圆

发表于 2012-8-31 12:09:07 | 显示全部楼层
顶……

出0入0汤圆

发表于 2012-9-3 10:49:01 | 显示全部楼层
楼主怎么还没有来

出0入0汤圆

发表于 2012-9-3 11:20:26 | 显示全部楼层
不错,谢谢!!!

出0入0汤圆

发表于 2012-9-3 12:16:49 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2012-9-3 12:31:56 | 显示全部楼层
看到了,就标记下,说不定会用到!

出0入0汤圆

发表于 2012-9-4 11:48:46 | 显示全部楼层
xyr 发表于 2012-5-7 09:18
不是软件的问题,我由原来AVR Studio 4改为ICC编译就好了,具体AVR Studio 4为什么不行我还未查清,

谢 ...

移值成功啦?移植到AVR了?

出0入0汤圆

发表于 2012-10-2 15:29:50 | 显示全部楼层
点h文件里面有程序也能编译,我以前连定义变量在点h文件里也会报错。

出0入0汤圆

发表于 2012-11-15 22:04:46 | 显示全部楼层
不错,学习一下

出0入0汤圆

发表于 2012-11-15 22:28:08 来自手机 | 显示全部楼层
不错的

出0入0汤圆

发表于 2012-11-27 20:25:05 | 显示全部楼层
学学,最近正在解码红外。

出0入0汤圆

发表于 2012-11-29 17:01:36 | 显示全部楼层
有人在AT89C2051上测试通过吗?

出0入0汤圆

发表于 2012-11-30 21:47:29 | 显示全部楼层
用AT89C2051芯片,同样采用12M晶振,将代码修改为如下:
发射部分:
#include <AT892051.h>
#include "INC\MY_SET.h"

//sbit  IR  = P3^6;                                  //发射引脚(接PNP三极管基极)
sbit  IrOutput  = P1^6;       

//#define  USER_H   P2              //用户码高8位
//#define  USER_L   P0              //用户码低8位

#define  USER_H  0x03
#define  USER_L         0xFC

//uint8c tab[16] = {                                  //操作码
// 0x12,0x05,0x1e,0x55,
// 0x01,0x1b,0x03,0x6b,
// 0x07,0x08,0x09,0x68,
// 0x22,0xE6,0x33,0xe2};

#define m9    (65536-9000)               //9mS
#define m4_5  (65536-4500)               //4.5mS
#define m1_6  (65536-1650)               //1.65mS
#define m_56  (65536-560)               //0.56mS
#define m40   (65536-40000)       //40mS
#define m56   (65536-56000)       //56mS
#define m2_25 (65536-2250)        //2.25mS

void  ZZ(uint8 x);                                  //NEC编码发送程序
void  Z0(uint8 temp);                          //单帧(8位数据)发送程序
void  TT0(bit BT,uint16 x);                  //38KHz载波发射 + 延时程序

void delay()  //延时程序,大约 1s
{
  int i,j;
  for(i=0;i<400;i++)
  {
    for(j=0;j<100;j++)
    {
    }
  }
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:主程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void main(void)
{
  TMOD = 0x01;         //T0 16位工作方式
  IrOutput=1;                           //发射端口常态为高电平  (接PNP三极管基极)
  //IrOutput=0;                                   //发射端口常态为低电平  (接NPN三极管基极)

  while(1)
  {          
    ZZ(0x05);
        delay();
        delay();
        delay();
  }
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:NEC编码发送程序
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void ZZ(uint8 Value)
{

  TT0(1,m9);                       //高电平9mS
  TT0(0,m4_5);                   //低电平4.5mS

  /*┈ 发送4帧数据┈*/
  Z0(USER_H);                              //用户码高8位                                                                                                               
  Z0(USER_L);                           //用户码低8位
  Z0(Value);                           //操作码
  Z0(~Value);                           //操作码反码

  /*┈┈ 结束码 ┈┈*/
  TT0(1,m_56);
  TT0(0,m40);

  /*┈┈ 重复码 ┈┈*/
  /*while(1)//KEY() != 0xFF)
   {
        TT0(1,m9);
        TT0(0,m2_25);

        TT0(1,m_56);
        TT0(0,m40);
                TT0(0,m56);                                  
    } */                  
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:单帧(8位数据)发送程序
入口:temp
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void Z0(uint8 temp)
{
  uint8 v;
  for (v=0;v<8;v++)                     //循环8次移位
  {     
                 TT0(1,m_56);                        //高电平0.65mS         
                         if(temp&0x01) TT0(0,m1_6); //发送最低位
                         else          TT0(0,m_56);     
                         temp >>= 1;                //右移一位
  }   
}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:38KHz载波发射 + 延时程序
入口:(是否发射载波,延时约 x (uS))
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void TT0(bit BT,uint16 x)
{
  TH0 = x>>8;                    //输入T0初始值
  TL0 = x;
  TF0=0;                                //清0
  TR0=1;                                //启动定时器0
  if(BT == 0) while(!TF0);        //BT=0时,不发射38KHz载波只延时;BT=1发射38KHz脉冲且延时;
  else while(1)                            //BT=1时,发射38KHz脉冲+延时;38KHz载波,(低电平)占空比5:26
       {
                  IrOutput = 0;        // PNP
                 // IrOutput = 1;   // NPN
                  if(TF0)break;if(TF0)break;
                  _nop_();          //频率有些高,降低添加适量的空操作“_nop_();”(注:不要放在大括号两侧)
                  IrOutput = 1;        // PNP
                  //IrOutput = 0;   // NPN
                if(TF0)break;if(TF0)break;
                 if(TF0)break;if(TF0)break;
                 if(TF0)break;if(TF0)break;
                 if(TF0)break;if(TF0)break;
                 if(TF0)break;if(TF0)break;
                }
                /*
else while(1) //BT=1时,发射38KHz脉冲+延时;38KHz载波(低电平)占空比约5:26  
{  
     // IrOutput = 0;        // PNP
     IrOutput = 1;   // NPN
     if(TF0)break;if(TF0)break;
     if(TF0)break;if(TF0)break;
      _nop_();
      //IrOutput = 1;        // PNP
         IrOutput = 0;   // NPN
     if(TF0)break;if(TF0)break;  
     if(TF0)break;if(TF0)break;  
     if(TF0)break;if(TF0)break;  
     if(TF0)break;if(TF0)break;  
}
         */
  TR0=0;                                //关闭定时器0
  TF0=0;                                //标志位溢出则清0

  IrOutput =1;     //载波停止后,发射端口常态为高        (接PNP三极管基极)
//  IrOutput =0;     //载波停止后,发射端口常态为高        (接NPN三极管基极)
}

接收部分:
#include <AT892051.h>
#include "INC\MY_SET.H"
#include "INC\IR_NEC.H"                   //调用NEC解码头文件

sbit   IrLED =  P1^6;                 //指示1
sbit   LED1 = P1^5;                         //指示2
sbit   LED2 = P1^4;                         //指示3

void KZ0();      //短按处理

/***************** 主函数 ********************/
void main(void)
{
          IRSignal = 1;  //P1口引脚写入“1”时,其可用作输入端
        IR_Init();                           //红外线解码初始化
        LED1 = 1;
        LED2 = 1;

        IR_BT= 0;
                                                  
        while(1)
        {
          //遥控检测
          if ((IR_BT==2)||(IR_BT==3))                          
      {
            TR0 = 0;
            KZ0();                                   //短按处理       
                IR_BT =0;                        //清有效标志
            IRReset();
                TR0 = 1;
          }

          if (!IRSignal)
          {
             IrLED =0;
          }
          else
          {
             IrLED = 1;
          }
          
        }
}
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:遥控短按处理
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void KZ0()
{
   switch(NEC[2])             
   {
     // case 0x12: P10 = !P10; break;
          case 0x12:
             LED1 = 0;//~LED1;
                 LED2 = 1;
                 break;

          case 0x05:
             LED2 = 0;//~LED2;
                 LED1 = 1;
             break;

          case 0x1E: break;
          case 0x55: break;

          case 0x01: break;
          case 0x1B: break;
          case 0x03: break;
          case 0x6B: break;

          case 0x07: break;
          case 0x08: break;
          case 0x09: break;
          case 0x68: break;

          case 0x22: break;
          case 0xE6: break;
          case 0x33: break;
          case 0xE2: break;
          default:break;
   }
}

/********************** 定时器0中断函数************************/
void time0(void) interrupt 1
{
   IR_NEC();
}  

#ifndef __IR_NEC_H__
#define __IR_NEC_H__

//【用户必填项:USER_H、USER_L、Check_EN、CPU_Fosc、IR】
#define  USER_H     0x80                         //用户码高8位
#define  USER_L     0x7F                         //用户码低8位

#define  Check_EN   0                             //是否要校验16位用户码:不校验填0,校验则填1
       
#define  CPU_Fosc   12000000             //输入主频,自适应解码(单位:Hz,范围:6MHz ~ 40MHz)
#define  CA_S       8                             //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜)

//sbit IR = P3^6;                              //红外线接口(任意引脚)
sbit IRSignal = P1^7;                          //红外线接口(任意引脚)

#define  Step       400                             //红外采样步长:400us
#define  TH_H       ((65536-Step*(CPU_Fosc/300)/40000)/256)  //定时器高8位基准赋值
#define  TH_L       ((65536-Step*(CPU_Fosc/300)/40000)%256)  //定时器低8位基准赋值

uint8   IR_BT;                         //解码效果返回:0无效,1有效,2短按,3长按
uint8   NEC[4];                         //解码存放:16位用户码、操作码正反码
uint8   cntCA;                         //长按计数
//uint16  cntStep;                         //步数计
uint8   cntStep;                         //步数计
bit     IRa,IRb;                         //电位状态保存
bit     IRsync;                                 //同步标志
uint8   BitN;                //位码装载数

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:红外线解码初始化
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_Init()
{
        TMOD &= 0xF0;           //清定时器0
        TMOD |= 0x01;           //定时器0:16位定时器
        TL0 = TH_L;               //每步时间
        TH0 = TH_H;
        ET0 = 1;
        EA  = 1;
        TR0 = 1;
}

void IRReset()
{
          TL0 = TH_L;               //每步时间
        TH0 = TH_H;

    NEC[0] = 0x00;                         //解码存放:16位用户码、操作码正反码
        NEC[1] = 0x00;
    NEC[2] = 0x00;
    NEC[3] = 0x00;

    cntCA = 0;                         //长按计数
    cntStep = 0;                         //步数计
    IRa =0;
    IRb = 0;                         //电位状态保存
    IRsync =0;                                 //同步标志
    BitN =0;                //位码装载数
}

/*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/
//#define    Boot_Limit            (((9000+4500) +2000)/Step)          //引导码周期上限   
//#define    Boot_Lower            (((9000+4500) -2000)/Step)          //引导码周期下限   
//#define    Bit1_Limit       ((2250 +800)/Step)                  //“1”周期上限
//#define    Bit0_Limit       ((1125 +400)/Step)                          //“0”周期上限
//允许误差2000us有点大了,改成1000
#define    Boot_Limit            (((9000+4500) +1000)/Step)          //引导码周期上限   
#define    Boot_Lower            (((9000+4500) -1000)/Step)          //引导码周期下限   
#define    Bit1_Limit       ((2250 +800)/Step)                  //“1”周期上限
#define    Bit0_Limit       ((1125 +400)/Step)                          //“0”周期上限

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:红外线NEC周期采样解码法(定时中断,下降沿查询周期时间)
全局变量:IR_BT = 0无效
                  1有效,待继续判断长、短按(如不需要判断长、短按,则直接使用)
                              2短按
                              3长按
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_NEC()
{          
        TL0 = TH_L;               //重赋值
        TH0 = TH_H;       

        IRb = IRa;                   //上次电位状态
        IRa = IRSignal;           //当前电位状态

        cntStep++;                   //步数采样
        if (IR_BT==1)
        {
           if(cntStep>300)
           {
              IR_BT=2;//解码有效后,如果无长按,120ms(400us×300)后默认短按
           }
        }
//        IRb = IRa;                   //上次电位状态
//        IRa = IRSignal;                   //当前电位状态
       
        if(IRb && !IRa)                                            //是否下降沿(上次高,当前低)
        {
                if(cntStep > Boot_Limit)      //超过同步时间?
                {       
                    if(IR_BT==1)
                        {
                          if(++cntCA>CA_S)
                          {
                              IR_BT=3; //解码有效后,继续按住遥控>CA_S即长按
                          }
                        }
                        IRsync=0;                                  //同步位清0
                }
                else if (cntStep > Boot_Lower)
                {
                   IRsync=1;
                   BitN=32;
                }//同步位置1,装载位码数                          
                else if (IRsync)                                                       //如果已同步
                {
                        if(cntStep > Bit1_Limit)
                        {
                          IRsync=0;         
                        }         
                        else
                        {       
                                NEC[3] >>= 1;                               
                                if(cntStep > Bit0_Limit)
                                   NEC[3] |= 0x80;    //“0”与“1”

                if(--BitN == 0)                               
                                {
                                        IRsync = 0;                                     //同步位清0
#if (Check_EN == 1)                                       
                                        if((NEC[0]==USER_H)&&(NEC[1]==USER_L)&&(NEC[2]==~NEC[3])) //校验16位用户码、操作码正反码
                                         {
                                           IR_BT=1;
                                           cntCA=0;
                                        }             //解码有效,接下来判断:短按?长按?
#else
                                        if(NEC[2]==~NEC[3])
                                        {
                                          IR_BT=1;
                                          cntCA=0;
                                        } //校验操作码正反码
#endif                                       
                                }
                                else if ((BitN & 0x07)== 0)       //NEC[3]每装满8位,移动保存一次(即 BitN%8 == 0)
                                {       
                                   NEC[0]=NEC[1];
                                   NEC[1]=NEC[2];
                                   NEC[2]=NEC[3];
                                }
                        }
                }
                cntStep = 0;   //步数计清0
        }
}

//取消相关宏定义
#undef CPU_Fosc

#endif


其他部分,没有改动!

写入芯片之后, 无法解码出来哦!

拜托各位,看看问题出在哪里?

出0入0汤圆

发表于 2012-11-30 22:28:36 | 显示全部楼层
留个爪印

出0入0汤圆

发表于 2012-12-1 14:54:51 | 显示全部楼层
mTouch 发表于 2012-11-30 21:47
用AT89C2051芯片,同样采用12M晶振,将代码修改为如下:
发射部分:
#include

  移植到89C2051成功!
  前面不成功的原因是下面的代码的原因:
     if(NEC[2]==~NEC[3])
     {
         TR0 =0;   // 增加
         IR_BT=1;
    }
   判断解码成功之后, 没有TR0=0的话,
   下面的代码,没有执行到
   if(cntStep>300)
   {
      IR_BT=2;//解码有效后,如果无长按,120ms(400us×300)后默认短按
  }

    也没有执行到
          if(++cntCA>CA_S)
                          {
                              IR_BT=3; //解码有效后,继续按住遥控>CA_S即长按
                          }       

   这可能跟发射部分有关!
另外,还修改了下面的二句宏定义
#define    Boot_Limit            (((9000+4500) +500)/Step)          //引导码周期上限   
#define    Boot_Lower            (((9000+4500) -500)/Step)          //引导码周期下限   


  

出0入0汤圆

发表于 2012-12-2 13:13:15 | 显示全部楼层
mark............

出0入0汤圆

发表于 2012-12-2 22:05:50 | 显示全部楼层
好文章~~~~~~~~~~~~~

出0入0汤圆

发表于 2012-12-3 14:33:58 | 显示全部楼层
BXAK 发表于 2012-2-3 19:15
回复【22楼】tzsteel
-----------------------------------------------------------------------

  如何修改为占空比为1/3 或1/10 ?

出0入0汤圆

发表于 2012-12-3 14:50:32 | 显示全部楼层
楼主 ,这个程序有很大的BUG。。。单片机仿真中错开了漏洞所在。
单片机查询方式浪费了大量的单片机时间。
程序中的38K红外产生部分实际中不能应用。
相信产生的频率比38K低得多。。根本无法编码。
利用中断的方式比较适合。

出0入0汤圆

 楼主| 发表于 2012-12-3 20:42:23 | 显示全部楼层
Doctor_A 发表于 2012-12-3 14:50
楼主 ,这个程序有很大的BUG。。。单片机仿真中错开了漏洞所在。
单片机查询方式浪费了大量的单片机时间。
...

“相信产生的频率比38K低得多。。根本无法编码。”你懂汇编吗?你看过其他坛友的回复吗?说得这么绝对,从坛友的回复看,他们也成功了,而且我是实物验证成功了,想分享才弄了个仿真上传的

出0入0汤圆

发表于 2012-12-4 09:10:42 | 显示全部楼层
BXAK 发表于 2012-12-3 20:42
“相信产生的频率比38K低得多。。根本无法编码。”你懂汇编吗?你看过其他坛友的回复吗?说得这么绝对, ...

这样啊。。。我也是先利用查询方式失败后改用中断才可以执行的。。只不过占空比需要两个中断辅助完成调节而已。。查询方式以26US的时间查询示波器显示编码长度延长了不少。。得此回复

出0入0汤圆

发表于 2012-12-4 10:55:49 | 显示全部楼层
楼主,你现在这个程序只支持长短按键,如果要改成连按呢?要怎么改动?望指点

出0入0汤圆

发表于 2013-1-4 20:15:45 | 显示全部楼层
看看!谢谢!

出0入0汤圆

发表于 2013-1-6 07:03:32 来自手机 | 显示全部楼层
多好的贴子!总有人都不仔细看就回复!不知道会暴露出你挺二的啊!?

出0入0汤圆

发表于 2013-1-8 14:34:28 | 显示全部楼层
认真看了,这个代码写的很模块,复用率很高

出0入0汤圆

发表于 2013-1-22 00:56:22 | 显示全部楼层
不错!支持!

出0入0汤圆

发表于 2013-2-21 16:14:52 | 显示全部楼层
本帖最后由 beyondvs 于 2013-2-21 16:19 编辑
BXAK 发表于 2012-2-23 00:45
回复【45楼】wangyz1997
-----------------------------------------------------------------------


非常感谢楼主,用你的程序调通了12T的STC89C58系列单片机红外发射模块,但是我们现在用的都是1T的STC12C5A32S2单片机,楼主发得1T程序看的不太明白,请教如下:
void TT0(bit BT,uint16 X)
{
   uint8 t;

   TH0 = ((uint8 *)&X)[0];        //X高8位
   TL0 = ((uint8 *)&X)[1];        //X低8位
   TF0=0;                                //清0
   TR0=1;                                //启动定时器0
                                                                 
   if(BT)                                //38KHz载波,(低电平)占空比约 9:(9+28)【12M: 1t <=> 1/12(uS),38KHz周期26.316uS <=> 316t 】
   {                                                
          while(1)
          {
            IR_Out = 0;                                                 // 4t
        for(t=9;t;t--)if(TF0)goto TN;    // 2t + (4t+4t)*x
        if(TF0)goto TN;                                         // 4t
                IR_Out = 1;                                                 // 4t
        for(t=28;t;t--)if(TF0)goto TN;         // 2t + (4t+4t)*x
                if(TF0)goto TN;                                     // 4t
          }                                                                        
   }                                                                        
   else while(!TF0);

TN:TR0 =0;                                //关闭定时器0
   IR_Out =1;                            //38KHz载波停止后,发射端口常态=1
}
1.楼主程序里goto TN是什么意思?倒数第三行也有个TN:TR0 =0; 不明白什么意思。
2.TH0 = ((uint8 *)&X)[0];        //X高8位
   TL0 = ((uint8 *)&X)[1];        //X低8位
这个[0],[1]如何理解?为何12T程序里是这样赋初值的
TH0 = x>>8;                  //输入定时值
  TL0 = x;
麻烦楼主把1T的38KHz载波发射 + 延时程序重新注释整理共享下,非常感谢,感觉楼主这段程序写的 太精妙。
3.12T发射程序里
TT0(1,m9);             //高电平9mS
  TT0(0,m4_5);             //低电平4.5mS

  /*┈ 发送4帧数据┈*/
  Z0(USER_H);             //用户码高8位
  Z0(USER_L);             //用户码低8位
  Z0(Value);             //操作码
  Z0(~Value);             //操作码反码

  /*┈┈ 结束码 ┈┈*/
  TT0(1,m_56);
  TT0(0,m40);
NEC协议里为何有结束码?不是9MS高电平+低电平4.5mS+用户名+用户反码+操作码+操作反码吗?

出0入0汤圆

发表于 2013-2-21 17:37:15 来自手机 | 显示全部楼层
不错,支持下

出0入0汤圆

 楼主| 发表于 2013-2-21 23:14:21 | 显示全部楼层
beyondvs 发表于 2013-2-21 16:14
非常感谢楼主,用你的程序调通了12T的STC89C58系列单片机红外发射模块,但是我们现在用的都是1T的STC12C5 ...

1、关于 goto:http://baike.baidu.com/view/3209842.htm,看了就知道 TN 是干嘛的


2、 ((uint8 *)&X)[0]、 ((uint8 *)&X)[1] 通过指针方式获取X的高八位、低八位(具体看C语言的指针用法),而且这个还要注意不同编译器大小端不同,比如:
【大小端】
Keil-C51    大端寻址
SDCC-C51 小端寻址
AVRGCC   小端寻址
……
如果将一个32位的整数0x12345678存放到一个长整型变量(long)中,这个整型变量采用大端或者小端模式在内存中的存储由下表所示。
简单起见,用OP0表示一个32位数据的最高字节MSB(Most Significant Byte),用OP3表示一个32位数据最低字节LSB(Least Significant Byte)。  
地址偏移        大端模式         小端模式
0x00            12(OP0)         78(OP3)
0x01            34(OP1)         56(OP2)
0x02            56(OP2)         34(OP1)
0x03            78(OP3)         12(OP0)

如:uint16 X = 0x1234,
在 Keil-C51 中, ((uint8 *)&X)[0] 即是 0x12 、 ((uint8 *)&X)[1] 即是 0x34;
在 SDCC-C51 中, ((uint8 *)&X)[0] 即是 0x34 、 ((uint8 *)&X)[1] 即是 0x12;
在 AVRGCC 中, ((uint8 *)&X)[0] 即是 0x34 、 ((uint8 *)&X)[1] 即是 0x12;


3、标准NEC编码没仔细看,但我平时用的各种成品NEC编码遥控器都这样,自己用示波器 或者 简易逻辑分析仪((最新)热转印自制了一个红外线遥控逻辑分析器) 捕捉一个完整的波形看看最清楚

出0入0汤圆

发表于 2013-2-22 21:27:01 | 显示全部楼层
先下载,有时间试试。

出0入0汤圆

发表于 2013-2-27 12:05:49 | 显示全部楼层
今天试了楼主的1T发射程序,可以发射,楼主真是牛人,还有一些疑问要请教楼主:我家电视机遥控器是NEC协议的,DVD遥控器是其他协议的,而空调遥控器是每按一次键,发送两次NEC协议码,如何做到能学习各种遥控器码?

出0入0汤圆

发表于 2013-2-27 12:17:56 | 显示全部楼层
mark, 好资料

出0入0汤圆

发表于 2013-2-27 12:30:22 | 显示全部楼层
好东西,顶起来,感谢共享~~~~~~~~~~~~

出0入0汤圆

 楼主| 发表于 2013-2-27 20:41:53 | 显示全部楼层
beyondvs 发表于 2013-2-27 12:05
今天试了楼主的1T发射程序,可以发射,楼主真是牛人,还有一些疑问要请教楼主:我家电视机遥控器是NEC协议 ...

参考:基于STC89C52的简易学习型红外遥控器
这个只是简易的单键固定码学习,看原理,自己修改完善吧

出0入0汤圆

发表于 2013-2-27 20:57:15 来自手机 | 显示全部楼层
红外解码不错的

出0入0汤圆

发表于 2013-3-6 18:11:13 | 显示全部楼层
学习了~!

出0入0汤圆

发表于 2013-4-11 16:56:10 | 显示全部楼层
楼主,菜鸟请问如何把你的程序改成按住一个键,让小灯亮,放开就熄灭的效果??

出0入0汤圆

发表于 2013-4-12 08:47:06 | 显示全部楼层
mark
            

出0入0汤圆

发表于 2013-4-12 09:05:24 | 显示全部楼层
mark一下~~~~

出0入0汤圆

发表于 2013-4-14 15:19:37 | 显示全部楼层
学习,学习,再学习!!!!

出0入0汤圆

发表于 2013-4-14 16:08:50 | 显示全部楼层
学习一下。

出0入0汤圆

发表于 2013-4-14 16:15:04 来自手机 | 显示全部楼层
收藏了谢谢

出0入0汤圆

发表于 2013-4-14 17:34:38 | 显示全部楼层
标记一下。。。

出0入0汤圆

发表于 2013-4-14 19:54:05 来自手机 | 显示全部楼层
不错的红外解码

出0入0汤圆

发表于 2013-5-2 23:25:04 | 显示全部楼层
留言备用!!

出0入0汤圆

发表于 2013-5-3 14:43:13 | 显示全部楼层
用STC  1T   发56KHz载波 怎么计算

出0入0汤圆

发表于 2013-5-3 14:59:53 | 显示全部楼层
    mark   

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-3-29 18:59

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

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