实践背景:小孩刚出生不久,每天夜里要醒来好多次,给孩子换尿不湿和喂奶,刚开始只能打开手电筒,拿着很费劲。于是就把自己家卧室灯调暗,再追加一个红外遥控,每次孩子哭闹,按一下遥控器的任意一个按键,就可以打开/关闭卧室灯,解决了我家庭的苦恼。
材料准备:
1、实验线路板/万能板一个(焊接电路使用)
2、小型拨动开关一个(给单片机供电/断电使用)
3、5V手机充电器一个(电路供电)
4、STC89C52单片机一个(核心器件)
5、12MHz晶振一个(单片机最小系统器件)
6、33pF电容两个(单片机最小系统器件)
7、10K/20K/电阻各一个(单片机最小系统器件)
8、VS1838红外接收器一个(接收红外信号使用)
9、4K7电阻一个(红外接收器信号接收端上拉电阻)
10、继电器一个(单片机5V信号控制220V通断,以便控制家庭220V照明灯的开关)
11、红外遥控器一个(发送红外信号使用)
12、导线若干
13、TTL USB转串口工具一个(烧录hex文件使用)
原理图示意图:
经过焊接,装饰后的样子:
硬件部分准备完毕,下面接着描述软件部分:
IDE使用的Keil5,下载工具是 stc-isp-15xx-v6.87F.exe。
至于代码部分,难点在于VS1838的红外接收信号解码。
给出一个可以参考的视频链接供学习参考 《VS1838红外遥控解码》
红外信号按照上述时序进行解析。
详情见上述视频链接,讲的比较清楚。
我没有使用某个按键的码来进行控制继电器开关,我的需求比较简单,只要接收到任意红外遥控的任意按键的信号,继电器的就开或关一次。
参考代码:
#include <reg52.h>
sbit RELAY = P1^7;
sbit IRIN = P3^2;
#define uchar unsigned char
#define uint unsigned int
uchar codes[4];
uchar flag_recv;
void IR_init(void)
{
TMOD = 1;
EX0 = 1;
ET0 = 0;
EA = 1;
}
void IR_CODE(void) interrupt 0
{
uchar i, j, k = 0;
uchar tmp = 0;
TH0 = 0;
TL0 = 0;
TR0 = 1;//start timer
EA = 0;
while(!IRIN)
{
if(TH0 > 45)//11.52 ms 45*256 = 11520
{
EA = 1;
return;
}
}
TR0 = 0;
if(TH0 < 25) //6.4ms 25*256 = 6400
{
EA = 1;
return;
}
TH0 = 0;
TL0 = 0;
TR0 = 1;
while(IRIN)
{
if(TH0 > 28)//7.168 ms 28*256 = 7168
{
EA = 1;
return;
}
}
//now start to check signals
TH0 = 0;
TL0 = 0;
TR0 = 0;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 8; j++)
{
TR0 = 1;
while(!IRIN)
{
if(TH0 > 15) //15*256 = 3840
{
EA = 1;
return;
}
}
TH0 = 0;
while(IRIN)
{
if(TH0 > 15) //15*256 = 3840
{
EA = 1;
return;
}
}
TR0 = 0;
k = (k >> 1);
if(TH0 > 4)
{
k |= 0x80;
}
TH0 = 0;
}
codes[i] = k;
}
flag_recv = 1;
EA = 1;
}
void main()
{
IRIN = 1;
flag_recv = 0;
IR_init();
while(1)
{
if(flag_recv == 1)
{
flag_recv = 0;
if(codes[0] == 0x00)
{
RELAY = ~RELAY;
}
}
}
}
如果有需要判断某个按键按下后执行某个操作,可以根据codes数组中的码值进行判断。