STC单片机获取红外解码从串口输出

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC单片机获取红外解码从串口输出相关的知识,希望对你有一定的参考价值。

STC单片机获取红外解码从串口输出


  • 串口数据演示

  • 所使用的红外接收头VS1838

  • VS1838引脚定义

  • 电气特性

  • 所使用的红外按键板

红外遥控接收模块 VS/HX1838 相关的资料:

https://pan.baidu.com/s/1V62yRfGT-c9bfgIlq12ZCQ 
提取码:8888

说明NEC协议的高低电平说明

这种VS1838模块所使用的通讯协议是NEC协议。

  • NEC协议使用比特的脉冲距离编码。每个脉冲是一个560us长的38kHz载波脉冲(大约21个周期)。一个逻辑“1”需要2.25毫秒来传输,而一个逻辑“0”只需要一半的时间,即1.125毫秒。建议载波占空比为1/4或1/3。

引导码:9ms 的载波+4.5ms 的空闲。
比特值“0”:560us 的载波+560us 的空闲。
比特值“1”:560us 的载波+1.68ms 的空闲。

用户码和数据码中的‘0’和‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式(PPM)。

NEC 协议的数据格式包括了引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。停止位主要起隔离作用,一般不进行判断。

  • 数据分析举例

上面的第一段接收码中的 00-ff段为用户码和用户反码,4a为数据码,b54a的反码。

4a用二进制:01001010
b5的二进制:10110101
通过数据码和数据反码构成对接收到的数据的有效验性进行校验。

  • 一个NEC数据帧占用的时间长度包括:(引导码,9ms的高电平和4.5ms的低电平,然后是32位数据[其中包括:两字节用户码,第三字节是数据码,第四字节是数据反码]和1位停止位):即引导码:(9+4.5)ms + 32位数据[全是高电平时,(32x2.25)ms; 全是低电平时,(32x1.12)ms] + 1位停止位(0.5625ms),所以一帧数据所占用的时间范围是:
    9+4.5+35.84+0.5625 = 49.9025ms < frame_data_time(NEC) < 9+4.5+72+0.5625 = 86.0625ms

  • 采用逻辑分析仪采集到的VS1838按键信号数据

编程注意事项

1.红外接收头引脚信号是相反的电平。

以上电平是从发射头角度来看,红外接收头引脚输出的是相反的电平。当接收头没有收到信号时,输出引脚是高电平状态。

示例代码


/**********************************************
利用红外接收头(VS1838)获取遥控按键码
******************************************************************/
#include<reg52.h>    //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>//用于printf打印,需要加载此头文件
#include <stdarg.h> 

sbit IR=P3^2;  //红外接口,需要接到带外部中断引脚上

/*------------------------------------------------
                全局变量声明
------------------------------------------------*/

unsigned char  irtime;//红外用全局变量

bit irpro_ok,irok;
unsigned char IRcord[4];
unsigned char irdata[33];

/*------------------------------------------------
                  函数声明
------------------------------------------------*/

void Ir_work(void);
void Ircordpro(void);

/*------------------------------------------------
                 串口初始化函数
------------------------------------------------*/
void init_com(void)

	TMOD|=0x20;		   //设T1为方式1,GATE=1;
	SCON=0x50;
	TH1=0xFD;
	TL1=0xFD;
	TR1=1;			   //开启定时器1
	TI=1;
	EA=1;			   //开启总中断



/*------------------------------------------------
                  定时器0中断处理
------------------------------------------------*/

void tim0_isr (void) interrupt 1 using 1

  irtime++;  //用于计数2个下降沿之间的时间


/*------------------------------------------------
                  外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中断0服务函数

  	static volatile unsigned char  i =0 ;             //接收红外信号处理
	static  volatile bit startflag = 1;                //是否开始处理标志位
	TR0 = 1;//打开定时器0,开始计算高电平的时间(引导码)
	if(startflag)                         
	
		if(irtime<63 && irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
			i=0;
		irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
		irtime=0;
		i++;
		if(i==33)
		
			irok=1;
			i=0;
		
	
	else
	
		irtime=0;
		startflag=1;
	



/*------------------------------------------------
                定时器0初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化


  TMOD|=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
  TH0=0x00; //重载值
  TL0=0x00; //初始化值
  ET0=1;    //开中断
  TR0=0;    //不开启定时器0

/*------------------------------------------------
                  外部中断0初始化
------------------------------------------------*/
void EX0init(void)

 IT0 = 1;   //指定外部中断0下降沿触发,INT0 (P3.2)
 EX0 = 1;   //使能外部中断
 EA = 1;    //开总中断

/*------------------------------------------------
                  键值处理
------------------------------------------------*/

void Ir_work(void)//红外键值散转程序

	//发送红外码
	//这里转义后的码由上位机解码显示,也可以自己上传显示,默认X,也就是只要是X则上位机自动解码,其他值上位机则显示上传的值
	//02bx输出以16进制的格式输出整数类型的数值域宽为2,右对齐,不足的用字符0替代
	printf("RECE_IR DATA:%02bx-%02bx-%02bx-%02bx \\n", IRcord[0], IRcord[1], IRcord[2], IRcord[3]);  
	irpro_ok=0;//清空完成标志
	

/*------------------------------------------------
                红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
 
	unsigned char i, j, k;
	unsigned char cord,value;
	
	k=1;
	IRcord[0] = 0; 
	IRcord[1] = 0;
	IRcord[2] = 0;
	IRcord[3] = 0;
	for(i=0;i<4;i++)      //处理4个字节
	
		for(j=1;j<=8;j++) //处理1个字节8位
		
			cord=irdata[k];
			if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
				value|=0x80;
			if(j<8)
			
				value>>=1;
			
			k++;
		
		IRcord[i]=value;
		value=0;     
	 
	irpro_ok=1;//处理完毕标志位置1

/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main(void)

	init_com();
	EX0init(); //初始化外部中断
	TIM0init();//初始化定时器
	while(1)//主循环
	
		if(irok)                        //如果接收好了进行红外处理
		   
			EA = 0;
			Ircordpro();
			EA = 1;
			irok=0;
		
		
		if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
		
			EA = 0;    //关总中断
			Ir_work();
			EA = 1;    //开启总中断,等待下一次接收

		
	

  
  

程序源码说明

红外接收涉及到通讯协议,通讯时的延时时间和单片机运行速率有关,在其他型号单片机或不同晶振频率时,单片机的运行速度都会影响红外接收,如果想将程序移植到其他单片机型号上,注意代码中的相关参数。保证处理数据中的延时需要十分准确才行,不然会收不到数据或采集到的数据是乱码。

  • 本代码验证了STC12C5A60S2 采用的晶振是11.0592MHz 和STC15W408AS 采用的是内部晶振频率11.0592MHz
  • 在STC15W408AS上使用时,需要使用定时器2作为波特率发生器,因为该型号没有定时器1。
/*------------------------------------------------
                 串口初始化函数
------------------------------------------------*/
void init_com(void)

		SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xE8;		//设置定时初始值
	T2H = 0xFF;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时
	TI=1;			// 很关键,使用printf函数时必须有此命令
	EA=1;			   //开启总中断

链接:https://pan.baidu.com/s/1UxuJnxvaj-9R4ts2NHZ99Q 
提取码:eztv

以上是关于STC单片机获取红外解码从串口输出的主要内容,如果未能解决你的问题,请参考以下文章

基于STC12系列单片机的通用红外遥控信号分析程序

STC12C5A60S2 12M 红外发射

STC单片机3路PWM波形输出并串口打印当前脉冲值

STC学习:串口通信

IRM3800 红外遥控器解码 linux驱动

普中51_红外线通信应用(未完)