实验开发板为CT107D蓝桥官方板,编译环境为MDK5
目录
工程下载地址:
https://gitee.com/Joseph_Cooper/blue-bridge-mcu/tree/master
1 、红外发射和接收原理简述
红外发射:通过单片机软件模拟发射出一定频率的红外信号,红外信号的发射类似于普通LED,不过红外发射头发射的是不可见的红外光,并且以一定的频率发射 。
红外接收头:L2为红外接收管收到的红外光越强则反向电流越大则3口电压越小通过运算后发向信号检测端口。
在这里先不深入研究原理,蓝桥的板子为一体化接收头先掌握驱动原理吧。
2、蓝桥杯竞赛板所使用的红外一体化接收头
2.1、通信协议
红外一体化接收头使用的是NEC通信协议。只用一个引脚来完成数据的接收因此对时间有严格的要求。
NEC数据格式:引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,
最后一个停止位。
引导码:9ms的载波+4.5ms的空闲。
比特值“0”:560us的载波+560us的空闲。
比特值“1”:560us的载波+1.68ms的空闲。
图片来源@金沙滩工作室
2.2、实际驱动
在使用红外接收头前要先将红J2跳线帽全部右移才能使用红外发射和接收。
一般红外接收引脚会接在外部中断方便接收到信号后直接读取信号,但是反人类的蓝桥开发板并没有,所以我用了一根杜邦线连接了P3^3和P1^1。
具体操作如下:
/**************************************************/
/* 需使用杜邦线将P1^1和P3^3短接 */
/**************************************************/
#include "infrared.h"
bit irflag = 0;
u8 ircode[4];//数码管接收缓冲区
void InitInfrared()
{
//AUXR &= 0x7F;//设置定时器为12T模式
IR_INPUT = 1;
TMOD = (TMOD & 0x0F) | 0x10;
TR1 = 0;
ET1 = 0;//定时器1中断关闭
IT1 = 1;//设置外部中断1为下降沿触发
}
u16 GetHighTime()
{
TH1 = 0;
TL1 = 0;
TR1 = 1;
while(IR_INPUT)
{
if(TH1 >= 0x40) break;//高电平时间持续过长(约18ms)则跳出
}
TR1 = 0;
return (TH1 * 256 + TL1);
}
u16 GetLowTime()
{
TH1 = 0;
TL1 = 0;
TR1 = 1;
while(!IR_INPUT)
{
if(TH1 >= 0x40) break;//低电平时间持续过长(约18ms)则跳出
}
TR1 = 0;
return (TH1 * 256 + TL1);
}
//INT1外部中断服务函数,接收红外并解码
void Service_INT1() interrupt 2
{
u8 i, j;
u8 byt;
u16 time;
SMG_Display();
time = GetLowTime();
if( (time < 7833) || (time > 8755) )//判断是否为误码
{
IE1 = 0;//清除外部中断标志
return;
}
time = GetHighTime();
if( (time < 3686) || (time > 4608) )//判断是否为误码
{
IE1 = 0;
return;
}
for(i = 0; i < 4; i ++)
{
for(j = 0; j < 8; j ++)
{
//先判断每位的数据中的低电平是否超时
time = GetLowTime();
if( (time < 313) || (time > 718) )
{
IE1 = 0;
return;
}
//接收判断每位高电平时间判断值
time = GetHighTime();
if( (time > 313) && (time < 718) )//值为0
{
byt >>= 1;
}
else if( (time > 1345) || (time < 1751) )//值为1
{
byt >>= 1;
byt |= 0x80;
}
else//不符合上述两种条件即为误码
{
IE1 = 0;
return;
}
}
ircode[i] = byt;
}
irflag = 1;
IE1 = 0;
}
void HW_Get()
{
if(irflag)
{
irflag = 0;
SMG_Buff[0] = SMG[ircode[0] >> 4];
SMG_Buff[1] = SMG[ircode[0]&0x0F];
SMG_Buff[6] = SMG[ircode[2] >> 4];
SMG_Buff[7] = SMG[ircode[2]&0x0F];
}
}
/****************************infrared.h****************************/
#ifndef _INFRARED_H
#define _INFRARED_H
#include "config.h"
#include "SMG.h"
sbit IR_INPUT = P1^1;
extern void InitInfrared();
extern u16 GetHighTime();
extern u16 GetLowRime();
extern void HW_Get();
#endif
数码管上显示的是用户码的前两位和16进制的键码