4.4 51单片机-NEC红外线遥控器解码

举报
DS小龙哥 发表于 2021/12/09 22:14:36 2021/12/09
【摘要】 4.4  NEC红外线遥控器解码 4.4.1 接收头原理图介绍 图4-4-1 实验板上的红外线接收头是接在单片机的P3.2 IO口上,要使用红外线接收功能,需要将红外线接收头的跳线帽接上。 图4-4-2 4.4.2 NEC红外线协议介绍 红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置...

4.4  NEC红外线遥控器解码

4.4.1 接收头原理图介绍

图4-4-1

实验板上的红外线接收头是接在单片机的P3.2 IO口上,要使用红外线接收功能,需要将红外线接收头的跳线帽接上。

图4-4-2

4.4.2 NEC红外线协议介绍

红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。

红外线是波长介于微波和可见光之间的电磁波,波长在 760 纳米到 1 毫米之间,是波形比红光长的非可见光

家电遥控器通信距离往往要求不高,而红外的成本比其它无线设备要低的多,所以家电遥控器应用中红外始终占据着一席之地。遥控器的基带通信协议很多,大概有几十种,常用的就有 ITT 协议、 NEC 协议、 Sharp 协议、 Philips RC-5 协议、 Sony SIRC 协议等。用的最多的就是 NEC 协议了,本小节以 NEC协议标准进行讲解,实验板自带的遥控器也是NEC协议的。

NEC协议,通常是使用 38K左右的载波进行调制,再发送的;这里的调制就是用待传送信号去控制某个高频信号的幅度、相位、频率等参量变化的过程,即用一个信号去装载另一个信号。比如:我们的红外遥控信号要发送的时候,先经过 38K 调制。

图4-4-3 信号调制示例

原始信号就是要发送的一个数据“0”位或者一位数据“1”位,而38K 载波就是频率为 38K 的方波信号,调制后信号就是最终我们发射出去的波形。使用原始信号来控制 38K 载波,当信号是数据“0”的时候, 就发送38K载波,当信号是数据“1”的时候,就不发送任何载波信号,那么数据接收方只需要检测是否收到38KHZ的载波就行判断是否收到了数据。实验板上带了一个一体化接收头HS0038B,可以识别38KHZ的载波信号,当HS0038B收到38KHZ载波就输出低电平,没有收到38KHZ载波就输出高电平;程序就可以判断HS3008的引脚电平配合指定的协议格式来分析收到的数据。

图4-4-4 红外线接收头

NEC协议的数据格式包括了引导码、用户码、用户码反码、按键码、按键反码

其中数据编码总共是4个字节 32 位(除了引导码外就是数据位),数据格式中的反码用于数据校验,可以判断数据在传输过程中有没有丢包。

图4-4-5 NEC协议传输格式

NEC协议解码总结:

引导码:9ms的低电平+4.5ms的高空闲。

逻辑 1:  560us 低+1680us 高电平

逻辑 0:  应该是 560us 低+560us 高电平。

遥控接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平。

红外线遥控器向红外线接收头按下一个按键之后,红外线接收头先收到的是9ms的高电平脉冲,接着是4.5ms的低电平,之后就是接收8bit的用户码、8bit的用户码的反码,8bit 的按键码,8bit 的按键码的反码。如果一直按着1个键,这样遥控器发送的是以110ms为周期的重复码,就是说,发了一次按键码之后,不会再发送按键码,而是每隔110ms时间,发送一段重复码,重复码由9ms高电平和2.25ms的低电平以及560us的高电平组成。

4.4.3 采集NEC协议的信号

为了更加直观的理解NEC协议格式,可以使用逻辑分析仪或者示波器采集HS0038红外线接收头收到的数据,再通过软件分析收到的数据。

 图4-4-6 逻辑分析采集的NEC数据

 

图4-4-7 逻辑分析采集过程

逻辑分析仪软件下载地址: Logic analyzer software from Saleae

图4-4-8 逻辑分析软件

4.4.4 NEC红外线协议解码示例

下面代码采用定时器+外部中断的方式解码红外线数据,外部中断采用外部中断0,接在P3.2口上,配置外部中断0的触发方式为下降沿触发。

解码思路: 红外线接收头没有收到38KHZ方波时,默认输出高电平,当收到38KHZ方波时输出低电平,这时就触发了下降沿,接着就进入到外部中断0 的中断服务函数;解码的过程就在中断服务函数里实现,高低电平的持续时间通过定时器0进行计数,当前实验板的晶振是12MHZ,刚好定时器的计数器+1的时间就是1us,配置定时器0的工作方式为16位模式,最大计数可以到65535,NEC协议最长的一段时间也就9000us,完全满足需求;解码完成之后设置标志位,在主函数里将解码的数据通过串口打印出去。

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:


  
  1. #include <reg51.h>
  2. u8 Infrared_RX_Flag=0//红外接收标志,收到一帧正确数据后置1
  3. u8 Infrared_RX_Buff[4];//红外代码接收缓冲区
  4. sbit Infrared_GPIO=P3^2;//红外接收引脚--外部中断0
  5. /*
  6. 函数功能: 开始红外线解码之前的相关初始化
  7. 实验板的晶振频率是12MHZ
  8. 51单片机标准架构下一个机器周期是12个时钟周期,如果晶振频率是12MHZ,那一个机器周期的时间就是12/12微秒。
  9. 也就是说定时器的计数器+1的时间就是12/12=1us。
  10. */
  11. void Infrared_Init(void)
  12. {  
  13.    Infrared_GPIO=1;//红外接收引脚默认保持高电平输出
  14.    TMOD&=0xF0//清除配置  
  15.    TMOD|=0x01//配置定时器0,工作在16位计数模式
  16.    TR0=0;      //停止定时器0计数
  17.    ET0=0;       //禁止定时器0中断
  18.    IT0=1;      //开启外部中断0,下降沿触发
  19.    EX0=1;      //允许外部中断0中断
  20. }
  21. /*
  22. 函数功能: 检测高电平持续的时间
  23. */
  24. u16 Infrared_GetTimeH(void)
  25. {
  26.    TH0=0//定时器0重装值为0
  27.    TL0=0//定时器0重装值为0
  28.    TR0=1//启动定时器0开始计数
  29.    while(Infrared_GPIO)//等待高电平结束
  30.    {
  31.       if(TH0>0x40)//防止超时   
  32.       {
  33.          break;
  34.       }
  35.    }
  36.    TR0=0;//停止定时器0计数
  37.    return TH0<<8|TL0;//T0计数值合成为16位整数返回
  38. }
  39. /*
  40. 检测低电平持续的时间
  41. */
  42. u16 Infrared_GetTimeL(void)
  43. {
  44.    TH0=0;//定时器0的高8位重装值
  45.    TL0=0;//定时器0的低8位重装值  
  46.    TR0=1;//开启定时器0
  47.    while(Infrared_GPIO==0)//等待低电平结束
  48.    {
  49.       if(TH0>0x40)//防止超时   
  50.       {
  51.          break;
  52.       }
  53.    }
  54.    TR0=0;//停止定时器0计数
  55.    return TH0<<8|TL0;//T0计数值合成为16位整数返回
  56. }
  57. /*
  58. 外部中断0中断服务函数
  59. */
  60. void EXTI0_IRQHandler() interrupt 0
  61. {
  62.    u8 i, j;
  63.    u16 time;
  64.    u8 byte;
  65.    time=Infrared_GetTimeL();   //获取出现低电平的时间
  66.    if((time<7800)||(time>9300))//判断低电平时间是否符合9ms范围
  67.    {                           //超过此范围则说明为误码,直接退出
  68.       IE0=0;                  //清除外部中断0中断标志
  69.       return;  
  70.    }
  71.    time=Infrared_GetTimeH();   //获取出现高电平的时间
  72.    if((time<3500)||(time>4700))//高电平是否符合4.5ms范围
  73.    {                           //超过此范围则说明为误码,直接退出
  74.       IE0=0;                //清除外部中断0中断标志
  75.       return;
  76.    }
  77.    //接收32位数据位
  78.    for(i=0;i<4;i++)
  79.    {
  80.       for(j=0;j<8;j++)
  81.       {
  82.          time=Infrared_GetTimeL();   //获取低电平持续时间,标准的间隔时间为560us范围                    
  83.          if((time<300)||(time>700))  //判断范围是否合理
  84.          {
  85.             IE0=0;//清除外部中断0中断标志
  86.             return;
  87.          }
  88.             //1和0是靠高电平持续的长短来区分的
  89.          time=Infrared_GetTimeH();  //获取高电平持续时间
  90.          if(time>300&&time<700)    //0的标准时间为560us
  91.          {
  92.             byte>>=1;
  93.          }
  94.             else if(time>1400&&time<1800//1的标准时间是1680us
  95.          {
  96.             byte>>=1;
  97.             byte|=0x80;
  98.          }
  99.          else //不在上面的判断范围内说明是错误码,直接退出
  100.          {
  101.             IE0=0;//清除外部中断0中标
  102.             return;
  103.          }
  104.       }
  105.       Infrared_RX_Buff[i]=byte;//接收完一个字节后保存到缓冲区
  106.    }
  107.    Infrared_RX_Flag=1;//接收完毕后设置标志
  108.    IE0=0;//退出前清除外部中断0中断标志
  109. }
  110. int main()
  111. {
  112.     UART_Init();        //初始化串口波特率为4800
  113.     Infrared_Init();    //初始化红外功能
  114.     while(1)
  115.     {
  116.         if(Infrared_RX_Flag)          //接收到红外数据
  117.         {
  118.             Infrared_RX_Flag=0;     //清楚标志
  119.             printf("user1:%d,user2:%d\r\n",(int)Infrared_RX_Buff[0],(int)((u8)(~Infrared_RX_Buff[1])));
  120.             printf("key1:%d,key2:%d\r\n",(int)Infrared_RX_Buff[2],(int)((u8)(~Infrared_RX_Buff[3])));
  121.         } 
  122.     }
  123. }

文章来源: xiaolong.blog.csdn.net,作者:DS小龙哥,版权归原作者所有,如需转载,请联系作者。

原文链接:xiaolong.blog.csdn.net/article/details/121031252

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。