【蓝桥杯单片机组模块】13、NEC 红外通信 - vs1838B

微信搜索ReCclay,也可免费阅读博主蓝桥系列所有文章,后台回复“代码”即可获取蓝桥所有备赛代码!关注博主公众号,还可拥有加入博主粉丝群实时沟通技术难题、免费下载CSDN资源等多项福利,还在等什么呢?快快扫码关注,学习才不会迷路

在这里插入图片描述

这里再向各位同学推荐一个CSDN博主 ReRrain 的蓝桥备赛博客,博主秉持初学者思路,向你讲述自己蓝桥备赛的心路历程,娓娓道来蓝桥备赛经验,个人觉得非常不错,值得细细品读。


导读:《蓝桥杯单片机组》专栏文章是博主2018年参加蓝桥杯的单片机组比赛所做的学习笔记,在当年的比赛中,博主是获得了省赛一等奖,国赛二等奖的成绩。成绩虽谈不上最好,但至少问心无愧。如今2021年回头再看该系列文章,仍然感触颇多。为了能更好地帮助到单片机初学者,今年特地抽出时间对当年的文章逻辑和结构进行重构,以达到初学者快速上手的目的。需要指出的是,由于本人水平有限,如有错误还请读者指出,非常感谢。那么,接下来让我们一起开始愉快的学习吧。

不积跬步无以至千里,不积小流无以成江海。


一、基础理论

HS0038红外接收头,内部集成了监测,放大,滤波,解调等一系列电路处理输出基带信号。
其实HS0038 和vs1838B 没什么区别,只是相比0038的性能更好!

这里写图片描述

原始信号就是我们要发送的一个数据“0”位或者一位数据“1”位,而所谓 38K 载波就是频率为 38K 的方波信号,调制后信号就是最终我们发射出去的波形。我们使用原始信号来控制 38K 载波,当信号是数据“0”的时候,38K 载波毫无保留的全部发送出去,当信号是数据“1”的时候,不发送任何载波信号。

要想让 HS0038B 识别到 38K的红外信号,那么这个 38K 的载波必须要大于 10 个周期,这就限定了红外通信的基带信号的比特率必须不能高于 3800,那如果把串口输出的信号直接用 38K 调制的话,波特率也就不能高于 3800。

但是更常用的红外通信协议——NEC 协议。

NEC 协议的数据格式包括了引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。

这里写图片描述

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

这里写图片描述

HS0038B 这个红外一体化接收头,当收到有载波的信号的时候,会输出一个低电平,空闲的时候会输出高电平。

这里写图片描述

程序的逻辑不难,难是难在了编码!

多练!
多练!
多练!

二、动手实战

以一个简单的demo为例实战红外通信模块:实时显示键码到数码管!

main.c

/*
*******************************************************************************
* 文件名:main.c
* 描  述:
* 作  者:CLAY
* 版本号:v1.0.0
* 日  期: 
* 备  注:红外接收,while(1)里面红外扫描接收,T1计时高低电平时间!
*         接收完毕后,在while(1)进行数码管显示。
*******************************************************************************
*/

#include "config.h"
#include "infrared.h"

u8 code LedChar[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
u8 LedBuff[] = {
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

u8 T0RH = 0, T0RL = 0;

void ConfigTimer0(u16 ms);
void CloseFucker();

void main()
{	
	EA = 1;
	CloseFucker();
	ConfigTimer0(1);
	InitInfrared();

	while(1)
	{
		if(!IR_INPUT)
		{
			IRScan();
		}
		if(irflag)
		{
		 	irflag = 0;
			LedBuff[5] = LedChar[ircode[0] >> 4];//用户码
			LedBuff[4] = LedChar[ircode[0]&0x0F];
			LedBuff[1] = LedChar[ircode[2] >> 4];//键码
			LedBuff[0] = LedChar[ircode[2]&0x0F];
		}
	}
}

void CloseFucker()
{
 	P2 = (P2 & 0x1F) | 0xA0;
	P0 = P0 & 0xAF;
	P2 = P2&0x1F;
}


void ConfigTimer0(u16 ms)
{
    u32 tmp; 
    
    tmp = 11059200 / 12;    
    tmp = (tmp * ms) / 1000;  
    tmp = 65536 - tmp;          
    T0RH = (u8)(tmp>>8);  
    T0RL = (u8)tmp;
    TMOD &= 0xF0;   
    TMOD |= 0x01;   
    TH0 = T0RH;     
    TL0 = T0RL;
    ET0 = 1;       
    TR0 = 1;       
}

void LedScan()
{
 	static u8 index=0;

	P2 = (P2 & 0x1F) | 0xE0;
	P0 = 0xFF;
	P2 = (P2 & 0x1F);

	P2 = (P2 & 0x1F) | 0xC0;
	P0 = 0x80>>index;
	P2 = (P2 & 0x1F);
	P2 = (P2 & 0x1F) | 0xE0;
	P0 = LedBuff[index];
	P2 = (P2 & 0x1F);
	
	index++;
	index &= 0x07;
}

void InterruptTimer0() interrupt 1
{
    TH0 = T0RH; 
    TL0 = T0RL;

	LedScan();
}

infrared.c

/*
*******************************************************************************
* 文件名:infrared.c
* 描  述:
* 作  者:CLAY
* 版本号:v1.0.0
* 日  期: 
* 备  注:
*         
*******************************************************************************
*/

#include "config.h"


bit irflag = 0;
u8 ircode[4];

void InitInfrared()//初始化T1相关参数,等着一会计时用!
{
 	IR_INPUT = 1;//确保红外引脚被释放
	AUXR &= 0xBF;//定时器时钟12T模式
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TR1 = 0;
	ET1 = 0;
}

u16 GetHighTime()
{
 	TH1 = 0;
	TL1 = 0;
	TR1 = 1;
	while(IR_INPUT)
	{
	 	if(TH1 >= 0x46)//高电平持续时间大于18ms  ...0x4650...
		{
		 	break;
		}
	}
	TR1 = 0;

	return (TH1*256 + TL1);
}

u16 GetLowTime()
{
 	TH1 = 0;
	TL1 = 0;
	TR1 = 1;
	while(!IR_INPUT)
	{
	 	if(TH1 >= 0X46)//低电平持续时间大于18ms  ...0x4650...
		{
		 	break;
		}
	}
	TR1 = 0;

	return (TH1*256 + TL1);
}

//void IRScan()//对应的内部晶振11.0592M
//{
// 	u8 i, j;
//	u8 byt;
//	u16 time;
//
//	time = GetLowTime();			  //引导码的低电平 9ms - 9000
//	if((time<8500) || (time>9500))
//	{
//		return; 	
//	}
//
//	time = GetHighTime();
//	if((time<4000) || (time>5000))//引导码的高电平 4.5ms - 4500
//	{
//	 	return;	
//	}
//
//	for(i=0; i<4; i++)
//	{
//		for(j=0; j<8; j++)
//		{
//		 	time = GetLowTime();
//			if((time<340) || (time>780))
//			{
//			 	return;
//			}
//
//			time = GetHighTime();
//			if((time>340) && (time<780))
//			{
//			 	byt >>= 1;
//			}
//			else if((time>1460) && (time<1900))
//			{
//				byt >>= 1;
//				byt |= 0x80;
//			}
//			else
//			{
//			 	return;
//			}
//		}
//		ircode[i] = byt;
//	}
//	irflag = 1;
//}

void IRScan()对应的内部晶振12M
{
 	u8 i, j;
	u8 byt;
	u16 time;

	time = GetLowTime();
	if((time <7833) || (time > 8755))	   
	{
		return;	
	}

	time = GetHighTime();
	if((time<3686) || (time > 4608))
	{
		return;
	}
	for(i=0; i<4; i++)
	{
		for(j=0; j<8; j++)
		{
			time = GetLowTime();
			if((time<313) ||(time >718))
			{
				return;
			}
			time = GetHighTime();
			if((time>313) && (time <718))
			{
				byt >>= 1;	
			}
			else if((time>1345) && (time<1751))
			{
				byt >>= 1;
				byt |= 0x80;
			}
			else
			{
				return;
			}
		}
		ircode[i] = byt;
	}
	irflag = 1;
}

infrared.h

/*
*******************************************************************************
* 文件名:infrared.h
* 描  述:
* 作  者:CLAY
* 版本号:v1.0.0
* 日  期: 
* 备  注:
*         
*******************************************************************************
*/

#ifndef INFRARED_H
#define INFRARED_H

void InitInfrared();
void IRScan();

extern bit irflag;
extern u8 ircode[4];

#endif

config.h

/*
*******************************************************************************
* 文件名:config.h
* 描  述:一些公用文件
* 作  者:CLAY
* 版本号:v1.0.0
* 日  期: 
* 备  注:
*         
*******************************************************************************
*/

#ifndef CONFIG_H
#define CONFIG_H

#include <stc15.h>
#include <intrins.h>

typedef unsigned char u8;
typedef unsigned int  u16;
typedef unsigned long u32;

#define LCD1602_DB P0
sbit LCD1602_RS = P2^0;
sbit LCD1602_RW = P2^1;
sbit LCD1602_E  = P1^2;

sbit I2C_SCL = P2^0;
sbit I2C_SDA = P2^1;

sbit DS1302_CE = P1^3;
sbit DS1302_CK = P1^7;
sbit DS1302_IO = P2^3;

sbit KEY_OUT_1 = P3^0;
sbit KEY_OUT_2 = P3^1;
sbit KEY_OUT_3 = P3^2;
sbit KEY_OUT_4 = P3^3;
sbit KEY_IN_1 = P4^4;
sbit KEY_IN_2 = P4^2;
sbit KEY_IN_3 = P3^5;
sbit KEY_IN_4 = P3^4;

sbit IR_INPUT = P1^1;


#endif

小结:本篇文章主要介绍了单片机比赛中的一个不那么重要的比赛模块:vs1838B。该部分说实话同1602一样,在比赛中几乎考不到,但是对以后实际项目的攻关,大有裨益!还是希望读者可以借此机会好好研究一下!

希望大家多多支持我的原创文章。如有错误,请大家及时指正,非常感谢。


微信搜索ReCclay,即可免费阅读博主蓝桥系列所有文章,后台回复“代码”即可获取蓝桥所有备赛代码!关注博主公众号,还可拥有加入博主粉丝群实时沟通技术难题、免费下载CSDN资源等多项福利,还在等什么呢?快快扫码关注,学习才不会迷路

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReCclay

如果觉得不错,不妨请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值