红外遥控解码原理及代码实现

本篇介绍红外解码的原理和程序的写法。

     下面来看一下,红外线是如何编码的。
     ![这里写图片描述](https://img-blog.csdn.net/20150926130659823)

下面来具体说一下,解码的原理,每按一下遥控器的一个按键,遥控器就会发出32个“0”“1”代码(当然是通过高低电平的占空比来判断是0还是1的),具体是0,1是如何编码的上面图片中有介绍,和一个引导码,引导码的作用是告诉处理器,接下来将要开始发送代码,我们在编写程序时,当检测到引导码时,就应该准备接受数据了。32位代码中的前16位是用户识别码,不同的遥控器不相同,防止互相干扰的,后16是8为数据码,和8位数据反码。

     接下来开始介绍如何解码程序的编写。


      程序中用到了两个中断,一个是定时器中断,一个是外部中断。定时器中断用来准确计时,判断接受的代码是0还是1,外部中断用来准确确定定电平到来的时刻,然后开始计时。
/*********************************************************
函数功能:红外解码,用八位数码管显示红外线的按键码,便于红外控制
测试环境:hot 51学习板
编译环境:keil4
整理人:张家越  QQ:435835181
整理时间:2011-04-03
************************************************************/


#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code seg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,   
      0x77,0x7c,0x39,0x5E,0x79,0x71  };           //0-f的段选码
unsigned char code seg_we[]={0,1,2,3,4,5,6,7};
uchar irtime,startflag,bitnum,irreceok;
uchar irdata[33];
uchar irprosok;
uchar display[8];
uchar ircode[8] ;
sbit led1=P0^1;
sbit led2=P0^2;
/************************************************************************
函数功能:延时函数,在数码管显示时使用,不需要很精确
*************************************************************************/ 
void delay_50us(uint t)
{
 uchar j;
 for(;t>0;t--)
  for(j=19;j>0;j--);
}
/**************************************************************************
函数的功能:定时器0的初始化
**************************************************************************/ 
void timer0init()
{
 TMOD=0x02;   //设置定时器工作在方式2
 TH0=0x00;   // 
 TL0=0x00;   //设置定时器的初值 
 ET0=1;    //开定时器中断 
 TR0=1;    // 打开定时器 
 EA=1;    //开总中断 
}
/************************************************************************
外部中断1的初始化
***********************************************************************/ 
void int1init()
{ 
 IT1=1;      //设置触发方式为上升沿 
 EX1=1;      //开外部中断1 
 EA=1;       //开总中断 
}
/**********************************************************************
定时器0的功能函数,每中断一次irtime++,用于计时
***********************************************************************/ 


void timer0() interrupt 1
{
 irtime++;      //定时器中断一次irtime++,用于计时 
} 
/***********************************************************************
外部中断0的处理函数,每当有低电平数据过来时,中断一次,(使用次中
断的前提是,信号线必需接在外部中断0上面,也就是P3^2口),函数功能
是,把信号从高低电平变成时间的代码放入irdata【】中 
************************************************************************/ 
void int1() interrupt 2     
{
 if(startflag)
 {
  if(irtime>32)   //一组代码检测完毕
  {       
   bitnum=0;
  }
   irdata[bitnum]=irtime;   //把检测到的时间送到数组irdata【】中去 
   irtime=0;       
   bitnum++;
   if(bitnum==33)     //如果检测到bitnum=33,说明32位用户码已经检测完毕 
   {
    bitnum=0;     //将bitnum清零以便重新计数 
   irreceok=1;     //接收完毕标志位置一 
   }


 }
 else        //(此函数先进入else语句,跳过引导码的检测) 
 {
  startflag=1;     //将开始标志位置一 
  irtime=0;      //设置时间初值为零 
  irreceok=1;      //接收完毕标志位置一 
 } 
}


/*************************************************************************
函数功能:把irdata【】中的时间代码转换成二进制代码存放在ircode【】中 
**************************************************************************/ 


void irpros()
{
 uchar k=1,value,j,i;
 for(j=0;j<4;j++)
 {
  for(i=0;i<8;i++)
  {
   value=value>>1;       //右移7次(第一次是00,相当于没有移位)

   if(irdata[k]>6)     //循环8次
   {
    value=value|0x80;
    }
    k++;

  }  
  ircode[j]=value;
 } 
 irprosok=1; 
}
/****************************************************************************
 函数的功能是:将ircode【】中的二进制代码转换成为16进制代码便于在数码管上显示
 ***************************************************************************/ 
void irwork()
{
 display[0]=ircode[0]/16;
 display[1]=ircode[0]%16;
 display[2]=ircode[1]/16;
 display[3]=ircode[1]%16;   


 display[4]=ircode[2]/16;
 display[5]=ircode[2]%16;
 display[6]=ircode[3]/16;
 display[7]=ircode[3]%16;
}
/************************************************************************
函数功能:用数码管显示解码结果
************************************************************************/ 
void display1()
{
 uchar i;
 for(i=0;i<8;i++)
 {
  P2=seg_we[i];
  P0=seg_du[display[i]];
  delay_50us(40);
 }
}


void main()
{
 timer0init();           //定时器初始化
 int1init();                   //外部中断初始化
 while(1)
 {
  if(irreceok)                 //判断数据接收完毕(数组中存储的是高低电平的时间)
  {
   irpros();                 //执行处理函数,将高低电平时间转化成16进制的01代码,存放在数组中
   irreceok=0;           //标志清零
  }
  if(irprosok)             //处理函数执行完毕,
  {
   irwork();                   //将存储的16进制代码分离,便于数码管显示
   irprosok=0;          //标志清零
  }
  display1();

 }
}

//在最后我再分析一下程序的编写思路,便于大家理解,一旦有按键按下,接受管接收到引导码,进入外部中断,并将高低电平的时间放入irdata【】数组中,接受完毕标志位置一,判断接受标志位,为1,进行处理函数,将高低电平转换成16进制数,处理标志位置一,判断处理标志位,为1,执行分离函数,将16进制数分离,便于数码管显示,分离完毕后显示。

编程技巧:善用标志位,是程序的层次感很强,便于阅读,修改和调试。

改程序已通过调试!

(由于本人水平有限,文中难免有错误或不妥之处,敬请读者批评指正!转载请注明出处!)

                                              联系方式:435835181@qq.com
  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值