抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

红外通信

红外遥控电路组成

一般而言,红外遥控系统由发射装置接收装置两大部分组成

发射装置(例如遥控器)主要包括:

  • 键盘电路
  • 红外编码芯片
  • 电源
  • 红外发射电路

红外接收设备:

  • 可由红外接收电路
  • 红外解码芯片
  • 电源
  • 应用电路组成

image-20210824165320963

信号调制和解调

为了使信号更好的传输,一般会把信号进行调制使频率变高,接收到后再通过解调等一系列步骤还原信号

NEC协议

NEC 标准下的编码表示

  1. 引导码高电平约 9000us 左右,低电平约4500us 左右

  2. 用户码16 位,数据码16 位,共32位

    image-20210824165820317

  3. 数据0 是用“高电平约 560us + 低电平约 560us ”表示

  4. 数据1 是用“高电平约 560us + 低电平约 1680us”表示

    image-20210824165845177

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
NEC协议红外通信
单片机解码后通过串口以9600的比特率发送出去
*/

#include <reg52.h>

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

typedef unsigned int INT16U;
typedef unsigned int uint;

/*====================================
硬件接口位声明
====================================*/
sbit IR = P3^2; //定义红外脉冲数据接口 外部中断O输入口

uchar IRtime; //检测红外高电平持续时间(脉宽)
uchar IRcord[4]; //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
uchar IRdata[33]; //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
bit IRpro_ok, IRok; //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕

void init() //初始化定时器0 和外部中断0
{
TMOD = 0x22; //定时器0和定时器1工作方式2,8位自动重装
TH0 = 0x00; //高8位装入0那么定时器溢出一次的时间是256个机器周期
TL0 = 0x00;
EA = 1; //总中断
ET0 = 1; //定时器0中断
TR0 = 1; //启动定时器0

IT0 = 1; //设置外部中断0为跳沿触发方式,来一个下降沿触发一次
EX0 = 1; //启动外部中断0

TH1 = 0xfd; //此溢出率为波特率9600
TL1 = 0xfd;
TR1 = 1; //启动定时器1
SM1 = 1; //设置串口工作方式1,10位异步收发器
}

void time0() interrupt 1 //定义定时器0
{
IRtime++; //检测脉宽,1次为278us
}

void int0() interrupt 0 //定义外部中断0
{
static uchar i; // 声明静态变量(在跳出函数后在回来执行的时候不会丢失数值)i用于把33次高电平的持续时间存入IRdata
static bit startflag; //开始储存脉宽标志位
if(startflag) //开始接收脉宽检测
{
if( (IRtime < 53) && (IRtime >= 32) ) /*判断是否是引导码,底电平9000us+高4500us
这个自己可以算我以11.0592来算了NEC协议的引导码低8000-10000+高4000-5000
如果已经接收了引导码那么i不会被置0就会开始依次存入脉宽*/
i = 0; //如果是引导码那么执行i=0把他存到IRdata的第一个位
IRdata[i] = IRtime; //以T0的溢出次数来计算脉宽,把这个时间存到数组里面到后面判断
IRtime = 0; //计数清零,下一个下降沿的时候在存入脉宽
i++; //计数脉宽存入的次数
if(i == 33) //如果存入34次 数组的下标是从0开始i等于33表示执行了34次
{
IRok = 1; //那么表示脉宽检测完毕
i = 0; //把脉宽计数清零准备下次存入
}
}
else
{
IRtime = 0; //引导码开始进入把脉宽计数清零开始计数
startflag = 1; //开始处理标志位置1
}
}

void IRcordpro() //提取它的33次脉宽进行数据解码
{
uchar i, j, k, cord, value; /*i用于处理4个字节,j用于处理一个字节中每一位,k用于33次脉宽中的哪一位
cord用于取出脉宽的时间判断是否符合1的脉宽时间*/
k = 1; //从第一位脉宽开始取,丢弃引导码脉宽
for(i = 0; i < 4; i++)
{
for(j = 0; j < 8; j++)
{
cord = IRdata[k]; //把脉宽存入cord
if(cord > 5) //如果脉宽大于我11.0592的t0溢出率为约278us*5=1390那么判断为1
value = value | 0x80; /*接收的时候是先接收最低位,
把最低位先放到value的最高位在和0x08按位或一下
这样不会改变valua的其他位的数值只会让他最高位为1*/
if(j < 7)
{
value = value >> 1; //value位左移依次接收8位数据。
}
k++; //每执行一次脉宽位加1
}
IRcord[i] = value; //每处理完一个字节把它放入IRcord数组中。
value = 0; //清零value方便下次在存入数据
}
IRpro_ok = 1; //接收完4个字节后IRpro ok置1表示红外解码完成
}


void main()
{
uchar i;
init(); //执行初始化定时器0和外部中断0
while(1) //大循环
{
if(IRok) //判断脉宽是否检测完毕
{
IRcordpro();//根据脉宽解码出4个字节的数据
IRok = 0; //重新等待脉宽检测
if(IRpro_ok) //判断是否解码完毕
{
for(i = 0; i < 4; i++)
{
SBUF = IRcord[i];
while(!TI);
TI = 0;
}
IRpro_ok = 0;
}
}
}
}

评论