当前位置:首页 > 单片机学习笔记 > 正文

NEC格式红外遥控器解码原理附STC单片机程序

       一体化红外接收头型号为1838B,接在外部中断0上,单片机使用的是STC12C5A60,显示用的是5110液晶屏,不多说,先来看下NEC协议:

NEC协议格式

1.首先是一条引导码,引导码由9ms高电平载波和4.5ms低电平载波关断构成,然后就是数据了。


2.一帧数据32位码,两次8位用户码(地址),8位数据码和8位数据码反码。


3.数据1和0取决于脉冲之间的时间,数据0由0.56ms高电平和0.565ms低电平组成,共1.125ms,数据1由0.56ms高电平和1.69ms低电平组成共2.25ms。


4.遥控器发送的信号为高电平,一体化接收头收到的数据就是低电平,使用外部中断0下降沿触发。


5.当按住遥控器键不放时,会有连发重复码,这个我们先不管。

        关于用单片机如何解码,这里简单说一下原理,把接收头接在外部中断上,一旦按下遥控器,接收头就会接收到信号,遥控器发出的高电平,接收头收到的为低电平,我们把外部中断设置成下降沿触发,触发以后,用一个定时器记录每一次触发后的时间并保存起来,接收完一帧数据后,再判断记录中的时间长短就能知道是数据0还是1了,把0和1合并起来就是我们想要的数据了,具体请看代码中解释。

#include"stc12.h"
#include"5110LCD.h"
#include"font.h"
#include"Beep.h"
 
#define uchar  unsigned char
#define uint   unsigned int
 
//sbit LEDK = P1^4;
 
uchar IR_Time=0;
uchar IR_Flag=0;
uchar IR_Buffer[33];
uchar Decode_Buffer[4];
uchar BitNum=0;
bit Receive_OK=0;
bit IR_OK=0;
 
 
uchar Display_Buffer[4];
 
void INT0_Init(void); //外部中断0初始化
void T0_Init(void); //定时器T0初始化 12T传统8051模式
void IR_Decode_Process(void); //取出4位用户码和数据码
void Display_Decode(void);
 
 
void main(void)
{
   P0M1=0x00;//00000000 P0口全部配置成推挽输出 
   P0M0=0xff;//11111111 
   LEDK=0;
   P0=0x00;
   INT0_Init();
   T0_Init();
   Nokia_5110_Init();
   Clear_Screen();
  while(1)
  {
	 if(Receive_OK==1) //接收完毕
	 {
	   Receive_OK=0;
	   TR0=0;
	   IR_Flag=0;
	   IR_Time=0;
	   BitNum=0;  //清零
	   IR_Decode_Process();	//解码处理
	 }
	 if(IR_OK==1) //处理完毕
	 {
	   IR_OK=0;
 
	 }
	 Display_Decode(); //解出来的十六进制码显示在液晶上
  }
 
}
 
void INT0_Init(void) //外部中断0初始化
{
   IT0=1;//设置中断触发类型IT0=1为下降沿触发 
         //IT0=0为低电平触发,详情参考手册第196页TCON寄存器 
   EX0=1;//外部中断0允许位,EX0=1允许中断,
         //EX0=0禁止中断,详情参考手册第192页IE寄存器 
   EA=1;//CPU的总中断允许控制位,EA=0关闭所有中断 
        //EA=1打开所有中断,详情参考手册第197页IE寄存器    
}
 
void T0_Init(void) //定时器T0初始化 12T传统8051模式	
{
   TMOD=0x02;//TMOD.2置0用作定时器,M1:1 M0:0 8位自动重装 见手册186页
 
   TH0=0;//定时277.7秒 填充初始值见手册186页 
   TL0=0; //TMOD寄存器,定时器初始值计算方法见手册215页 256-x/(12/11.0592)=0
 
   TR0=0;//定时器0运行控制位,详情参考手册第156页TCON寄存器 
   ET0=1;//T0溢出中断允许位 ET0=1 允许T0中断
         //ET0=0禁止T0中断,详情参考手册第152页IE寄存器 
   EA=1;//CPU的总中断允许控制位,EA=0关闭所有中断 
        //EA=1打开所有中断,详情参考手册第157页IE寄存器    
}
 
void INT0() interrupt 0 //外部中断0入口 下降沿触发 
{						//遥控器发的高电平接收头收到的是低电平
  uchar i=0;
  TR0=1;//打开计时器
  if(IR_Flag==1)
  {
	  if(IR_Time>48) //引导码9ms
	  {
		BitNum=0;
	  }					//开始接收32比特数据,把接收到的每一比特的时
	    IR_Buffer[BitNum]=IR_Time; //间存到数组里面,用于后面判断0和1
		IR_Time=0;
		BitNum++;
		if(BitNum==33)
		{
		  BitNum=0;
		  Receive_OK=1;//接收完标志位
		}				                                    
  }
  else
  {
    IR_Flag=1;
	IR_Time=0; 
  } 
}
 
void T0() interrupt 1 //定时器0中断入口 每277.7ms进入一次
{
  IR_Time++;
}
 
void IR_Decode_Process(void)  //取出4位用户码和数据码
{
  uchar i=0,j=0,num=1,temp=0,Value=0;
  for(j=0;j<4;j++)
  {
	  for(i=0;i<8;i++) //合成数据 高位在前
	  {
	    temp=IR_Buffer[num];
		Value>>=1;
		if(temp>5) //大于1.125ms为数据1
		{
		  Value=Value|0x80;
	  	}
		num++;
	  }
	 Decode_Buffer[j]=Value;  //放入缓冲区
	 Value=0;
  }
  IR_OK=1;
 
}
void Display_Decode(void)
{
  Ascii_8X16_Font(0,0,Font_8X16[Decode_Buffer[0]/16]);
  Ascii_8X16_Font(8,0,Font_8X16[Decode_Buffer[0]%16]);
 
  Ascii_8X16_Font(22,0,Font_8X16[Decode_Buffer[1]/16]);
  Ascii_8X16_Font(30,0,Font_8X16[Decode_Buffer[1]%16]);
 
  Ascii_8X16_Font(44,0,Font_8X16[Decode_Buffer[2]/16]);
  Ascii_8X16_Font(52,0,Font_8X16[Decode_Buffer[2]%16]);
 
  Ascii_8X16_Font(66,0,Font_8X16[Decode_Buffer[3]/16]);
  Ascii_8X16_Font(74,0,Font_8X16[Decode_Buffer[3]%16]);
 
 //液晶会显示已经解码出来的键值,记录下来就能用了,比如OK键
 //的键值为:00 FF 40 BF,我们来试一下,按一下OK键蜂鸣器响一下。
 //00 FF为固定的用户码,40 BF为数据码(键值),两者互为反码
 
  if(Decode_Buffer[0]==~Decode_Buffer[1])//先对比下00和FF,看看是不是我们的遥控器
  {
     if(Decode_Buffer[2]==0x40)//OK键的键值为40
	 {
	     Beep();
		 Decode_Buffer[2]=0;  //Debug
	 }
  }
 
}
上一篇: 下一篇:

报歉!评论已关闭。