51单片机红外通讯

51单片机——红外通讯

实物与键码对应图示
在这里插入图片描述在这里插入图片描述
红外接收的电路图:
在这里插入图片描述
NEC协议
数据格式: 发射端的方波图,接收端的正好与之相反,数据传输从最低位开始
在这里插入图片描述
NEC 标准下的编码表示
其中:引导码高电平约9000us 左右,低电平约4500us 左右;
用户码16 位,数据码16 位,共32位;
数据0 是用“高电平约560us +低电平约560us”表示。
数据1 可用“高电平约560us+低电平约1680us”表示。
在这里插入图片描述

通讯流程:(部分顺序可改变)
1.定义头文件。
2.定义要使用的变量。
3.始化定时器0,外部中断0,串口。
4.写定时器0的中断函数。
5.写外部中断0,中断处理函数函数(外部中断0,存储脉宽33次)。
6.写把提取的33次脉宽进行解码 NEC协议 的函数(对比脉宽,看是0还是1)
7.主函数(写出自己的要求(将串口发送的数据显示出来))

程序实现:
#include <reg52.h>

//自定义类型名
typedef unsigned char INT8U;
typedef unsigned char uchar;

typedef unsigned int INT16U;
typedef unsigned int uint;

uchar IRtime; //储存检测红外高低电平持续时间
uchar IRcord[4]; //储存解码后的4个字节数据
uchar IRdata[33]; //包含起始码在内的33位数据
bit IRpro_ok; //解码后四个字节数据接收完成标志位
bit IRok; //33位数据接收完成标志位

//初始化定时器0,外部中断0,串口
void init()
{
TMOD |=0x02; //设置定时器0工作模式2,8位自动重装
TL0 = TH0 = 0; //初始化定时器0寄存器,定时器0溢出一次,时间为256个机器周期
EA = 1; //开总中断
ET0 = 1; //开定时器0中断
TR0 = 1; //启动定时器0

IT0 = 1;  //设置外部中断0跳变沿触发方式
EX0 = 1;  //开外部中断0中断

TMOD |=0x20; //设置定时器1,工作模式2,8位自动重装(串口的定时器)
TL1 = TH1 = 0xfd;//比特率9600
SM1 = 1; //将串口设置为工作模式1,10位异步收发
TR1 = 1; //启动定时器1

}

/中断函数/ //定时器中断,没中断一次需要256*1.085us=277.76us
void time0() interrupt 1 //定时器0的中断
{
IRtime++;//277.76us
}

/外部中断0,存储脉宽33次/
//外部中断0,中断处理函数
void int0() interrupt 0 //c储存33次的计数
{
static uchar i;//(静态)变量用于存入33次数据计数,退出函数时,数值会保留
static bit startflag; //开始储存脉宽标志位
if(startflag) //判断是否为1
{
if((IRtime < 53)&&(IRtime >= 32)) i = 0; //53277.72,32277.72 判断引导码,如果是引导码则从起始码开始存
IRdata[i]=IRtime; //以T0溢出的次数来计算脉宽把这个时间存放在数组中
IRtime = 0; //计数清零
i++; //计数脉宽存入次数自加
if(i==33) //i等于33那么表示已经存入了33次脉宽
{
IRok = 1; // 脉宽检查完成
i = 0; //把脉宽计数清零准备下次存入
}
}
else //(startflag=0时)
{
IRtime = 0; //定时器0计数清零
startflag = 1;//开始处理标志位置1
}
}

//把提取的33次脉宽进行解码 NEC协议
void IRcordpro()//对比脉宽,看是0还是1
{
uchar i; //i是用于计数处理4个字节
uchar j; //j用于计数处理1个字节的8位数据
uchar k; //k用于计数处理33次脉宽
k = 1; //从第一位脉宽开始处理,丢掉起始码
for(i = 0;i < 4;i++) //把四个字节循环完
{
for(j=0;j<8;j++)
{
/如果脉宽大于数据0标准的1125us那么就判定为数据1/
if(IRdata[k]>5) IRcord[i] |=0x80; //最高位写1
//只能右移七次,如果右移八次则会把第一位数据移出去
if(j<7) IRcord[i] >>=1;
k++; //处理下一次脉宽
}
}
IRpro_ok = 1;
}
void main()
{
uchar i; //计数串口发送字节数
init(); //初始化-
while(1)
{
if(IRok) //判断33次脉宽是否提取完成
{
IRcordpro(); //根据脉宽解码出4个字节的数据
IRok = 0; //解码完成后,清零脉宽检查完成标志位等待下一次脉宽检查
if(IRpro_ok ) //判断解码是否完成
{
for(i=0;i<4;i++) //串口发送4个字节数据
{
SBUF = IRcord[i]; //串口发送数据
while(!TI) //等待发送完成标志
TI = 0; //清零发送完成标志为
}
IRpro_ok = 0; //清零解码标志位,以便下次使用
}

	}
}

}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值