本实验的演示功能是通过对红外遥控键值解码后,对设定的目标键值做出响应,实验中的响应是单片机对继电器的开合、通断控制,可以简单理解为单片机检测到遥控器某个指定的按键按下,则控制继电器实现开关的切换功能
对单片机的了解学习,是作为简单的遥控器解码学习的基础,因为本次DIY是通过MCU作为解码媒介的。但实验中的DIY方式又不必需要功能强大的ARM系列单片机去实现,一般0851单片机就能解决。
本实验的演示功能是通过对红外遥控键值解码后,对设定的目标键值做出响应,实验中的响应是单片机对继电器的开合、通断控制,可以简单理解为单片机检测到遥控器某个指定的按键按下,则控制继电器实现开关的切换功能,实现过程如下:
Figure 1原理图
首先是选型,由于物资条件,我们考虑成本,
所以选择的都是廉价器件,器件有车载MP3红
外遥控,1318红外接收头,51系列的stc15F104w
芯片,一个11.0592MHZ的晶振,两个100pf的电
容,一个继电器,一个二极管1N4148,一个PNP三极管9012/S8550,两个200欧姆电阻。
其次是电路搭建,电路通过红外遥控接收头,将接收到的遥控编码信息发送至单片机,单片机对红外遥控的键值解码后在P3.5口输出控制信
号,控制继电器的开关效果。具体的电路原理图见
原理图所示。
最后,实现解码功能的51程序流程图如右图
所示:首先硬件上电,软件初始化外部中断,初始
化定时器配置,之后是不断地轮询单片机的中断引
脚,检测单片机的引脚状态是否改变,如果引脚状态被改变了,说明端口有数据到来,此时单片机的定时器将在中断中被激活。定时器被激活的作用是用来给给每个二进制数据位进行定时的,将高低电平状态产生的时间存储到一个数组里面,最后将该时间值数组转换成高低电平状态。
左图是红外遥控采集单片机中断引脚的高低电平时间,并将得到的时间放在irdate数组里,我们使用的红外遥控的编码是32位的编码。由引导码、用户码、数据码和数据码反码组成32位的编码方式。实验测试得到,引导码是有9ms的高电平和4.5ms的低电平组成。用户码或数据码中的每一个位可以是位‘1’,也可以是位‘0’。区分‘0’和‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式。英文简写PPM。其脉冲调制是使用455KHz晶体产生的载波脉冲实现。
总结:通过本次实验,了解到了红外遥控编码及解码的工作原理。并实践应用51单片机解码实现继电器的吸合开关电路控制。实验中用到了单片机的外部中断配置和单片机的定时器配置。
具体代码如下
hwjm.c
#include<stc15f104w.h>
#include"hwjm.h"
#include"delay.h"
#include"music.h"
uchar irreceok;//一整数据接收完毕
uchar irprosok;
unsigned char b;
extern unsigned char b;
//uchar irtime,irtime1;//第一步时间存储
uchar irtime; //第一步时间存储
uchar startflag;
uchar bitnum;
uchar ircode[4];
extern unsigned char Count;
extern uchar smg_gyangji[];
//uchar display[8];
uchar irdate[33];//接收数组此为一些时间变量;0.25ms或者2.256ms
uchar anjianjiema[]={0x16,0x0c,0x18,0x5e,0x08,0x1c,0x5a,0x42,0x52,0x4a};//0-7;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
//uchar smg_gyangji[]={
//0xC0,0xF9,0xA4,0xB0,
//0x99,0x92,0x82,0xF8,
//0x80,0x90,0x88,0x83,
//0xC6,0xA1,0x86,0x8E
//};
//////////////红外接收到数据的数据函数////////////////////////
void hwxm_irrece(void)
{
if(startflag)//第一次红外数据为引导码不起作用所以startflag为0直接跳过
{
if(irtime>30)//检测引导吗;
{
bitnum=0;
}
irdate[bitnum]=irtime;//存的是时间0.25/0.256或是2.25/0.256时刻提取计时器实计数
irtime=0;
bitnum++;//红外接收数据数组下标每次检测到一次下降沿引发中断时加一
if(bitnum==33)//
{
bitnum=0;
irreceok=1;//档主函数判断是否当一次红外数据发送并接收完毕
}
}
else
{
startflag=1;//中断触发后中断标志变量startflag将一直为1;
irtime=0;
}
}
void hwxm_irpros(void)
{
uchar k,i,j;
uchar value;
k=1;//只提取用户吗;4*8=32位;
for(j=0;j<4;j++)//四个码
{
for(i=0;i<8;i++)//每个码有8位
{
value=value>>1;//7ci第一次vlalue等于0右移后等于0;
if(irdate[k]>6)
{
value=value | 0x80;//10000000
}
k++;
}
ircode[j]=value;//为2进制
}
irprosok=1;//对时间转化成2进制的转换完毕;
}
int.c
#include<stc15f104w.h>
#include"int.h"
#include"hwjm.h"
extern uchar ircode[4];
extern unsigned char Count;
unsigned char Temp2;
sfr T2MOD=0xc9;
void timer0init(void) //计时器零初始化
{
EA=1;
ET0=1;
TH0=0X00;
TL0=0X00;//工作方式0
TMOD=0X02;
TR0=1;
}
void timer1init(void) //计时器1初始化//最大值是255
{
EA=1;
ET1=1;
T2H=0XDC;
T2L=0X00;
T2MOD=0X02;//工作方式2,8位初值自动重装8位定时器/计数器
TR1=1;
}
void int0init(void)//中断0初始化函数
{
EA=1;
EX0=1;
IT0=1; //为跳变触发方式,电平从高到低的负跳变有效IT0=0时为低电平有效的电平触发方式
}
////////////////////////////////////////////////////////////////////////
///////////计时器0服务函数//////////////////
void timer0() interrupt 1
{
irtime++;
}
void timer1() interrupt 3
{
TH1 = 0xDC;
TL1 = 0x00;
Count++;
}
///////中断服务函数////////////////
void int0 () interrupt 0//外部中断 服务函数
{
hwxm_irrece();
hwxm_irpros();
if(ircode[2]==0x45||ircode[2]==0x47)
Temp2 = Count;
}
main.c
#include<stc15f104w.h>
#include"delay.h"
#include"music.h"
#include"hwjm.h"
#include"int.h"
///////////////////////////////
extern unsigned char b;
extern uchar ircode[4];
extern uchar smg_gyangji[];
extern uchar anjianjiema[];
unsigned char Count;
extern uchar irreceok;//一整数据接收完毕
extern uchar irprosok;
sbit JD=P3^0;
sbit D=P3^1;
void main(void)
{
timer1init();
timer0init();
int0init();
P0=0xff;
while(1)
{
unsigned char b;
if(irreceok)//判断总中断服务函数中对接收时间的存储是否接收完眎rreceok为接收完毕标志位;
{
hwxm_irpros();//解码服务函数;将时间间隔大小转换成16进制数
irreceok=0;//解码是否完毕;
}
if(irprosok)
{
irprosok=0;//对时间做出相应的十六进制转化完成标志清零;
for(b=0;b<10;b++)
{
if(ircode[2]==anjianjiema[b])
{
delay_50us(2);
if(ircode[2]==anjianjiema[0])
{
JD=1;
D=1;
}
else
{
JD=0;
D=0;
}
}
}
}
}
}