`

51单片机学习笔记:红外接收(对原子哥的ALIENTEK遥控器进行解码)

阅读更多

正点原子的ALIENTEK遥控器

用户码00ff

16进制键值码表
45    46    47
44    40    43
07    15    09
16    19    0d
0c    18    5e
08    1c     5a
42    ☻     4a

 

 

红外接收管  通用型即可

 


 ---------------------------------------------------------------------------

下面是类似的波形图,这个是网上找的,图片较大,缩小后看上去有些模糊,不过没关系,数据手册上一般都有



 

遥控器在发射红外信号之前,我们的mcu已经开启了定时器
在定时器中断函数中的全局变量irTimeCounts++ 一直在自加
irTimeCounts多长时间加一次? 或者说多长时间进入一次定时器中断函数呢?
在方式2时,t=256*12/11059200 约为277.78us
============================================================
1.对于1.125ms的时间,timer0会中断1.125/t=4.05次 也就是要5次,算上各种误差,(顶多5次,至少4次)
2.对于2.25ms 的时间,timer0会中断 2.25/t=8.1次, 也就是要9次,算上各种误差,(顶多9次,至少8次)
  对于这里的次数,比N次小一点,就是N次,比N次大一点,就是N+1次,因为不会有半次,
  误差给它正负0.4次足够了,给了误差后再算次数,直接舍入就行

那么我们就检测irTimeCounts的值,
如果小于6或7,那么接收到的数据为0
如果大于6或7,那么接收到的数据为1

从计算结果来看,我觉得0.56,1.125,2.25这些值的出现是比较合理的,
能有效避免由于器件误差和环境造成的数据误判,而且计算也方便

 

#include "my51.h"
#include "ir.h"
#include "smg.h"

void main()
{
	timer0Init();	  //定时器0初始化
	int0Init();		  //外部中断0初始化
	
	while(1)
	{
		if(irTimeCountsArrProcess()) //如果成功接收并解析完成一帧数据
		{							 //就让蜂鸣器响一下
			beep=0;					 //蜂鸣器开启
			led4=~led4;				 //4号灯反转一下
		}
										 
		displaySMG(irCodeByteDataProcessForSmg());//显示
		beep=1;			   			 			  //蜂鸣器关闭
		//由于displaySMG()函数执行时间较短,故蜂鸣器响声时间也较短,听到滴了一下
	}

}

 

#ifndef _51IR_H_
#define _51IR_H_
#include "my51.h"

extern u8 data smgWela[7];	  			 //数码管显示的数据

extern void int0Init();	   	  			 //外部中断0初始化
extern void timer0Init();	  			 //定时器0初始化
extern bool irTimeCountsArrProcess();    //成功解析一帧中断数据返回TRUE
extern u8* irCodeByteDataProcessForSmg();//将遥控器码值处理成数码管可显示数据

#endif

 

#include "ir.h"

u8 irTimeCounts=0;	  		  //定时器0在方式2下8位自动重装时的中断计数值
u8 irTimeCountsArr[32]={0};	  //存放红外接收数据时的中断次数记录值,
u8 bitNum=0;		  		  //标志当前接收的是第几个比特位
u8 irReceFlag=0;	  		  //红外接收一帧数据未完成标志,为1时完成
u8 irCodeByteData[4]={0}; 	  //保存接收到的4个字节的有效数据
u8 irTimeCountsArrProcessOk=0;//对接收到的33位数据处理未完成标志,1完成

void int0Init();	   			  //外部中断0初始化
void timer0Init();	   			  //定时器0初始化
bool irTimeCountsArrProcess();    //解析中断次数,即解码
u8* irCodeByteDataProcessForSmg();//将遥控器码值处理成数码管可显示数据

u8* irCodeByteDataProcessForSmg() //将解码的4字节数据处理成数码管可显示的数据
{	
	if(irTimeCountsArrProcessOk)  //检测一帧数据是否解析完成
	{
		//这里的用户码只显示低八位,因为高八位反正都是00(手上2个遥控器都是00)
		//然后还显示遥控键值及其反码,我们的数码管只有6位,只显示3字节数据
		if(irCodeByteData[2]+irCodeByteData[3]!=0xff)//校验数据的完整性
		{									 //最后一个字节是键码的反码
			led6=0;	  //调试代码
		}
		else
		{
			smgWela[0]=irCodeByteData[1] >> 4 ;	   //取高4位
			smgWela[1]=irCodeByteData[1] & 0x0f;   //取低4位
			smgWela[2]=irCodeByteData[2] >> 4 ;
			smgWela[3]=irCodeByteData[2] & 0x0f;
			smgWela[4]=irCodeByteData[3] >> 4 ;
			smgWela[5]=irCodeByteData[3] & 0x0f;
		    smgWela[6]=0xff;	//小数点全不显	
		}
		irTimeCountsArrProcessOk=0;//标志清零,下一次有未解析的数据时才会再解析
	}
	return 	 smgWela;
}

bool irTimeCountsArrProcess()	//对接收到的32位的中断次数数据进行解析
{
	u8 i,j,k,value=0;
	if(irReceFlag)			   //检测是否已经接收到新的4字节的红外通信数据
	{
		for(j=0;j<4;j++)   		 //有4个字节
		{
			for(i=0;i<8;i++)	 //对每个字节的8位数据处理
			{
				value>>=1;
				if(irTimeCountsArr[k++]>6)	 //这里我们用6或7都是可以的
				{
					 value|=0x80;			 //大于6的话该位数据是1
				}
			}
			irCodeByteData[j]=value;//保存该字节,也就是遥控器的键码	
		}
		irReceFlag=0;	//接收标志清零,这样就会等到下次收到数据后才会再解析
		irTimeCountsArrProcessOk=1; //中断数据解析完毕标志置1
		return TRUE;		  	    //解析完成
	}
	return FALSE;	//未进行解析,该返回值主要是为了方便外部文件调用时判断的	
}


void int0() interrupt 0//外部中断0
{	  
   if(irTimeCounts>30) //9ms的话中断32.4次,30这个取值差不多就可以了,不用太精确
   {	//这里9ms引导码需要timer0中断irTimeCounts=9*11059.2/(256*12)=32.4次
    	bitNum =0;
		irTimeCounts=0;//为接收第0位数据做准备
		return;		   //丢弃引导码,反正不是有效数据0或1的都丢弃,直接返回  		
   }				 

   irTimeCountsArr[bitNum]=irTimeCounts; //将中断次数数据存储起来
   irTimeCounts=0;     //存好了就立即清零,这样不会影响下一位数据的接收
   bitNum++;	       //继续下一位
   if(32==bitNum)      //32位数据已经接收完成(0~31已经存储)
   {
   		bitNum=0;  	   //清零,这里不清也可以,反正引导时也会清
		irReceFlag=1; //接收完成标志
   }				  
	
}

void timer0() interrupt 1  //定时器0中断函数
{
	 irTimeCounts++;	   //注:该值最大为255
}

void timer0Init()	//定时器0初始化
{	//配置工作方式寄存器,且不影响定时器1的状态
	TMOD &= 0xf0;   //保留定时器1的配置,并清除定时器0的配置
	TMOD |= 0X02;   //使用定时器0的工作方式2
	TH0=0X00;
	TL0=0X00; 		//工作方式2是8位自动重装
	ET0=1;	  		//打开定时器
	EA=1;	  		//打开总中断
	TR0=1;	  		//启动定时器0
}

void int0Init()	    //外部中断0初始化
{
	IT0=1; 			//配置外部中断0的触发方式为 跳变延触发
	EX0=1; 			//打开外部中断0
	EA=1;  			//打开总中断	
}

 

#ifndef _51SMG_H_
#define _51SMG_H_

#include "my51.h"

sbit dula =P2^6;  			//段选锁存器控制  控制笔段
sbit wela =P2^7;  			//位选锁存器控制  控制位置
extern u8 data smgWela[7];  //第一位到第六位,最后一个是小数点位置控制

#define dark	0x11//0x11是第17号元素,0x00是低电平,数码管不亮,即table[17]
#define dotDark 0xff		//小数点全暗

void displaySMG(u8* pWela); //数码管显示函数,参数是数组指针

#endif

 

#include "smg.h"
#include "my51.h"

static u8 code table[]= { 		//0~F外加小数点和空输出的数码管编码
	0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
	0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
	0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
	0x39 , 0x5e , 0x79 , 0x71 , // C D E F
	0x80 , 0x00 , 0x40          // . 暗 负号    暗即不显示是第17索引号
 };								//负号为第18索引号元素

/*  由于此表只能一次显示一个小数点,故已注释掉,仅供查询
	例如想要第一个和第六个数码管小数点同时点亮,
	则执行 pWela->dot = 0xfe & 0xdf  即可
	u8 code dotTable[]={   //小数点位置,某一位置0时,小数点亮
	0xff ,                 //那么全暗就是0xff
	0xfe , 0xfd , 0xfb ,   //1 2 3
	0xf7 , 0xef , 0xdf     //4 5 6                    
};*/

u8 data smgWela[7]={0,0,0,0,0,0,0}; //第一位到第六位,最后一个是小数点位置控制

//P0口的数码管位选控制锁存器只用了低6位,我们保留高2位的数据,留作它用
void displaySMG(u8* pWela)
{
	u8 i=0;	
    //控制6位数码管显示函数,不显示的位用参数dark
    u8 preState=P0|0x3f;  //保存高2位状态,其中最高位是ADC0804的片选信号
	wela=0;dula=0;_nop_();//先锁定数据,防止吴亮及位选锁存器高2位数据被改变
		
	P0=0;  		 	      //由于数码管是共阴极的,阳极送低电平,灯不亮
    dula=1;_nop_();
    dula=0;	  	 	      //段选数据清空并锁定

    P0=preState;  		  //共阴极数码管是阴极置高不亮,低6位置1,高2位保留	
    wela=1;_nop_();		  //注:wela和dula上电默认为1		 
    wela=0;		  		  //位选锁定,初始保留高2位的数据,低6位置高不亮

	for(i=0;i<6;i++)	  //显示6位数码管
	{
		P0=table[pWela[i]]|(((1<<i) & pWela[6])?0x00:0x80);
	    dula=1;_nop_();	     //送段数据,叠加小数点的显示,0x00点亮小数点
	    dula=0;
	    
	   	P0=preState&~(1<<i); //不影响高2位数据,低6位是数码管位选,低电平有效
	    wela=1;	_nop_();	 //送位选号
	    wela=0;	
	    delayms(1);			 //稍作延时,让灯管亮起来			
		{  //消除叠影及误亮,阴极置1不亮,低6位置1,高2位保留并锁定
	        P0=preState;
	        wela=1;	_nop_();			
	        wela=0;	
	    }
	}
}

 

  • 大小: 256.3 KB
  • 大小: 444.7 KB
  • 大小: 130.3 KB
1
1
分享到:
评论

相关推荐

    STC15红外遥控接收_红外遥控_stc单片机红外线遥控器解码程序_

    标题中的“STC15红外遥控接收”涉及的是基于STC15系列单片机的红外遥控系统设计。STC15系列是STC公司推出的一系列8位增强型单片机,以其低功耗、高性价比和丰富的内部资源而受到广泛应用。在红外遥控系统中,STC15...

    基于51单片机学习型红外线遥控器

    本项目“基于51单片机学习型红外线遥控器”提供了一种创新的设计方案,使用户能够自定义遥控器以适应多种家用电器的控制需求。 51单片机,即AT89C51,是美国Atmel公司生产的一款8位微处理器,基于Intel的8051内核。...

    红外遥控器解码

    本人开发的,稳定可靠的单片机红外遥控器解码程序 C51编写. 注释详细,移植方便,任何问题欢迎交流。

    基于51单片机的红外遥控器设计

    通过编程,STC89C52RC单片机可以实现对红外编码的接收、解码、学习和重发等功能,同时处理来自键盘的输入,并在LCD屏上显示相关信息。Altium Designer则用于电路板的设计,包括元器件布局和布线,确保电路的高效运行...

    51单片机教程(六):单片机外部中断及红外遥控器解码

    通过本教程的学习,读者可以了解到如何利用51单片机的外部中断功能来实现对红外遥控器信号的解码。在实际应用中,掌握单片机外部中断的编程处理以及红外遥控器编码解码的原理,能够让我们设计出功能更为强大、使用...

    基于51单片机的红外遥控转发器程序

    这个项目基于51单片机设计了一个红外遥控转发器,使得用户可以通过它来接收和转发红外遥控信号。 【红外遥控】是一种无线通信技术,常用于家电设备的远程控制,如电视、空调等。在这个系统中,51单片机扮演了接收和...

    51单片机红外发射接收_objecth1h_51单片机_红外发射_红外接收_

    这个信号会被51单片机的输入引脚检测,然后通过内部的ADC(模数转换器)或者直接数字比较进行解码。解码过程涉及到对信号的滤波、整形以及译码,以还原原始的数据信息。 项目中提到的“96 自制发射 接收 完整资料”...

    51单片机VS1838红外遥控解码程序NEC

    本文将详细解析与“51单片机VS1838红外遥控解码程序NEC”相关的知识点,包括红外遥控技术、红外编码与解码、STC12C5A60S2单片机以及VS1838红外接收模块。 首先,红外遥控是家电设备常用的一种无线通信方式,主要...

    51单片机红外遥控解码资料

    总的来说,51单片机红外遥控解码的学习需要理解红外遥控的基本原理,熟悉51单片机的硬件接口和软件编程,同时掌握特定解码器的使用方法。通过深入研究提供的资料,初学者可以逐步掌握这一技术,并应用于实际项目中。

    51单片机HAL库1.0.5 参考例程:红外接收

    总的来说,51单片机HAL库1.0.5的这个参考例程提供了一个全面的红外遥控解决方案,不仅涵盖了红外接收的核心技术,还包括了周边功能的实现,为开发人员提供了便利。通过学习和理解这些代码,开发者可以更好地掌握51...

    51单片机驱动LCD+红外接收C程序

    红外解码程序需识别特定的遥控器协议,如NEC、RC5或SIRC等,并将按键信息转换成可处理的数据。 5. **C语言编程**:51单片机的编程通常采用C语言,因为C语言既具有高级语言的抽象性和简洁性,又能直接访问硬件资源。...

    红外遥控解码数码管显示实验_单片机_

    在这个名为“红外遥控解码数码管显示实验”的项目中,我们将探讨如何使用51系列单片机,结合VC++编程环境,实现红外遥控信号的解码,并通过数码管显示遥控器的操作指令。 1. **红外遥控技术**:红外遥控是利用红外...

    基于51单片机红外遥控解码与波形显示(程序+原理图+元件清单+设计说明).zip

    在本项目中,51单片机被用来接收和解析红外遥控器发出的信号,同时通过某种显示设备(如LCD或LED)展示解码后的波形。 红外遥控系统的核心是编码和解码过程。遥控器发送的信号通常采用脉冲宽度调制(PWM)编码,...

    51单片机红外遥控器程序

    红外接收器接收到信号后,会通过解码电路将其转化为数字信号,然后由51单片机处理。解码过程通常涉及比较接收到的信号波形与预设的编码模板,匹配成功则执行相应的动作。 总的来说,这个项目涵盖了51单片机基础、...

    单片机解码红外遥控器

    ### 单片机解码红外遥控器 #### 一、编码格式 红外遥控器发射的信号是由一系列“0”和“1”的二进制代码组成的,这些代码通过红外线发送出去。不同的芯片对于“0”和“1”的编码方式可能有所不同,主要采用的是...

    51单片机红外接收代码加解码.rar_51红外解码_单片机_红外接收代码

    理解并实现51单片机的红外接收代码加解码涉及了硬件接口设计、信号处理、协议解析等多个方面,对于学习单片机控制和嵌入式系统的开发者来说,这是一个重要的实践环节。通过这个过程,不仅可以提升对51单片机的掌握,...

    51单片机解码红外遥控器原理

    通过本文的介绍,我们了解了红外遥控器的基本工作原理,以及如何使用51单片机对其进行解码。NEC和Philips标准虽然存在差异,但在设计程序时可以提取共性部分,提高编程效率。对于希望深入研究这一领域的读者来说,...

    基于单片机的红外遥控发射接收解码设计带原理图.rar

    使得红外发光二极管发射出一定频率的红外线,当接收控制系统接收到该红外光后,由单片机内定时/计数器得到该红外光的频率,然后将该频率送往CPU,由CPU对该信号进行反编码,识别出控制信号,控制LED灯亮,蜂鸣器发声...

    单片机红外遥控资料 解码 发射

    51单片机-红外遥控.pdf 常用红外遥控编码资料集+ircode.pdf 单片机处理红外遥控信号.pdf 单片机发送并接收红外遥控信号的方法.pdf 单片机红外发射(原理与设计程序).pdf 单片机学习实例--红外遥控实验学习.pdf 红外...

Global site tag (gtag.js) - Google Analytics