红外遥控器的解码

2020-01-22 12:01发布

红外遥控器的解码
实测距离10米时不会错误或需要重复按遥控器 (*^__^*) ……


接收头 (原文件名:接收头.jpg.jpg)


正确解码 (原文件名:20110103426.jpg)
第一行显示的是:地址码+地址码+操作码+操作码反码  接受数据正确时第二行显示OK  旁边的数字是连_发次数


错误解码 (原文件名:20110103427.jpg)
第一行显示的是:地址码+地址码+操作码+操作码反码  接受数据错误时第二行显示error  旁边的数字是连_发次数


51开发板配的万能遥控器 (原文件名:20110103428.jpg)
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
97条回答
zxc2769
1楼-- · 2020-01-26 15:09
MARK
hmzwm
2楼-- · 2020-01-26 15:41
 精彩回答 2  元偷偷看……
hmzwm
3楼-- · 2020-01-26 15:41
另外,外部中断服务程序里的

if(timeout)    //如果超时
{
TL0=TIMER0_COUNT;  //初始化定时器0

初始化定时器0这一句可以去掉,因为TMOD=0x02。
qq335702318
4楼-- · 2020-01-26 18:10
回复【39楼】hmzwm
-----------------------------------------------------------------------

谢谢 你的意思是自动重载方式无需初始化定时器0?
hmzwm
5楼-- · 2020-01-26 20:56
回复【40楼】qq335702318 | 昌少
-----------------------------------------------------------------------

不是啊...

贴上我参考您的程序,改写的一个版本。


/*        
        CPU-XTL :89S52-12MHz
        红外编码方案: NEC upd6121,upd6122;PT2222; SC6121; HS6221,HS6222
        编码格式:引导信号(或连_发信号)+地址码1+地址码2+数据码+数据码反码
        引导码:9ms低电平+4.5ms 高电平
        连_发码:9ms低电平+2.25ms高电平
        数据0:0.56ms低电平+0.56ms高电平
        数据1:0.56ms低电平+1.69ms高电平                  
        2011.1.24        OK
*/
#include<LCD1602.h>                  //包含延时函数Delay.h

/* 宏定义*/
/* 由于遥控器和程序存在一定误差,须允许编码时长有一定的范围便于调试*/
/******************************************************************/
//#define IR_ADDR1 0x00                                //本机地址1
//#define IR_ADDR2 0xFF                                //本机地址2
#define GTime 39                                    //引导码最短时长          39*225us=8775us=8.775ms[9ms]
#define CTime 100                                 //连_发码最短时长        39-> 100
#define D0MinTime 3                                        //数据0 最短时长        平均5*225us=1125us=1.125ms
#define D0MaxTime 7                                        //数据0 最长时长        0.56ms+0.56ms=1.120ms
#define D1MinTime 8                                        //数据1 最短时长        平均10*225us=2250us=2.25ms
#define D1MaxTime 12                                //数据1 最长时长        0.56ms+1.69ms=2.25ms
#define TIMER0_COUNT 0x1f                //定时器定时时间        12MHz-225us           0x1f=31
#define TimeOut_cnt 250                            //超时时长                        250*225us=56250us=56.25ms

/*全局公共变量*/
static unsigned char T0_CNT;                //定时器计数值
static unsigned char T0_CNT_bk;                //计数备份
static bit TimeOut;                                        //超时标志
static bit Guide;                                        //引导码有效
static bit Continuous;                                //连_发码
static unsigned char IR_Time[33];        //保存每两个下降沿之间的时间间隔  

/*结构体*/                   /* 保存一次解码后接收到的四字节数据*/
static struct IR_data                                //红外接收的数据结构
{         unsigned char addr1;                        //地址1(客户码1)
        unsigned char addr2;                        //地址2(客户码2)
        unsigned char data1;                        //数据1(数据码)
        unsigned char data2;                        //数据2(数据码反码)
}IR_DATA;         
//unsigned char IR_KeyValue;                         //红外遥控器键值
/*LCD显示用ASCII字符表*/
unsigned char code ASCII_Tab[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/* 看门狗2011.1.21*/
sfr WatchDogTimer = 0xC1;
sbit BEEP=P1^0;      /* BEEP */
static unsigned char nKey;                //正确解码的次数,用于键值处理2011.1.25
/******************************************************************/
/* 函数声明*/
void Timer0_Init(void);                        //定时器0初始化
void EX1_Init(void);                           //外部中断1初始化
void Decode(void);                            //解码子程序

void get_IRkey(void);                          //键处理
void display_keyValue(void);          //显示从遥控器接收到的数据
void display_Continuous(void);        //显示连_发次数
void SysInit(void);                //系统初始化
/******************************************************************/
/*函数定义*/
/*定时器0初始化: 定时值:225us 12MHz(11.0592MHz) ;方式2 自动重载 重载值31(0X1F)*/
void Timer0_Init(void)//定时器0初始化
{         TMOD=0x02;//定时器0工作方式2 自动重载
        TH0=TIMER0_COUNT; //重载值
        TL0=TIMER0_COUNT; //初始化值
        ET0=1;    //定时器0中断有效
        TR0=1;    //定时开始
}
/******************************************************************/
/*Timer0中断子程序*/
void Timer0_Int(void) interrupt 1 using 1
{        T0_CNT++;
        if(T0_CNT>TimeOut_cnt)        TimeOut=1;           //超时标志                                                 
}
/******************************************************************/
/*外部中断1初始化:外部中断1 P3.3,触发方式:下降沿*/
void EX1_Init(void)
{        EA = 1;    //总中断开
        IT1 = 1;   //指定外部中断1下降沿触发,INT1 (P3.3)
        EX1 = 1;   //开外部中断1
}
/******************************************************************/
/* 外部中断1函数,下降沿触发*/
void EX1_Int(void) interrupt 2 using 0
{        static unsigned char m=0;
       
        T0_CNT_bk=T0_CNT;                //备份时间计数值,即前一个下降沿到本下降沿的时间间隔
        T0_CNT=0x00;                          //清空时间计数值
         
        if(TimeOut)                                   //如果超时
        {//        TL0=TIMER0_COUNT;          //初始化定时器0           -0x1f(31)
                TimeOut=0;                   //清除超时标志
                m=0;                           //复位数据位
                T0_CNT=0x00;                   //清空时间计数值
                Guide=0;           //清除引导标志
                Continuous=0;      //清除连_发标志
        }
        else                                  //正常按键时长58.5ms~76.5ms
        {        if(Guide|Continuous)                           //如果引导码有效
                {        IR_Time[m++]=T0_CNT_bk;                 //保存时间间隔
                        if(m==32)                                         //接收够32数据后
                        {        m=0;
                                Guide=0;                                         //清除引导标志
                                /*进行解码操作*/
                                Decode();                                         //解码
                                nKey++;          //正确解码的次数,用于键值处理2011.1.25
                        }
                }                                                                
                                                                           
                if(T0_CNT_bk>GTime)         //如果时间间隔>引导码时长
                {        Guide=1;        m=0;        };//使能引导标志
                if(T0_CNT_bk>CTime)         //如果时间间隔>连_发码时长
                {        Continuous=1;                                                 //使能连_发标志
                        EX1=0;                   //关外部中断1
                        /**此处加入连_发操作代码**/
                        display_Continuous();

                        EX1=1;                //开外部中断1
                        m=0;  
                }
        }//end of 超时
}  

/******************************************************************/
/*解码核心程序*/
void Decode(void)
{        unsigned char i=0x00,j,k;
        static unsigned char *p;  //指向结构体IR_DATA.XX的指针
       
        EX1 = 0;   //关外部中断1
        /*/////////////////////////进行解码处理////////////////////////*/
        p=&IR_DATA.addr1;
        for(k=0;k<4;k++)
        {        for(j=0;j<8;j++)
                  {        if((IR_Time>D0MinTime)&(IR_Time<D0MaxTime))
                           {        *p>>=1;        *p&=0x7f;}//右移1位,        //与0111 1111置0. 数据“0” 0.56ms低电平+0.56ms高电平                  
                          else if((IR_Time>D1MinTime)&(IR_Time<D1MaxTime))
                           {        *p>>=1;        *p|=0x80;}//右移1位,//或1000 0000置1. 数据“1” 0.56ms低电平+1.69ms高电平   
                          i++;
                  }
                  p++;
        }
        if(IR_DATA.data2==~IR_DATA.data1){        get_IRkey();        }   /*提取按键值*///数据2=数据1反码
        else {         WriteStrTo1602(2,1,"Error!");        };        /**非本机遥控器或数据错误**/
        /*/////////////////////////解码处理完毕////////////////////////*/
        EX1 = 1;   //重新开放外部中断1
}
/******************************************************************/
/*中断程序调用——红外遥控键处理函数。键值功能为用户自定义*/
void get_IRkey()
{        display_keyValue();          //显示从遥控收到的数据
}   
/*                不同的遥控器各键值代码有不同的定义 eg.:
//0~9数字键
0-0x0D                1-0x0C                2-0x18                3-0x5E                4-0x08
5-0x1C                6- 0x5A                7-0x42                8-0x52                9-0x4A
//功能键
|<<         0x07        >|| 0x09        >>| 0x15        VOL- 0x16
VOL+ 0x19        CH+ 0x40        EQ  0x43        CH- 0x44
ON/FF 0x45        RETURN 0x46        MODE 0x47
*/
/******************************************************************/
/*按键处理函数,输入:接收到的数据码——结构体IR_DATA*/
void display_keyValue(void)
{        WriteCharTo1602(1,1,ASCII_Tab[IR_DATA.addr1/0x10]);       
        WriteCharTo1602(1,2,ASCII_Tab[IR_DATA.addr1%0x10]);
        WriteCharTo1602(1,4,ASCII_Tab[IR_DATA.addr2/0x10]);
        WriteCharTo1602(1,5,ASCII_Tab[IR_DATA.addr2%0x10]);
        WriteCharTo1602(1,7,':');
        WriteCharTo1602(1,9,ASCII_Tab[IR_DATA.data1/0x10]);
        WriteCharTo1602(1,10,ASCII_Tab[IR_DATA.data1%0x10]);
        WriteCharTo1602(1,12,ASCII_Tab[IR_DATA.data2/0x10]);
        WriteCharTo1602(1,13,ASCII_Tab[IR_DATA.data2%0x10]);
        WriteStrTo1602(1,15,"OK");

        WriteStrTo1602(2,1,"U=");
        WriteCharTo1602(2,3,ASCII_Tab[IR_DATA.addr1/0x10]);       
        WriteCharTo1602(2,4,ASCII_Tab[IR_DATA.addr1%0x10]);
        WriteCharTo1602(2,6,ASCII_Tab[IR_DATA.addr2/0x10]);
        WriteCharTo1602(2,7,ASCII_Tab[IR_DATA.addr2%0x10]);

        WriteStrTo1602(2,13,"K=");
        WriteCharTo1602(2,15,ASCII_Tab[IR_DATA.data1/0x10]);
        WriteCharTo1602(2,16,ASCII_Tab[IR_DATA.data1%0x10]);

        BEEP=0;
        DelayNms(5);
        BEEP=1;
}
/******************************************************************/
/*显示连_发函数*/
void display_Continuous(void)
{        static unsigned char n;
       
        WriteCharTo1602(2,10,ASCII_Tab[n/0x10]);
        WriteCharTo1602(2,11,ASCII_Tab[n%0x10]);
        n++;

        BEEP=0;
        DelayNms(50);
        BEEP=1;
}
/***************************************
* 名称 : SysInit()
* 功能 : 单片机初始化,设置定时器,中断,看门狗等初值
* 输入 : 无
* 输出 : 无
****************************************/
void SysInit(void)
{        /****************看门狗初始化************************/
        WatchDogTimer = 0x3C;                  /*晶振在12M或11.0592M时,溢出时间为1s左右2011.1.21*/
        /* 0011,1100 EN_WDT = 1,CLR_WDT = 1,IDLE_WDT = 1,PS2=1,PS1=0,PS0=0 */
        /****************LCD1602显示器初始化*****************/
    Initiate1602();
          WriteStrTo1602(1,1,"IR Decode System");/*LOGO*/
          WriteStrTo1602(2,1,"(c)");
          WriteStrTo1602(2,8,"2011-1-24");
        DelayNms(1500);
        WriteCmdTo1602(0x01);/* 清屏 */       
        /****************外部中断1初始化**********************/
        EX1_Init();
        /****************定时器0初始化************************/
        Timer0_Init();
        /****************波特率初始化************************/
  
        /****************其他硬件相关初始化******************/

}
/***************************************
* 名称 : main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
****************************************/
//主函数
void main(void)
{        SysInit();

        while(1)
        {        /*看门狗——喂狗2011.1.21*/
                WriteCharTo1602(2,10,nKey+'0');
                DelayNms(1000);
                WatchDogTimer = 0x3C; //喂狗
        }
}
hmzwm
6楼-- · 2020-01-27 01:49
在下面的外部中断1服务子程序中那个“如果超时”下面的那句话,我去掉后调试通过,程序运行正常。

******************************************************************/
/* 外部中断1函数,下降沿触发*/
void EX1_Int(void) interrupt 2 using 0
{ static unsigned char m=0;

T0_CNT_bk=T0_CNT; //备份时间计数值,即前一个下降沿到本下降沿的时间间隔
T0_CNT=0x00;    //清空时间计数值
  
if(TimeOut)     //如果超时
{// TL0=TIMER0_COUNT;   //初始化定时器0    -0x1f(31)
TimeOut=0;    //清除超时标志
m=0;    //复位数据位
T0_CNT=0x00;    //清空时间计数值
Guide=0;           //清除引导标志
Continuous=0;      //清除连_发标志
}
...

一周热门 更多>