找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19951|回复: 15
收起左侧

单片机红外发射程序与原理详解

  [复制链接]
ID:438751 发表于 2018-12-3 21:25 | 显示全部楼层 |阅读模式
用AT89S51单片机制作红外电视遥控器

制作的实物如下图所示:


  一般红外电视遥控器的输出都是用编码后串行数据对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红外信号,高电平处则不发送红外信号。
  单片机红外电视遥控器电路图如下:

单片机程序源码:
  1. #include <AT89X51.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. }
复制代码

以上的Word格式文档51黑下载地址:
单片机红外发射(原理与设计程序).doc (126.5 KB, 下载次数: 199)

评分

参与人数 1黑币 +10 收起 理由
z72287 + 10 赞一个!

查看全部评分

回复

使用道具 举报

ID:661763 发表于 2019-12-26 15:33 | 显示全部楼层
有没有用单片机发送矩阵开关红外信号的程序
回复

使用道具 举报

ID:227603 发表于 2020-1-18 15:42 | 显示全部楼层
大神,请问为什么 endcount=223是9ms  endcount=10时是0.56ms。定时器不是26us一次吗?算迷糊了呀。自学的很多都不懂,务鄙视呀。
回复

使用道具 举报

ID:258566 发表于 2020-1-18 20:35 | 显示全部楼层
逻辑分析仪1.PNG
实测接收头处的波形,
回复

使用道具 举报

ID:159575 发表于 2020-1-27 18:45 来自手机 | 显示全部楼层
直接驱动?没用三极管
回复

使用道具 举报

ID:253767 发表于 2020-1-28 07:58 | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

ID:735528 发表于 2020-5-14 09:18 | 显示全部楼层
你好 在keil上编译出错 错误信息
回复

使用道具 举报

ID:735528 发表于 2020-5-14 09:19 | 显示全部楼层
你好 在keil上编译出错 错误信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c...
AAG.C(59): error C141: syntax error near 'flag'
Target not created
回复

使用道具 举报

ID:919701 发表于 2021-5-11 22:03 | 显示全部楼层
1239225803 发表于 2020-5-14 09:19
你好 在keil上编译出错 错误信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c. ...

你不会一点C的语法纠错都不会吧
回复

使用道具 举报

ID:885138 发表于 2021-5-12 12:55 来自手机 | 显示全部楼层
cccc888 发表于 2020-1-18 20:35
实测接收头处的波形,

这是用什么工具测试的啊
回复

使用道具 举报

ID:919701 发表于 2021-5-14 17:03 | 显示全部楼层
我验证过了,这个代码不行
回复

使用道具 举报

ID:740383 发表于 2021-5-19 11:44 | 显示全部楼层
楼主用的是40us溢出,上面是223,117等等...都有重新核算一次,就可以正常运行了
回复

使用道具 举报

ID:577423 发表于 2021-6-27 10:32 | 显示全部楼层
1239225803 发表于 2020-5-14 09:19
你好 在keil上编译出错 错误信息:Build target 'Target 1'
assembling STARTUP.A51...
compiling aag.c. ...

flag附近少了一个分号而已,自己好好看看,不动点脑子不行的
回复

使用道具 举报

ID:887202 发表于 2021-6-29 18:48 | 显示全部楼层
红外信号编码的方式有很多种,楼主说明的只是其中最常见的一种,一般称为NEC,还有其他很多种不同的编码,编码方式不同,解码的方式自然也就不同,所以应用的时候还是要看具体时哪一种编码方式
回复

使用道具 举报

ID:194006 发表于 2021-8-2 16:07 | 显示全部楼层
实验发现, 采用12M的晶振,中断最少要20us,也就是周期最少要40us了,所以楼主的程序算法上是40us溢出.
如果采用24M晶振,就可以13us中断,产生周期为26us的38K载波.
所以要采用24M晶振.不然速度不够.
回复

使用道具 举报

ID:488937 发表于 2022-2-22 22:03 | 显示全部楼层
大师为什么用的两个晶振 那个左边那个小IC是干啥的呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表