阿哲
发表于: 2015-12-11 23:20:01 | 显示全部楼层

最近在项目中添加了使用红外遥控的功能,可以在产品不打开盖的情况下修改参数。下面简单介绍一下基于NXP的LPC1752实现红外遥控的过程。

使用的红外接收器型号是ROHM的RPM7238-H8R,该型号的载波频率是 37.9KHZ。红外遥控分为两种编码方式:PWM编码(脉宽调制)和PPM编码(脉冲位置调制)。该型号采用的是PPM方式。关于这两种方式的不同,可以在网上搜索一下。PPM遥控编码脉冲由前导码、16位地址码(8位地址码、8 位地址码的反码)和16位操作码(8位操作码、8位操作码的反码)组成。

fsdf.jpg

PPM通过脉冲串之间的时间间隔来实现信号的调制。逻辑“0”是由0.56ms的38KHZ载波和0.560ms的无 载波间隔组成;逻辑“1”是由0.56ms的38KHZ载波和1.68ms的无载波间隔组成;结束位是0.56ms的38K载波。

asdfasdf.jpg

硬件原理图

红外接收器的输出引脚接到LPC1752的P0.3口,使用3.3V供电。下图是RPM7238与LPC1752的连接图。

02.jpg

红外接收器接收到红外线信号后,经过内部的放大、检波、整型后滤除了37.9KHz的载波,输出接收到的信号。下图是红外接收器的内部原理框图。

115.jpg

输出的有用信号与原PPM编码信号相反,如下图接收到的波形与对应输出波形:

202.jpg


程序介绍

项目中使用LPC1752的P0.3口连接到红外接收器,因此设定P0.3为输入引脚。每隔20uS读取红外接收器的引脚状态,RPM7238没有接收到红外信号时输出高电平,接收到红外信号的引导程序后,输出低电平,然后进入解码函数。

解码过程中共有六种状态:

  1. typedef enum _IR_STATE {
  2.         IR_STATE_IDLE,
  3.         IR_STATE_BOOT,
  4.         IR_STATE_RECV_HIGH,
  5.         IR_STATE_RECV_LOW,
  6.         IR_STATE_RECV_OK,
  7.         IR_STATE_ERROR
  8. } IR_STATE;
复制代码

IR_STATE_IDLE:空闲状态,等待接收红外遥控的引导程序

IR_STATE_BOOT:引导程序处理,如果引导程序持续时间4.5ms,则转到接收程序。如果持续时间是2.25ms,则判定为重复信号。

IR_STATE_RECV_HIGH:接收数据的高电平处理,等待数据的低电平

IR_STATE_RECV_LOW:接收数据的低电平处理,如果低电平持续时间等于1.5ms,则接收的数据为'1',如果持续的时间为0.5ms,则接收的数据为'0';

IR_STATE_RECV_OK:接收数据完成,置位标志位IRKey_Recv_Finished。

IR_STATE_ERROR:数据处理过程中出错,返回空闲状态。

以下代码是解码函数:

  1. void ReadIRKeyState()
  2. {
  3.         switch(IR_Recv_State)
  4.         {
  5.         case IR_STATE_IDLE: // idle, wait for boot code
  6.                 if( LPC_GPIO0->FIOPIN & (1ul << PIN_IR_KEY))
  7.                 {
  8.                         if( IRKey_Pin_Value_Count >= 425 )
  9.                         {
  10.                                 IR_Recv_State = IR_STATE_BOOT;
  11.                                 IRKey_Pin_Value_Count = 0;
  12.                         }
  13.                         else
  14.                         {
  15.                                 if( IRKey_Pin_Value_Count != 0 )
  16.                                 {
  17.                                         IRKey_Pin_Value_Count = 0;
  18.                                         IRKey_Recv_Count = 0;
  19.                                 }
  20.                         }
  21.                 }
  22.                 else
  23.                 {
  24.                         if( IRKey_Pin_Value_Count <= 1000)
  25.                                 IRKey_Pin_Value_Count++;
  26.                 }
  27.                 break;
  28.         case IR_STATE_BOOT: // boot code
  29.                 if( LPC_GPIO0->FIOPIN & (1ul << PIN_IR_KEY))
  30.                 {
  31.                         IRKey_Pin_Value_Count++;
  32.                         if( IRKey_Pin_Value_Count >= 250 )
  33.                         {
  34.                                 IR_Recv_State = IR_STATE_IDLE;
  35.                                 IRKey_Pin_Value_Count = 0;
  36.                         }
  37.                 }
  38.                 else
  39.                 {
  40.                         // check boot code either recv data or repeat code
  41.                         if(IRKey_Pin_Value_Count >= 200 && IRKey_Pin_Value_Count < 250)
  42.                         {
  43.                                 IRKey_Recv_State = 1;
  44.                                 IR_Recv_State = IR_STATE_RECV_LOW;
  45.                                 IRKey_Recv_Number = 0;
  46.                                 IRKey_Pin_Value_Count = 0;
  47.                                 IRKey_Recv_Count = 0;
  48.                         }
  49.                         else if(IRKey_Pin_Value_Count >= 85 && IRKey_Pin_Value_Count < 200)
  50.                         {
  51.                                 IRKey_Recv_Ready = 1;

  52.                                 if( IRKey_Recv_Count < 1000 )
  53.                                         IRKey_Recv_Count ++;
  54.                         }
  55.                         else
  56.                         {
  57.                                 IR_Recv_State = IR_STATE_IDLE;
  58.                                 IRKey_Pin_Value_Count = 0;
  59.                         }
  60.                 }
  61.                 break;
  62.         case IR_STATE_RECV_LOW: // recv data low
  63.                 if( LPC_GPIO0->FIOPIN & (1ul << PIN_IR_KEY))
  64.                 {
  65.                         if( IRKey_Pin_Value_Count >= 10 )
  66.                         {
  67.                                 IR_Recv_State = IR_STATE_RECV_HIGH;
  68.                                 IRKey_Pin_Value_Count = 0;
  69.                         }
  70.                         else
  71.                         {
  72.                                 IR_Recv_State = IR_STATE_IDLE;
  73.                                 IRKey_Pin_Value_Count = 0;
  74.                         }
  75.                 }
  76.                 else
  77.                 {
  78.                         IRKey_Pin_Value_Count++;
  79.                         if(IRKey_Pin_Value_Count >= 100 )
  80.                         {
  81.                                 IR_Recv_State = IR_STATE_IDLE;
  82.                                 IRKey_Pin_Value_Count = 0;
  83.                         }
  84.                 }
  85.                 break;
  86.         case IR_STATE_RECV_HIGH: // recv high
  87.                 if( LPC_GPIO0->FIOPIN & (1ul << PIN_IR_KEY))
  88.                 {
  89.                         IRKey_Pin_Value_Count++;
  90.                         if(IRKey_Pin_Value_Count >= 100 )
  91.                         {
  92.                                 IR_Recv_State = IR_STATE_IDLE;
  93.                                 IRKey_Pin_Value_Count = 0;
  94.                         }
  95.                 }
  96.                 else
  97.                 {
  98.                         if( IRKey_Recv_State == 1)
  99.                         {
  100.                                 IRKey_Recv_Value <<= 1;
  101.                                 if(IRKey_Pin_Value_Count >= 50 && IRKey_Pin_Value_Count < 85)
  102.                                         IRKey_Recv_Value += 1;
  103.                                 else if(IRKey_Pin_Value_Count >= 10 && IRKey_Pin_Value_Count < 50)
  104.                                         IRKey_Recv_Value += 0;

  105.                                 IRKey_Recv_Number++;
  106.                                 if( IRKey_Recv_Number >= 32)
  107.                                         IR_Recv_State = IR_STATE_RECV_OK;
  108.                                 else
  109.                                 {
  110.                                         IR_Recv_State = IR_STATE_RECV_LOW;
  111.                                         IRKey_Pin_Value_Count = 0;
  112.                                 }
  113.                         }
  114.                         else
  115.                         {
  116.                                 IR_Recv_State = IR_STATE_IDLE;
  117.                                 IRKey_Pin_Value_Count = 0;
  118.                         }
  119.                 }
  120.                 break;
  121.         case IR_STATE_RECV_OK:
  122.                 IRKey_Recv_Finished = 1;
  123.                 IR_Recv_State = IR_STATE_IDLE;
  124.                 IRKey_Pin_Value_Count = 0;
  125.                 break;
  126.         }
  127. }
复制代码

主函数每次查询该标志位,如果为1,则进入键值处理函数。接收数据的后16位是具体的键值。

  1. void IRKey_Recv_App()
  2. {
  3.         uint8_t Key_value;
  4.         uint8_t Recv_buf, Recv_buf_reverse;

  5.         if(IRKey_Recv_Finished == 1)
  6.         {
  7.                 IRKey_Recv_Finished = 0;

  8.                 Recv_buf = IRKey_Recv_Value >> 24;
  9.                 Recv_buf_reverse = (IRKey_Recv_Value >> 16) & 0xFF;
  10. //                if(Recv_buf == (uint8_t)~Recv_buf_reverse)
  11.                 if(Recv_buf == 0xE1 && Recv_buf_reverse == 0xA2)
  12.                 {
  13.                         Recv_buf = IRKey_Recv_Value >> 8;
  14.                         Recv_buf_reverse = IRKey_Recv_Value & 0xFF;
  15.                         if( Recv_buf == (uint8_t)~Recv_buf_reverse)
  16.                         {
  17.                                 Key_value = Recv_buf;
  18.                         }
  19.                 }
  20.         }
  21. }
复制代码
跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 53 | 回复: 76



手机版|

GMT+8, 2024-4-20 14:41 , Processed in 0.156412 second(s), 8 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

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