分享

用AT89S51单片机制作红外电视遥控器

 共同成长888 2019-12-30
   一般红外电视遥控器的输出都是用编码后串行数据对38~40kHz的方波进行脉冲幅度调制而产生的。
  当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:
  采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”。
  上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制,然后再通过红外发射二极管产生红外线向空间发射。一般电视遥控器的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。后16位为8位的操作码和8位的操作反码,用于核对数据是否接收准确。
  根据红外编码的格式,发送数据前需要先发送9ms的起始码和4.5ms的结果码。
  遥控串行数据编码波形如下图所示:

  接收方一般使用TL0038一体化红外线接收器进行接收解码,当TL0038接收到38kHz红外信号时,输出端输出低电平,否则为高电平。所以红外遥控器发送红外信号时,参考上面遥控串行数据编码波形图,在低电平处发送38kHz红外信号,高电平处则不发送红外信号。
  单片机红外电视遥控器电路图如下:

C51程序代码:
  1. #include<reg52.h>

  2. static bit OP;        //红外发射管的亮灭
  3. static unsigned int count;       //延时计数器
  4. static unsigned int endcount; //终止延时计数
  5. static unsigned char flag;      //红外发送标志
  6. char iraddr1;  //十六位地址的第一个字节
  7. char iraddr2;  //十六位地址的第二个字节

  8. void SendIRdata(char p_irdata);
  9. void delay();

  10. void main(void)
  11. {
  12.   count = 0;
  13.   flag = 0;
  14.   OP = 0;
  15.   P3_4 = 0;

  16.   EA = 1; //允许CPU中断
  17.   TMOD = 0x11; //设定时器0和1为16位模式1
  18.   ET0 = 1; //定时器0中断允许


  19.   TH0 = 0xFF;
  20.   TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
  21.   TR0 = 1;//开始计数

  22.   iraddr1=3;
  23.   iraddr2=252;


  24.   do{
  25.       delay();
  26.       SendIRdata(12);
  27.   }while(1);
  28. }

  29. //定时器0中断处理
  30. void timeint(void) interrupt 1
  31. {
  32.   TH0=0xFF;
  33.   TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次
  34.   count++;

  35.   if (flag==1)
  36.   {
  37.     OP=~OP;
  38.   }
  39.   else
  40.   {
  41.     OP = 0;
  42.   }
  43.   P3_4 = OP;
  44. }


  45. void SendIRdata(char p_irdata)
  46. {
  47.   int i;
  48.   char irdata=p_irdata;

  49.   //发送9ms的起始码
  50.   endcount=223;
  51.   flag=1;
  52.   count=0;
  53.   do{}while(count<endcount);

  54.   //发送4.5ms的结果码
  55.   endcount=117
  56.   flag=0;
  57.   count=0;
  58.   do{}while(count<endcount);

  59.   //发送十六位地址的前八位
  60.   irdata=iraddr1;
  61.   for(i=0;i<8;i++)
  62.   {

  63.      //先发送0.56ms的38KHZ红外波(即编码中0.56ms的低电平)
  64.      endcount=10;
  65.      flag=1;
  66.      count=0;
  67.      do{}while(count<endcount);

  68. //停止发送红外信号(即编码中的高电平)
  69.      if(irdata-(irdata/2)*2)  //判断二进制数个位为1还是0
  70.      {
  71.        endcount=41;  //1为宽的高电平
  72.      }
  73.     else
  74.      {
  75.      endcount=15;   //0为窄的高电平
  76.      }
  77.     flag=0;
  78.     count=0;
  79.     do{}while(count<endcount);

  80.     irdata=irdata>>1;
  81.   }

  82.   //发送十六位地址的后八位
  83.   irdata=iraddr2;
  84.   for(i=0;i<8;i++)
  85.   {
  86.      endcount=10;
  87.      flag=1;
  88.      count=0;
  89.      do{}while(count<endcount);

  90.      if(irdata-(irdata/2)*2)
  91.      {
  92.         endcount=41;
  93.      }
  94.      else
  95.      {
  96.        endcount=15;
  97.      }
  98.      flag=0;
  99.      count=0;
  100.      do{}while(count<endcount);

  101.      irdata=irdata>>1;
  102.   }

  103.   //发送八位数据
  104.   irdata=p_irdata;
  105.   for(i=0;i<8;i++)
  106.   {
  107.      endcount=10;
  108.      flag=1;
  109.      count=0;
  110.      do{}while(count<endcount);

  111.      if(irdata-(irdata/2)*2)
  112.      {
  113.          endcount=41;
  114.      }
  115.      else
  116.      {
  117.        endcount=15;
  118.      }
  119.      flag=0;
  120.      count=0;
  121.      do{}while(count<endcount);

  122.      irdata=irdata>>1;
  123.   }

  124.   //发送八位数据的反码
  125.   irdata=~p_irdata;
  126.   for(i=0;i<8;i++)
  127.   {
  128.      endcount=10;
  129.      flag=1;
  130.      count=0;
  131.      do{}while(count<endcount);

  132.      if(irdata-(irdata/2)*2)
  133.      {
  134.          endcount=41;
  135.      }
  136.      else
  137.      {
  138.        endcount=15;
  139.      }
  140.      flag=0;
  141.      count=0;
  142.      do{}while(count<endcount);

  143.      irdata=irdata>>1;
  144.   }

  145.   endcount=10;
  146.   flag=1;
  147.   count=0;
  148.   do{}while(count<endcount);
  149.   flag=0;
  150. }

  151. void delay()
  152. {
  153.   int i,j;
  154.   for(i=0;i<400;i++)
  155.   {
  156.     for(j=0;j<100;j++)
  157.     {
  158.     }
  159.   }
  160. }
复制代码



  制作的实物如下图所示:

//STC的为
  1. #include<reg52.h>

  2. static bit OP;        //红外发射管的亮灭
  3. static unsigned int count;       //延时计数器
  4. static unsigned int endcount; //终止延时计数
  5. static unsigned char flag;      //红外发送标志
  6. char iraddr1;  //十六位地址的第一个字节
  7. char iraddr2;  //十六位地址的第二个字节
  8. sbit  HOP=P3^4;

  9. void SendIRdata(char p_irdata);
  10. void delay();

  11. void main(void)
  12. {
  13.   count = 0;
  14.   flag = 0;
  15.   OP = 0;
  16.   HOP = 0;

  17.   EA = 1; //允许CPU中断
  18.   TMOD = 0x11; //设定时器0和1为16位模式1
  19.   ET0 = 1; //定时器0中断允许


  20.   TH0 = 0xFF;
  21.   TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
  22.   TR0 = 1;//开始计数

  23.   iraddr1=3;
  24.   iraddr2=252;


  25.   do{
  26.       delay();
  27.       SendIRdata(12);
  28.   }while(1);
  29. }

  30. //定时器0中断处理
  31. void timeint(void) interrupt 1
  32. {
  33.   TH0=0xFF;
  34.   TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次
  35.   count++;

  36.   if (flag==1)
  37.   {
  38.     OP=~OP;
  39.   }
  40.   else
  41.   {
  42.     OP = 0;
  43.   }
  44.   HOP = OP;
  45. }


  46. void SendIRdata(char p_irdata)
  47. {
  48.   int i;
  49.   char irdata=p_irdata;

  50.   //发送9ms的起始码
  51.   endcount=223;
  52.   flag=1;
  53.   count=0;
  54.   do{}while(count<endcount);

  55.   //发送4.5ms的结果码
  56.   endcount=117;
  57.   flag=0;
  58.   count=0;
  59.   do{}while(count<endcount);

  60.   //发送十六位地址的前八位
  61.   irdata=iraddr1;
  62.   for(i=0;i<8;i++)
  63.   {

  64.      //先发送0.56ms的38KHZ红外波(即编码中0.56ms的低电平)
  65.      endcount=10;
  66.      flag=1;
  67.      count=0;
  68.      do{}while(count<endcount);

  69. //停止发送红外信号(即编码中的高电平)
  70.      if(irdata-(irdata/2)*2)  //判断二进制数个位为1还是0
  71.      {
  72.        endcount=41;  //1为宽的高电平
  73.      }
  74.     else
  75.      {
  76.      endcount=15;   //0为窄的高电平
  77.      }
  78.     flag=0;
  79.     count=0;
  80.     do{}while(count<endcount);

  81.     irdata=irdata>>1;
  82.   }

  83.   //发送十六位地址的后八位
  84.   irdata=iraddr2;
  85.   for(i=0;i<8;i++)
  86.   {
  87.      endcount=10;
  88.      flag=1;
  89.      count=0;
  90.      do{}while(count<endcount);

  91.      if(irdata-(irdata/2)*2)
  92.      {
  93.         endcount=41;
  94.      }
  95.      else
  96.      {
  97.        endcount=15;
  98.      }
  99.      flag=0;
  100.      count=0;
  101.      do{}while(count<endcount);

  102.      irdata=irdata>>1;
  103.   }

  104.   //发送八位数据
  105.   irdata=p_irdata;
  106.   for(i=0;i<8;i++)
  107.   {
  108.      endcount=10;
  109.      flag=1;
  110.      count=0;
  111.      do{}while(count<endcount);

  112.      if(irdata-(irdata/2)*2)
  113.      {
  114.          endcount=41;
  115.      }
  116.      else
  117.      {
  118.        endcount=15;
  119.      }
  120.      flag=0;
  121.      count=0;
  122.      do{}while(count<endcount);

  123.      irdata=irdata>>1;
  124.   }

  125.   //发送八位数据的反码
  126.   irdata=~p_irdata;
  127.   for(i=0;i<8;i++)
  128.   {
  129.      endcount=10;
  130.      flag=1;
  131.      count=0;
  132.      do{}while(count<endcount);

  133.      if(irdata-(irdata/2)*2)
  134.      {
  135.          endcount=41;
  136.      }
  137.      else
  138.      {
  139.        endcount=15;
  140.      }
  141.      flag=0;
  142.      count=0;
  143.      do{}while(count<endcount);

  144.      irdata=irdata>>1;
  145.   }

  146.   endcount=10;
  147.   flag=1;
  148.   count=0;
  149.   do{}while(count<endcount);
  150.   flag=0;
  151. }

  152. void delay()
  153. {
  154.   int i,j;
  155.   for(i=0;i<400;i++)
  156.   {
  157.     for(j=0;j<100;j++)
  158.     {
  159.     }
  160.   }
  161. }
复制代码



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多