OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7722|回复: 23

红外遥控解码,中断方式,51 C语言程序

[复制链接]

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
发表于 2016-6-1 00:52:03 | 显示全部楼层 |阅读模式

#include <reg52.h>       //管脚定义头文件
//#include <intrins.h>

#define uc unsigned char
#define ui  unsigned int

#define OSC 12000000  //晶振频率,按实际修改
#define MS  4 //一毫秒的次数
sbit  bat = P3^3 ;  //嗡鸣器引脚
sbit  power=P3^7;

#define ID 239  //遥控ID号.

code  unsigned char d[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e
};

bit pid_if,sleep_en,ir_if,int_if;
uc bb,t0,buf[6],wei;
uc shu[8];
uc tc;

void process_ir(void);
void process_beep(void);
void init(void);
void display(void);
void process_int(void);

//==================================================
void process_int(void)
{

static uc yw ;  
int_if=0;

if( tc< 6 ){yw>>=1;wei++;} //脉宽0
else
if(  tc<=12   ){yw>>=1;yw|=0x80;wei++;} //脉宽1
else wei=0;
if( (wei&7)==0 )buf[(wei>>3) ]=yw; //有8个BIT,记录到BUF内
if(wei==32)EX0=0;//收到32个位,也就是四个字节.数据够了.停止接收,关外部中断

}




//=============================================
void display(void)
{
static uc n=0;

P2=0XFF;
P0= d[shu[n]] ;
P2=~(1<<7-n);
n++;
n%=8;
}


//=============================================
void process_ir(void)
{static uc i;

ui id ;
id = (buf[1]<<8) + buf[2];

       
               
                                if( (buf[3]|buf[4])==0xff) //收到遥控信息,并且验证码正确
                                {
                                bb=1;
                               
                                        shu[0] =buf[4]&0x0f;
                                        shu[1] =buf[4]>>4;
                                        shu[2] =buf[3]&0x0f;
                                        shu[3] =buf[3]>>4;       
                                        shu[4] =buf[2]&0x0f;
                                        shu[5] =buf[2]>>4;
                                        shu[6] =buf[1]&0x0f;
                                        shu[7] =buf[1]>>4;
                                
        if (  id ==ID  || id ==255 )
{
                bb=2;//嗡鸣器叫一声
                                                switch(buf[3])
                                                {
                                                case 0:power=!power;
                                                break;
                                                case 10:power=1;
                                                break;
                                                case 2:power=1;
                                                break;
                                                case 3:power=0;
                                                break;
                                    case 12:power=0;
                                                break;
                                                }
                               
                               
}
                                }


for(i=0;i<6;i++)buf[i]=0xff;
wei=0;
EX0=1;
t0=0;
}




//===================================================
void process_beep(void)
{
static uc n=0;
pid_if=0;
if(bb>3)bb=0;
if(bb>0)
{
if(n==0)
{
bat=!bat;
if(bat)bb--;

}
n++;
if(n>11)n=0;

}
else n=0;

}



//==================================================
void init(void)
{

EX0 = 1;                    //使能INT0外部中断
IT0 = 1;                    //下降沿触发
TMOD=0x11 ;
RCAP2H=TH2=(65535-3*1000)/256 ;            //脉宽调节
RCAP2L=TL2=(65535-3*1000)%256 ;
EA=1;
ET0=1;
ET1=1;
ET2=1;

TR2=1;
TR1=1;
TR0=1;

power=1;
}




//=================================================
void  main(void)
{
  init();

while(1)
  {   
  if(int_if)process_int();
  if(EX0==0)process_ir();
                if(pid_if)
                {
                pid_if=0;
                process_beep();
                display();                         
                }                 
                       
                       
        if(power==1)
                {         
                        if(sleep_en)
                        {
                        sleep_en=0;
                        //睡眠前要处理的指令加在这里.关灯什么的
                  //          P0=0XFF;
                  //          PCON=2;
                        //_nop_();
                        //_nop_();
                  
                        }
               
               
                }                         
                        
                                                                                   ;
} //while(1);


}



void IR_IN()interrupt 0 using 0
{
TR0=0;
tc = TH0;
TH0=
TL0=0;                      //清定时器0
t0=0;                             //睡眠时间清0
int_if=1;
TR0=1;

}



/*********************************************************

定时器0中断服务程序   

*********************************************************/
void timer0() interrupt 1 using 1
{         
wei=0;       

}


/*********************************************************

定时器1中断服务程序  

*********************************************************/
void timer1() interrupt 3  using 3
{
t0++;
if(t0==500/65)sleep_en=1;   
//wei=0;            
}

void timer2() interrupt 5  using 3
{
TF2=0;
pid_if=1;            
}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
171
金钱
171
注册时间
2016-3-16
在线时间
48 小时
发表于 2016-6-1 10:49:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

2

主题

171

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3792
金钱
3792
注册时间
2016-6-26
在线时间
276 小时
发表于 2016-6-27 07:06:31 | 显示全部楼层
非常不错,谢谢分享。
回复 支持 反对

使用道具 举报

2

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
176
金钱
176
注册时间
2017-12-7
在线时间
20 小时
发表于 2017-12-26 10:17:14 | 显示全部楼层
我现在用15F104W,只有T0和T2,想用一个T0和一个外部中断完成红外解码,T2软件实现PWM输出,楼主觉得可行不?
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2017-12-26 10:22:36 | 显示全部楼层
rock614 发表于 2017-12-26 10:17
我现在用15F104W,只有T0和T2,想用一个T0和一个外部中断完成红外解码,T2软件实现PWM输出,楼主觉得可行不 ...

可以的。完全可以。
回复 支持 反对

使用道具 举报

2

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
176
金钱
176
注册时间
2017-12-7
在线时间
20 小时
发表于 2017-12-26 10:54:20 | 显示全部楼层
那麻烦楼主看看你之前帮我分析的那个程序,我就是用T0解码,T2软件实现PWM输出的,但是经过这几天的分析,只要一执行红外解码PWM输出就中断了,好像一解码程序就卡在红外功能函数里面不出来了,然后PWM就没有中断输出了
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2017-12-26 10:59:17 | 显示全部楼层
你直接移植我的程序试一下.你要解码的遥控器,是什么遥控器.是普通的4个字节的遥控器吗?还是空调遥控器.如果是空调遥控器.要修改的地方还有点多.
回复 支持 反对

使用道具 举报

2

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
176
金钱
176
注册时间
2017-12-7
在线时间
20 小时
发表于 2017-12-26 11:15:24 | 显示全部楼层
就是普通的遥控器,我先移植你的程序试试
回复 支持 反对

使用道具 举报

57

主题

316

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1344
金钱
1344
注册时间
2018-1-11
在线时间
156 小时
发表于 2018-1-20 10:15:12 | 显示全部楼层
操作系统 发表于 2017-12-26 10:59
你直接移植我的程序试一下.你要解码的遥控器,是什么遥控器.是普通的4个字节的遥控器吗?还是空调遥控器.如果 ...

你好,能实现,既有空调遥控器,又有电视机这种的学习型遥控器吗?
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 14:30:09 | 显示全部楼层
活到老,学到老 发表于 2018-1-20 10:15
你好,能实现,既有空调遥控器,又有电视机这种的学习型遥控器吗?

理论上当然是可以有的了.看你的技术功底了.
回复 支持 反对

使用道具 举报

57

主题

316

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1344
金钱
1344
注册时间
2018-1-11
在线时间
156 小时
发表于 2018-1-20 14:46:42 | 显示全部楼层
操作系统 发表于 2018-1-20 14:30
理论上当然是可以有的了.看你的技术功底了.

您这个是解码什么遥控器的啊?
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 15:52:09 | 显示全部楼层
本帖最后由 操作系统 于 2018-1-20 17:36 编辑

我的是适合普通电视机的遥控器.只有短按功能.没有长按功能.
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2017-11-14
在线时间
3 小时
发表于 2018-1-20 16:50:26 | 显示全部楼层
本帖最后由 神之终结 于 2018-1-20 16:57 编辑

你这ram用得也太猖狂了。。。
NEC6122格式的红外码,只用一个字节保存遥控码就行了,补码也直接比较,地址码不用保存的,直接比较,不对就舍弃这次接收。

而且你不判断按按键不动的引导头和重复码的么?
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2017-11-14
在线时间
3 小时
发表于 2018-1-20 16:58:49 | 显示全部楼层
活到老,学到老 发表于 2018-1-20 14:46
您这个是解码什么遥控器的啊?

NEC6121-6122格式的,你下个nec6121的pdf 里面有格式详解。
回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
904
金钱
904
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-20 17:27:41 | 显示全部楼层
神之终结 发表于 2018-1-20 16:50
你这ram用得也太猖狂了。。。
NEC6122格式的红外码,只用一个字节保存遥控码就行了,补码也直接比较,地址 ...

空调哪里来的重复按键,空调一个帧好几个字节的数据了,你说说哪里不对?
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 17:28:23 | 显示全部楼层
神之终结 发表于 2018-1-20 16:50
你这ram用得也太猖狂了。。。
NEC6122格式的红外码,只用一个字节保存遥控码就行了,补码也直接比较,地址 ...

阁下,火眼真金.
这个代码是没有长按的功能的.只有短按的功能.
这个代码主要是针对红外遥控中断解码+状态机的写法.做一个例程.
不是一个成功的商用代码.
功能不全.
这个代码解码的是普通电视机的遥控.
至于,用4个,还是3个,还是一个变量来 判断遥控器的码值,是不是对的.
方法不同,目的都是要比较4个接收到数据是不是我们要的.
你用变量的方式,常量的方式,都是可以的.
空间闲着也是闲着..想用就用用吧.
回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
904
金钱
904
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-20 17:35:27 | 显示全部楼层
活到老,学到老 发表于 2018-1-20 10:15
你好,能实现,既有空调遥控器,又有电视机这种的学习型遥控器吗?

这个自然是可以实现的,我已经做过了。

重难点在于:

1、能够根据时延准确判断出一次按键。
2、根据每个bit的时延准确判断这个bit表达了True还是False并记录这个时延值以便replay
3、发现特殊的时延值(例如格力空调遥控器YB0F2红外信号帧中间有一次大停顿)
YB0F2的红外信号实测如下图。请自行体会其余的难点。
TIM截图20180120173359.png


回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
904
金钱
904
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-20 17:36:15 | 显示全部楼层
操作系统 发表于 2018-1-20 17:28
阁下,火眼真金.
这个代码是没有长按的功能的.只有短按的功能.
这个代码主要是针对红外遥控中断解码+状 ...

你不说是空调的吗?
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 17:38:00 | 显示全部楼层
a496298685 发表于 2018-1-20 17:36
你不说是空调的吗?

空调的不是这个程序.空调要复杂一点.当时是我看错了帖子.回复错了.
空调的遥控,不同的厂家,格式不同,字节长度不同,引导码也不同.
比较乱.
回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
904
金钱
904
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-20 17:39:21 | 显示全部楼层
操作系统 发表于 2018-1-20 17:38
空调的不是这个程序.空调要复杂一点.当时是我看错了帖子.回复错了.
空调的遥控,不同的厂家,格式不同,字 ...

嘿嘿嘿嘿嘿,原来是这样。
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 17:42:18 | 显示全部楼层
a496298685 发表于 2018-1-20 17:27
空调哪里来的重复按键,空调一个帧好几个字节的数据了,你说说哪里不对?

空调的遥控,一般是没有表示长按重复的功能的.只有电视机这类的有.
空调长按功能是用其它的办法实现的.
回复 支持 反对

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6661
金钱
6661
注册时间
2016-5-29
在线时间
909 小时
 楼主| 发表于 2018-1-20 17:47:35 | 显示全部楼层
本帖最后由 操作系统 于 2018-1-20 17:49 编辑
活到老,学到老 发表于 2018-1-20 10:15
你好,能实现,既有空调遥控器,又有电视机这种的学习型遥控器吗?

如果只是要求实现任意遥控器的学习,并且要求学习的数量不是很多的话(数据多的话,操作复杂,理论上是可以实现的).可以实现.
方法,记录下电平高低各个时间值..保存到EEPROM就可以了.
由于89c51/52单片机RAM比较少.复杂的可能无法实现.要换RAM大一点的单片机.一定可以实现.并且不难.
回复 支持 反对

使用道具 举报

0

主题

13

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2018-8-21
在线时间
2 小时
发表于 2018-8-22 10:38:07 | 显示全部楼层
谢谢楼主分享.
回复 支持 反对

使用道具 举报

12

主题

68

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2012-11-14
在线时间
29 小时
发表于 2018-12-18 18:32:50 | 显示全部楼层
#在这里快速回复#谢谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 16:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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