小鹏STEM
首页
主题
课程
课件
创作
赛事
资源
文章
登录
注册
红外线解码及发射
红外线在生活中的应用十分广泛,如电视的遥控器就是通过发射红外线来完成其控制功能的。大多数的红外线发射和接收都是通过专用的IC来实现的,不过单片机同样可以在红外收发过程中大显身手,既可以用它来编码并驱动发射器发射红外线,也可以配合一体化红外接收头实现红外线的解码。本章主要介绍如何使用AVR单片机进行红外线的解码和发射。
18.1
红外线遥控的编码方式
红外线发射和接收专用IC型号众多,但其编码方式基本相同,我们以SC6122红外遥控发射集成电路为例,说明一下红外线遥控的编码方式。
18.1.1
编码的帧结构
SC6122是一块专用于红外线发射的集成电路,其所发射的一帧码由一个引导码、低8位用户编码、高8位用户编码、8位键数据码以及8位键数据码的反码构成,其编码结构如图18-1所示。
引导码是一帧码的起始部分,也是随后发射编码的引导。引导码由一个9ms的高电平和4.5ms的低电平构成,当接收系统由微处理器构成时,引导码会使微处理器更加可靠地识别编码并为正确的解码做好准备。接下来的16位是用户编码,用于区别不同的红外线发射设备,而最后的16位键数据码则是用于区别同一个红外发射设备上不同按键或不同的功能选项,当8位的键码被发送的同时,也会将其反码同时发送,以减少系统的误码率。
18.1.2
编码的方式
无论编码采用何种结构,其最基本的元素都是由若干个“0”和“1”构成。在红外线编码过程中,采用了脉冲位置调置方式(PPM),通过脉冲间的时间间隔来区分“0”或“1”。这种编码的方式如图18-2所示。
无论是编码“0”或“1”,编码首先都是由一个持续时间为0.56ms的高电平开始,之后根据接下来的低电平的持续时间来区别是“0”还是“1”。如果低电平的持续时间是0.56ms,则表示发送的是“0”,如果低电平的持续时间约为3×0.56ms,则表示发送的是“1”。
18.1.3
编码的调制与解调
从红外线编码的帧结构中我们发现,红外遥控信号其实就是一连串的二进制脉冲序列。为了使其在无线传输过程中免受可见光或其他红外信号的干扰,通常都是将这个二进制的脉冲序列调制在38kHz的载波频率上,然后再经红外发射二极管发射出去。原始的红外编码信号波形如图18-3所示,经调制后的信号波形如图18-4所示。
在红外线接收端,对于这种已经进行调制了的红外遥控信号,通常是采用一体化红外线接收头进行解调。一体化红外线接收头如图18-5所示,它是将红外接收二极管、低噪声放大器、限幅器、带通滤波器、解调器以及脉冲整形电路等集成在一起,专用于红外线的接收和解调。一体化红外接收头具有体积小、灵敏度高、外接元件少、抗干扰能力强等许多优点,目前已经成为红外线解码的标准器件。
红外光信号经一体化接收头接收后,将载波去掉并还原出数字编码信号。这里需要注意的是,经还原后有红外编码信号与发送端是反向的,即原来编码信号中的高电平变成了低电平,而低电平变成了高电平,这样做的目的是为了提高接收的灵敏度。经解调后的红外编码信号波形如图18-6所示。
18.2
红外线解码与发射
18.2.1
红外线解码的方法
使用单片机进行红外线解码,目的就是将一帧编码中的用户编码和键数据码分离出来,用于软件分析。红外线解码的硬件电路如图18-7所示。
在解码过程中要注意以下两个方面:
1)一体化接收头在未收到红外线遥控信号时,其信号输出端是持续的高电平。一旦其检测到经调制的红外线遥控信号,会首先将图18-6中所示的引导码中9ms低电平和4.5ms的高电平输出,判断这两个电平的宽度是区别干扰信号和启动解码的有效方法。
2)解码的关键是如何正确识别出二进制脉冲序列中的“0”和“1”。同样从图18-6中可以看出,经解调后的红外编码信号,无论是编码“0”或“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同。编码“0”的高电平持续时间是0.56ms,而编码“1”的高电平持续时间为1.69ms。在实际应用中,我们会在高电平的持续时间范围0.56ms至1.69ms之间取一个中间值1.12ms,把小于1.12ms的高电平认定是编码“0”,而把大于1.12ms的高电平认定是编码“1”。
18.2.2
红外线发射的方法
使用单片机同样可以完成红外线的编码和发射。为了简化程序代码,我们可以使用外部的硬件振荡器来产生38kHz的调制信号,单片机只需要控制高低电平的发送时间即可实现红外线的编码及发射,单片机控制的红外线编码及发射电路如图18-8所示。在使用单片机对红外发射信号进行编码时,其波形应当参考图18-3中关于编码的定义。
18.3
红外线遥控编程实例
18.3.1
红外线解码器
在AVR的系统板上,按照图18-7所示的红外线解码电路,将一体化红外接收头与ATmega32单片机的PD7引脚相连,图中22μF电容不可以省略,否则会出现不能正确解码的问题。打开Atmel Studio 6.1软件,新建名为“IR1”的项目,保存在chapter18文件夹下,软件会自动将名为IR1.c的源文件添加到新建的项目中。编辑IR1.c源文件,具体代码详见代码清单18-1。
代码清单18-1
红外线解码
/*
*
IR1.c *
红外线解码程序
PD7
数据端
*
Created: 2013/10/27
14:15:05
*
Author: GAO */
/*
红外线开始发送一段13.5ms 的引导码,由9ms 的高电平和4.5ms 的低电平
组成,跟着引导码是8
位系统码,8
位系统反码,8
位按键码,8
位按键反码*/
#include
//
包含AVR 头文件
#include
//
包含AVR 中断控制头文件
#define F_CPU 16000000UL //
定义系统时钟
#include
//
包含延时函数头文件
#define uchar unsigned char #define uint unsigned int const uchar table0[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //
共阴数码管0-F uchar ir_code[4]; //
定义数组,用于保存解码结果
uchar display_code[4]; //
定义数组,用于数码管显示缓冲区
uchar MS; //
定义毫秒变量,用于控制数码管显示
void seg_init(void); //
数码管驱动端初始化函数声明
void ir_bus_init(void); //
红外线解码接收端初始化函数声明
void TC0_init(void); //
定时器0
初始化函数声明
void TC1_init(void); //
定时器1
初始化函数声明
uint check_low_time(void); //
检测低电平时间函数声明
uint check_high_time(void); //
检测高电平时间函数声明
/***********
主函数***********/
int main(void)
{
ir_bus_init(); seg_init(); TC0_init(); TC1_init(); ir_code[0]=0; //
数组赋初值
ir_code[1]=0; ir_code[2]=0; ir_code[3]=0; display_code[0]=0; //
数组赋初值
display_code[1]=0; display_code[2]=0; display_code[3]=0; uint temp; //
定义临时变量
uchar x,y; //
定义循环变量
while(1)
{
restart: //
晶振16M ,1/8
分频比,每次计数需0.5
μs while((PIND&0x80)==0x80); //
无信号时接收头输出高电平,程序在此等待
temp=check_low_time(); //
捕获低电平并计算它的长度
if((temp<17000)||(temp>19000))
continue; //
引导脉冲低电平小于8.5ms 或大于9.5ms 去掉,9ms 会通过
temp=check_high_time(); //
捕获高电平并计算它的长度
if((temp<8000)||(temp>10000))
continue; //
引导脉冲高电平小于4ms 或大于5ms 去掉,4.5ms 会通过
for(x=0;x<4;x++)
//4
个字节解码开始
{
for(y=0;y<8;y++)
//
每个字节8
位
{
temp=check_low_time(); //
判断低电平宽度是否符合要求
if((temp<400)||(temp>1600))
goto restart; temp=check_high_time(); //
判断高电平宽度是否符合要求
if((temp<400)||(temp>4000))
goto restart; ir_code[x]>>=1; //
将红外解码变量左移1
位
if(temp>2240)
ir_code[x]|=0x80; }
//
如果检测的高电平时间大于1120ms //
即为编码1
,在解码变量最高位上或"1"
}
/*
为了解码出位"0"
和"1"
,在高电平的存在时间范围0.56-1.68ms 之间取一个
中间值1.12ms, 小于1.12ms 的高电平是位"0"
,大于1.12ms 的高电平是位"1"
。*/
/*
以下只使用两位键码Ir_Buf[2]
和Ir_Buf[3]
来显示,系统码Ir_Buf[0]
和Ir_Buf[1]
在本程式
中不采用,可以另做其他编程使用*/
display_code[0]=ir_code[3]&0x0f; display_code[1]=(ir_code[3]/16)&0x0f; display_code[2]=ir_code[2]&0x0f; display_code[3]=(ir_code[2]/16)&0x0f; }
}
/**********
数码管显示初始化函数**********/
void seg_init(void)
{
DDRA|=0xFF; //
设数码管段驱动端为输出
DDRB|=0xF0; //
设数码管位驱动端为输出
}
/**********
红外线解码接收端初始化函数**********/
void ir_bus_init(void)
{
DDRD&=0x7F; //PD7
为输入
}
/**********T/C1
初始化函数**********/
void TC1_init(void)
{
TCNT1H=0; //
初值0
(晶振16M ,1/8
分频比,每次计数需0.5us )
TCNT1L=0; TCCR1A=0x00; TCCR1B=0x00; //
不为T/C0
分配时钟,运行时分配时钟(1/8
分频比)
}
/**********
检测低电平时间函数**********/
uint check_low_time(void)
{
uchar VALL,VALH; uint VAL; TCNT1H=0; TCNT1L=0; TCCR1B=0x02; while((PIND&0x80)==0); TCCR1B=0x00; VALL=TCNT1L; VALH=TCNT1H; VAL=VALH*256+VALL; return VAL; }
/**********
检测高电平时间函数**********/
uint check_high_time(void)
{
uchar VALL,VALH; uint VAL; TCNT1H=0; TCNT1L=0; TCCR1B=0x02; while((PIND&0x80)==0x80); TCCR1B=0x00; VALL=TCNT1L; VALH=TCNT1H; VAL=VALH*256+VALL; return VAL; }
/**********T/C0
初始化函数**********/
void TC0_init(void)
{
SREG|=0x80; //
开全局中断
TIMSK|=0x01; //
开T/C0
溢出中断
TCNT0=(256-16); //
初值16
(16*0.0625us*1024=1.024ms )
TCCR0=0x05; //
T/C0
预分频比1/1024
}
/**********T/C0
中断服务函数**********/
ISR(TIMER0_OVF_vect)
{
TCNT0=(256-16); //
初值16
(16*0.0625us*1024=1.024ms )
MS++; //
毫秒变量自加1
,用于控制数码管显示扫描顺序
if(MS==8)
{
MS=0; }
switch(MS)
//
数码管中断法显示
{
case 0: PORTA=table0[display_code[0]];PORTB|=0x10; break; case 1: PORTA=0x00;PORTB&=0xEF;break; case 2: PORTA=table0[display_code[1]];PORTB|=0x20; break; case 3: PORTA=0x00;PORTB&=0xDF;break; case 4: PORTA=table0[display_code[2]];PORTB|=0x40; break; case 5: PORTA=0x00;PORTB&=0xBF;break; case 6: PORTA=table0[display_code[3]];PORTB|=0x80; break; case 7: PORTA=0x00;PORTB&=0x7F;break; }
}
/**********
结束**********/
将上述代码正确编译后下载到AVR系统板中,程序运行后数码管显示“0000”,使用遥控器对准连接到系统板上的红外接收头,按下按键,其键码值会显示在数码管上,具体效果如图18-9所示。
18.3.2
红外线发射器
按照图18-8介绍的红外线编码及发射电路原理,自行设计制作红外线发射模块,并使用ATmega32单片机的PD7引脚驱动红外线发射控制端。在Atmel Studio 6.1软件里,新建名为“IR2OUT”的项目,同样保存在chapter18文件夹下,软件会自动将名为IR2OUT.c的源文件添加到新建的项目中。编辑IR2OUT.c源文件,具体代码详见代码清单18-2。
代码清单18-2
红外线发射
/*
*
IR2OUT.c *
红外线发射程序红外驱动端PD7
*
Created: 2013/10/28
17:13:04
*
Author: GAO */
#include
//
包含AVR 头文件
#define F_CPU 16000000UL //
定义系统时钟
#include
//
包含延时函数头文件
#define uchar unsigned char #define uint unsigned int #define ir_out_SET (PORTD|=0x80)
//
置位PD7
(定义红外线发射驱动端)
#define ir_out_CLR (PORTD&=0x7F)
//
清零PD7
void ir_out_init(void); //
红外发射驱动端口初始化函数声明
void send0(void); //
发送红外线编码0
函数声明
void send1(void); //
发送红外线编码1
函数声明
void leadnumber(void); //
发送引导码函数声明
void irbit(uchar k); //
发射1
位红外线码函数声明
void irsend(uchar val); //
发射一帧红外线码函数声明
/**********
主函数**********/
int main(void)
{
ir_out_init(); //
初始化红外驱动端口
ir_out_CLR; //
关闭红外发射
while(1)
{
irsend(11); //
连续发射5
次,键码:11
irsend(11); irsend(11); irsend(11); irsend(11); _delay_ms(1000); //
延时1000ms irsend(1); //
连续发射5
次,键码:1
irsend(1); irsend(1); irsend(1); irsend(1); _delay_ms(1000); //
延时1000ms }
}
/**********
红外发射驱动端口初始化函数**********/
void ir_out_init(void)
{
DDRD|=0x80; }
/**********
发送红外线编码0
函数**********/
void send0(void)
{
ir_out_SET; _delay_us(560); //
延时560
μs ir_out_CLR; _delay_us(560); //
延时560
μs }
/**********
发送红外线编码1
函数**********/
void send1(void)
{
ir_out_SET; _delay_us(560); //
延时560
μs ir_out_CLR; _delay_us(560); //
延时560
μs _delay_us(560); //
延时560
μs _delay_us(560); //
延时560
μs }
/**********
发送引导码函数**********/
void leadnumber(void)
{
uchar i; //
发送9ms 高电平、4.5ms 低电平
ir_out_SET; for(i=0;i<16;i++)
{
_delay_us(560); //
延时560
μs }
ir_out_CLR; for(i=0;i<8;i++)
{
_delay_us(560); //
延时560
μs }
}
/**********
发射1
位红外线码函数**********/
void irbit(uchar k)
{
if(k==0)
{
send0(); }
else {
send1(); }
}
/**********
发射一帧红外线码函数**********/
void irsend(uchar val)
{
uchar i,k; //
即引导码,16
位机器码,8
位键码,8
位键码反码
leadnumber(); //
发送引导码
for(i=0;i<4;i++)
//
发送8
位机器码0101
0101
{
irbit(0); irbit(1); }
for(i=0;i<4;i++)
//
发送8
位机器码0101
0101
{
irbit(0); irbit(1); }
for(i=0;i<8;i++)
//
发送8
位键盘码
{
k=val; k=k>>i&1; //
取最低位
irbit(k); }
for(i=0;i<8;i++)
//
发送8
位键盘码反码
{
k=val; k=k>>i&1; irbit(!k); //
取反得到反码
}
}
/**********
结束**********/
使用红外线发射器,可以将自定义的机器码、键码以红外的方式进行发送,从而模拟不同的红外线发射设备,甚至还可以用于近距离的红外线数字传输。掌握了红外线的解码和发射,相信你一定还会开发出许多更有创意的红外产品出来。怎么样,快来试试吧!
上一节
DS1302实时时钟
下一节
DS18B20数字温度传感器
微信分享
评论
评论:
提交
AVR单片机应用实例
作者:高显生 共7讲
阅读模式
课程
步进电机的驱动
DS1302实时时钟
红外线解码及发射
DS18B20数字温度传感器
DHT11数字温湿度传感器
1602字符型液晶显示器
12864点阵型液晶显示器
推荐文章
用积木拼出时间?乐高还是太全面了!
在STEM(科学、技术、工程和数学)教育中推进AI辅助计算思维(Act-STEM)
乐高机械组42215 沃尔沃 EC500 混动挖掘机
Codeblocks 快速入门
树莓派Build HAT
乐高WEDO打印机搭建分享
《2024素质教育行业发展趋势报告》:“AI+素质教育”逐步落地
2025年少儿编程行业五大预测:少儿编程正站在一个新的起点上
乐高反重力悬浮?
Scratch 3.0连接EV3
推荐资源
深圳市义务教育人工智能课程纲要(2024年版)
乐高教育 2023 产品解决方案指南
FLL机器人挑战赛2024-2025赛季 SUBMERGED 资料
小学科学课程标准
EV3 Classroom程序创意设计第一部分
技术运用于教育:谁来做主?
乐高教育 WeDo 2.0 计算思维-教师指南
2023中小学阶段的人工智能课程调研报告
Python神经网络编程
微信分享
×
登录
×
手机号:
密码:
忘记密码?
微信扫码登录
×