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
为数据码,b5
是4a
的反码。
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单片机获取红外解码从串口输出的主要内容,如果未能解决你的问题,请参考以下文章