原创 红外发射和接收的制作

2009-3-9 21:46 4200 12 12 分类: MCU/ 嵌入式

      最近发现一个比较浪费电的现象,很多家庭在看完电视后就直接按遥控器上的按钮关闭电视机(其实这样也是费电的,有的牌子的电视机在待机情况下的功耗可达20W,甚至更多),加上现在都是数字电视,有的人家是基本上不关机顶盒的,浪费电的情况很是严重。我自己家里看电视不太多,睡觉前也总是将电视机和机顶盒的电源关闭,电脑也总是在关机后按下总电源,不过最近连了局域网,经常是ADSL和路由器开一个晚上,夏天的话或许半夜起来关掉,但现在天越来越冷,不太高兴晚上起来关了,要想个办法才行了。


      其实要想在不用的情况下完全不费电,那就只有自己起来关电源了。不过我想只要降低功耗了,那东西就值得用。


      现在很多电器都是用红外遥控的,有专门的编码和解码,市场上也有卖一些万能的遥控器,可见其编码和解码有一定规则。




      为了使我们在关闭电脑的电源而不影响电视机、DVD等电器的使用,就必须考虑我们的编码不能和电视机遥控器的编码有冲突。也就是说我们要自己定义编码规则。这样一来,解码也就自己要做了。单片机就成了我们最好的选择了。




      现在单片机有很多种可共我们选择,51系列对初学者来说应该是比较好的选择之一,资料很多,烧写器也比较便宜。我们就用20 PIN的AT89C2051,它有15个I/O口,够了吧。现在无线发射也是比较流行的,毕竟红外是会因为遮挡而无法正常接收的,就用一个口用来无线发射,反正口多嘛,另外需要8个按键外加一个LED用来指示,这样还是有口剩余哦。




 


经过整理,发射的原理图如下:


20089221366189.jpg





TL0038是集红外线信号接收放大为一体的接收器。其中心接收频率为38KZH,输出为TTL电平,平时输出高电平,当收到码信号后,输出低电平。用来做为我们接收头正好,另外用4个口控制4个继电器,4个口控制4个LED对应指示,另再留一个无线接收的。。哈,AT98C2051的I/O口还是蛮多的。


下面是整理后的原理图:


200892213620799.jpg



花了点时间LAY好了板。。


发射的PCB:


200892212727474.jpg




接收的PCB:


200892212859724.jpg




这几天把板子做好了,下来逐个上传!


这次用感光板做的,线条效果比较好,下面是显影后的发射PCB这之前的工作没有拍下.可惜了)


200892213112947.jpg



显影后的接收PCB


200892213133125.jpg



再来两张腐蚀后的PCB


200892213220433.jpg


200892213247684.jpg




先说下发射的PCB,设计的时候在上面还有无线的发射线路,现在只调试红外发射部分.在调试的过程中发现,用单片机产生38KHz的频率并没有想象中那么顺利,笔者用C编译的,结果为了这个38KHz的频率也费了不少劲,后来在用示波器测了之后才调到了下图所示的频率:


点击看大图




如果用汇编的话可能就会剩力一些了.


再上张工作中的发射PCB


200892213357467.jpg



接收PCB焊好后的效果,没有焊继电器


200892213413970.jpg



工作时的发射和接收波形比较:


200892213428715.jpg



最后来张合影:


200892213445494.jpg



下面是发射的源程序,供大家参考..其实还有很多需要改的地方,现在发射的时间比较长,而且只是简单的发射一遍数据,没有判断是否正确的步骤,


//                  www.555diy.com                    //
// 名称:2051红外发射                                 //
// 版本:2051 TX 001-A                                //
// 日期:2008.07.06.                                  //
// 作者;ksysl                                        //


// 修改记录:            //
//                                                    //



// I/O口功能说明
// P32  红外DATA  低电平数据发射
// P33  红外38K载波
// P37  LED指示  高电平LED亮
// P10 ~ P17 按键



#include <reg51.h>


#define uchar unsigned char
#define uint  unsigned int


sbit h38k   = P3^3;     // 38k频率位
sbit h_data = P3^2;              // 发射红外数据位
sbit led    = P3^7;     // LED指示位


bit  key    = 0   ;     // 按键标志位


uchar sed_data    ;        // 发送的数据
uchar key_data    ;     // 按键判断用


void delay_ms(uchar time);   // 延时
void key_scan(void);    // 按键扫描
void h_data_send(void);    // 红外数据发送


//*****************************************************************//
//                      延时 开始
void delay_ms(uchar time)
{
 uchar i,j;
 for(i=0;i<20;i++)
 for(j=0;j<248;j++)
 for(;time>0;time--);

//                      延时 结束
//*****************************************************************//


//*****************************************************************//
//                      按键扫描开始
void key_scan(void)
{
 key_data=P1&0xff;
 if(key_data!=0xff)
   {
    delay_ms(5);
 if(key_data!=0xff)
   {
    switch(key_data)
      {
    case 0xfe: key="1";       //S8
               sed_data=0xfe;
      break;


    case 0xfd: key="1";       //S7
               sed_data=0xfd;
      break;


    case 0xfb: key="1";    //S6
               sed_data=0xfb;
      break;


    case 0xf7: key="1";    //S5
               sed_data=0xf7;
      break;


    case 0xef: key="1";    //S4
               sed_data=0xef;
      break;


    case 0xdf: key="1";    //S3
               sed_data=0xdf;
      break;


    case 0xbf: key="1";             //S2
               sed_data=0xbf;
      break;


    case 0x7f: key="1";             //S1
               sed_data=0x7f;
      break;


    default :  break;
   }
   }
   }
}
//                    按键扫描结束
//********************************************************************//


//********************************************************************//
//                    红外数据发送开始
void h_data_send(void)
{
 if(key==1)            // 按键标志位
   {
    uchar p;
    led =1;            // 亮LED
 h_data=0;                                // =0,三极管导通,让单片机开始接收数据
 delay_ms(5);          // 延时
 for(p=0;p<8;p++)                              // 发送8为数据
   {  
     h_data=(bit)(sed_data&0x80);
     delay_ms(4);  
     sed_data<<=1;  
   } 
   }
 h_data=1;            // 停止发射
 key=0;             // 关按键标志位
 led=0;              // 灭LED
}
//                    红外数据发送结束
//*********************************************************************//
          
//*********************************************************************//
//                    主程序 开始
main()
{
TMOD=0x01;        // 定时器0 工作方式1
TR0=1;         // 开定时器中断
ET0=1;


EA=1;         // 开总中断


//I/O口初始化
h38k=0;         // 38K 频率
h_data=1;        // 红外数据
key=0;
P1=0xff;
led=0;


while(1)
  {
   key_scan();
   h_data_send();
  }
}
//                   主程序 结束
//**********************************************************************//


//**********************************************************************//
//                   定时器0 产生38K频率 开始
void t0(void) interrupt 1
{
 TH0=0xff;           //
 TL0=0xfc;
 h38k=~h38k;       // 38k 频率产生
}
//                   定时器0 产生38K频率 结束
//**********************************************************************//


 


接收源程序..共大家参考..


 

//                  www.555diy.com                    //
// 名称:2051红外接收                                 //
// 版本:2051 RX 001-A                                //
// 日期:2008.07.06.                                  //
// 作者;ksysl                                        //


//修改记录:            //
//                                                    //


#include <reg51.h>


#define uchar unsigned char
#define uint  unsigned int


sbit int0 = P3^2;            // 红外数据接收口
sbit rx   = P3^7;      // LED
sbit int1 = P3^3;      //


sbit k1   = P1^7;      // 继电器1
sbit k2   = P1^5;      // 继电器2
sbit k3   = P1^3;      // 继电器3
sbit k4   = P1^1;      // 继电器4


sbit led1 = P1^6;      // 继电器1对应LED
sbit led2 = P1^4;      // 继电器2对应LED
sbit led3 = P1^2;      // 继电器3对应LED
sbit led4 = P1^0;      // 继电器4对应LED


uchar key;        // 数据处理标志位
uchar res_data;                // 接收到的红外数据


//***************************************************************//
//                      延时 开始
void delay_ms(uchar time)
{
 uchar i,j;
 for(i=0;i<20;i++)
 for(j=0;j<248;j++)
 for(;time>0;time--);

//                      延时 结束
//***************************************************************//


//***************************************************************//
//                      红外数据处理 开始
void data_scan(void)
{
 if(key==1)
   {
    switch(res_data)
      {
    case 0xfe:            //S8
               led1=1;
      k1=1;
      break;


    case 0xfd:           //S7
               led1=0;
      k1=0;
      break;


    case 0xfb:        //S6
               led2=1;
      k2=1;
      break;


    case 0xf7:        //S5
               led2=0;
      k2=0;
      break;


    case 0xef:        //S4
               led3=1;
      k3=1;
      break;


    case 0xdf:             //S3
               led3=0;
      k3=0;
      break;


    case 0xbf:                   //S2
               led4=1;
      k4=1;
      break;


    case 0x7f:                   //S1
               led4=0;
      k4=0;
      break;


    default : 
               break;
   }
  res_data=0;        //清红外数据
   }          
   delay_ms(10);        //延时
   rx="0";          //灭LED
   key="0"; 
}
//                     红外数据处理 结束
//********************************************************************//


//********************************************************************//
//                     红外数据接收 开始
void rx_data(void)
{
 uchar p="0";
 res_data=0;
 for(p=0;p<8;p++)
   {
     res_data<<=1;                // 接收到的数据左移一位
     if(int0==1)
       {
      res_data++;  
    }     
     delay_ms(4);   
   }
 rx=0;
 key=1;
}
//                      红外数据接收 结束
//********************************************************************//
          
//********************************************************************//
//                      主程序 开始
main()
{
TMOD=0x01;            // 定时器0 工作方式1
TR0=1;             // 开定时器中断
ET0=1;


EA=1;             // 开总中断


key=0; 
res_data=0;
P1=0x00;         //
rx=0;


while(1)
  {
   data_scan();
   if(int0==0)
     {
   rx="1";
   delay_ms(5);
   rx_data(); 
  }
  }
}
//                       主程序 结束
//**********************************************************************// 


//**********************************************************************//
//                       定时器0 开始
void t0(void) interrupt 1
{
 TH0=0xff;           //
 TL0=0xfc;
 int1=~int1;       //
}
//                       定时器0 结束
//**********************************************************************//


如有疑问可点击http://bbs.555diy.com/dispbbs.asp?boardID=13&ID=402&page=1参与讨论.

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
12
关闭 站长推荐上一条 /3 下一条