1 实验现象
LCD1602上显示红外解码遥控器地址、键值。通过红外遥控器,按下某个按键时,遥控器通过红外发光二极管发射红外线,红外一体化接受头接受信号,并对其解码,单片机处理相应的信息,将得到的数据显示在LCD1602上。
2 实验原理
红外遥控是一种无线、非接触控制技术,具有抗干扰性能力强,信息传输可靠,功耗低、成本低、易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,在工业设备中也得到广泛应用。
什么是红外线?红外线是一种肉眼看不见的光。红外线是波长介于微波和可见光之间的电磁波,波长在760nm和1000nm之间,是波形比红光长的非可见光。
如何发出红外光?红外发射二极管就可以发出红外线。最常用的红外发射管是发出940nm的红外光。它的外形类似二极管,但是它发射出来的是红外光,是我们肉眼所看不到的。发光二极管的亮度会随着电路的增大而增加,同样的道理,红外发射管发射红外线的强度也会随着电流的增大而增强。
红外遥控基本原理:红外遥控器常用的载波的方式传送二级制编码,常用的载波频率为38KHz,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,井缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。
3 系统设计
4 硬件设计(略)
5 软件设计
5.1 主函数
#include
#include "lcd1602.h"
#include "InfraredRemote.h"
unsigned char Num;
unsigned char address;
unsigned char command;
void main()
{
LCD1602_Init();
LCD1602_ShowString(1,1,"ADDR CMD NUM");
LCD1602_ShowString(2,1,"00 00 000");
IR_init();
while(1)
{
if(IR_getdataflag()||IR_getrepeatflag()) //如果收到数据帧或者收到连发帧
{
address=IR_getaddress(); //获取遥控器地址码
command=IR_getcommand(); //获取遥控器命令码
LCD1602_ShowHexNum(2,1,address,2); //显示遥控器地址码
LCD1602_ShowHexNum(2,7,command,2); //显示遥控器命令码
if(command==IR_VOL_MINUS) //如果遥控器VOL-按键按下
{
Num--; //Num自减
}
if(command==IR_VOL_ADD) //如果遥控器VOL+按键按下
{
Num++; //Num自增
}
LCD1602_ShowNum(2,12,Num,3);//显示Num
}
}
}
5.2 红外遥控接收函数
#include
#include "timer0.h"
#include "exint0.h"
unsigned int IR_time; //记录相邻两个下降沿的时间
unsigned char IR_state; //状态机设计
unsigned char IR_data[4]; //用来接收数据32位,4个字节
unsigned char IR_pdata; //用来记录接收第几位数据,0-31
unsigned char IR_dataflag; //数据接收完毕标识信号
unsigned char IR_repeatflag; //重复发送标识信号
unsigned char IR_address; //接收地址
unsigned char IR_command; //接收命令
/**
* @brief 红外遥控初始化
* @param 无
* @retval 无
*/
void IR_init(void)
{
exint0_init(); //外部中断INT0
timer0_init(); //定时器T0
}
/**
* @brief 红外遥控获取收到数据帧标志位
* @param 无
* @retval 是否收到数据帧,1为收到,0为未收到
*/
unsigned char IR_getdataflag(void)
{
if(IR_dataflag)
{
IR_dataflag=0;
return 1;
}
else
return 0;
}
/**
* @brief 红外遥控获取收到连发帧标志位
* @param 无
* @retval 是否收到连发帧,1为收到,0为未收到
*/
unsigned char IR_getrepeatflag(void)
{
if(IR_repeatflag)
{
IR_repeatflag=0;
return 1;
}
else
return 0;
}
/**
* @brief 红外遥控获取收到的地址数据
* @param 无
* @retval 收到的地址数据
*/
unsigned char IR_getaddress(void)
{
return IR_address;
}
/**
* @brief 红外遥控获取收到的命令数据
* @param 无
* @retval 收到的命令数据
*/
unsigned char IR_getcommand(void)
{
return IR_command;
}
//外部中断0中断函数,下降沿触发执行,状态机设计
void int0_routine(void) interrupt 0
{
if(IR_state==0) //状态0,空闲状态
{
timer0_SetCounter(0); //设置计数器起始值,从0开始计数
timer0_Run(1); //启动定时器T0
IR_state=1;
}
else if(IR_state==1) //状态1,等待Start信号或Repeat信号
{
IR_time=timer0_GetCounter(); //获取上一次中断到此次中断的时间
timer0_SetCounter(0); //设置计数器起始值,从0开始计数
//如果计时为9ms+4.5ms=13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)
if(IR_time>12442-500 && IR_time<12442+500) //起始信号(11.0592MHz)
{
IR_state=2; //状态2,接收数据
}
//如果计时为9ms+2.25ms=11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)
else if(IR_time>10368-500 && IR_time<10368+500) //重复信号
{
IR_repeatflag=1; //置收到连发帧标志位为1
timer0_Run(0); //关闭定时器T0
IR_state=0; //置状态为0
}
else IR_state=1; //接收错误,状态保持
}
else if(IR_state==2) //接收数据状态
{
IR_time=timer0_GetCounter(); //获取上一次中断到此次中断的时间
timer0_SetCounter(0); //设置计数器起始值,从0开始计数
//如果计时为560+560=1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)
if(IR_time>1032-500 && IR_time<1032+500) //数据0
{
IR_data[IR_pdata/8] &= ~(0x01<<(IR_pdata%8)); //数据对应位清0
IR_pdata++; //数据位置指针自增
}
//如果计时为560+1690=2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)
else if(IR_time>2074-500 && IR_time<2074+500) //数据1
{
IR_data[IR_pdata/8] |= (0x01<<(IR_pdata%8)); //数据对应位置1
IR_pdata++; //数据位置指针自增
}
}
else //接收出错
{
IR_pdata=0; //数据位置指针清0
IR_state=1; //置状态为1
}
if(IR_pdata>=32) //接收完所有数据
{
IR_pdata=0; //数据位置指针清0
//判断地址码和地址反码,数据码和数据反码是否相反,数据验证
if((IR_data[0]==~IR_data[1])&&(IR_data[2]==~IR_data[3]))
{
IR_address=IR_data[0]; //转存数据,地址数据
IR_command=IR_data[2]; //命令数据
IR_dataflag=1; //置收到数据帧标志位为1
}
timer0_Run(0); //关闭定时器T0
IR_state=0; //空闲状态
}
}
#ifndef _InfraredRemote_h_
#define _InfraredRemote_h_
#define IR_POWER 0x45
#define IR_MODE 0x46
#define IR_MUTE 0x47
#define IR_START_STOP 0x44
#define IR_PREVIOUS 0x40
#define IR_NEXT 0x43
#define IR_EQ 0x07
#define IR_VOL_MINUS 0x15
#define IR_VOL_ADD 0x09
#define IR_0 0x16
#define IR_RPT 0x19
#define IR_USD 0x0D
#define IR_1 0x0C
#define IR_2 0x18
#define IR_3 0x5E
#define IR_4 0x08
#define IR_5 0x1C
#define IR_6 0x5A
#define IR_7 0x42
#define IR_8 0x52
#define IR_9 0x4A
void IR_init(void);
unsigned char IR_getdataflag(void);
unsigned char IR_getrepeatflag(void);
unsigned char IR_getaddress(void);
unsigned char IR_getcommand(void);
#endif
5.3 外部中断INT0
#include
void exint0_init(void)
{
IT0=1;
IE0=0;
EX0=1;
EA=1;
PX0=1;
}
//void int0_routine(void) interrupt 0