专注电子技术学习与研究
当前位置:单片机教程网 >> STM32 >> 浏览文章

射频遥控:射频遥控接收及解码(对PT2622及EV1527进行有效解码)

作者:未知   来源:Rainbow开源硬件   点击数:  更新时间:2014年06月21日   【字体:

  前两天用软件实现了EV1527及PT2622射频编码功能,周末在家闲来无事,我就琢磨用软件来实现射频编码接收并对PT2622和EV1527格式的编码进行解析,说干就干,周天上午一早就开始,晚上也是边看电视边做,经过一天的努力,终于在睡觉前完整了主要程序的编写,周一又花了些时间来检查,最后终于搞定。

 
    这次我用的是315M无线接收模块,就是这种的模块:

    按照资料说明这个模块需要5V供电,我本来还担心3.3V下面可能不工作,不过实践证明,是可行的。将这个模块的DATA管脚接到开发板的PA8,PA8是TIM1的CH1,对于射频遥控编码的采集我用了定时器的PWM捕获功能,这点和红外遥控编码采集方式类似,不同之处在于,红外遥控编码用的是下降沿触发采集,而射频遥控编码采用的上升沿触发进行采集。还有一点特别重要:红外遥控编码接收模块HX1838在平时没有收到红外信号的时候是高电平,当收到信号过后才产生脉冲,但是射频采用电磁波进行传输,而平时我们所在的空间中存在各种电磁波,所以即便没有信号的时候,也会出现不规则的波形输入,我们需要做的就是将有用的信号从各种干扰信号中提取出来,这一点是与红外遥控编码接收的最大不同。
 
    将有用的射频遥控编码信号从杂波中提取出来还是比较容易的,射频遥控的一个字码是由同步编码+地址码+数据码构成,我们只需要甄别出同步码,然后从同步码开始进行波形采集即可。射频编码一般一次至少发送4个以上的字码,由于无线传输过程中可能出现干扰信号,导致信号失真,因此我们必须对收到的多个字码进行验证,保证至少有两个以上的连续字码相同,这一点也是和红外遥控编码提取的最大不同。
 
    经过过滤杂波、验证有效的射频遥控编码之后,我们就可以得到一个有效的射频编码原始数据,接下来我们就需要判断是EV1527还是PT2622以及其它类型的编码,除了EV1527和PT2622之外的编码暂时不支持解码,只保留了原始采集的时长数据,而EV1527和PT2622的编码都是由50个高低电平来表示的,怎么样进行区分呢?
 
    PT2622是用两个脉冲来表示一个位,有0,1,F三种状态:两个窄脉冲表示0,两个宽脉冲表示1,一个窄脉冲+一个宽脉冲表示F;而EV1527用一个脉冲来表示0和1:窄脉冲表示0,宽脉冲表示1。所以在PT2622编码中不可能出现一个宽脉冲+窄脉冲的组合,通过这个特征就可以很方便将两种编码进行区分。进行了编码区分之后,接下来的事情就比较简单了,只需要根据两种编码格式的规则进行解析,得到真实的二进制编码即可。
 
    根据上述原理,我编写了一个类RFRecv,这个类里面封装了射频编码采集、解码的功能;同时又对之前编写的PT2622和EV1527编码程序进行了封装,写了一个类RFSend,用于实现对原始编码时长数据发送、EV1527和PT2622进行编码发送的功能。
 
    在软件包的“Projects\RF-Recv”文件夹包含了射频接收的完整工程,可以直接编译、烧写和调试。程序代码如下:
#include "WProgram.h"
#include "RFRemote.h"
 
//创建射频遥控接收实例,射频接收模块接到TIM1的CH1,即:PA8
RFRecv rfRecv;
 
void setup()
{
  //初始化默认串口
  Serial.begin();
 
  rfRecv.enableRFIn();
  Serial.println("RFRemote start...");
}
 
void loop()
{
  uint16_t* rawBuf;
  int16_t len = rfRecv.available();
  //判断射频遥控编码采集是否完成
  if(len > 0)
  {
    //取采集的原始编码
    awBuf = rfRecv.getRawCode();
    //将接收到的原始编码通过默认串口输出
    Serial.print("Frame Length:");
    Serial.print(len);
    Serial.println();
    for(uint16_t i=0; i
    {
      Serial.print(rawBuf[i]);
      if(i != len - 1)
      {
        Serial.print(",");
      }
    }
    Serial.println();
    if(rfRecv.decode())
    {
      Serial.println("RF decode success...");
      uint8_t codeType = rfRecv.getCodeType();
      uint32_t adValue = rfRecv.getADValue();
      //二进制方式显示解码结果
      Serial.print("RF adValue:");
      Serial.println(adValue, 16);
 
      if(codeType == 1)
      {
          Serial.println("Code Type: PT2622" );
          //12位数据中,地址为占8位,数据占4位
          Serial.print("Address: " );
          Serial.println(PT2622::parseAddress(adValue, 8), 16);
          Serial.print("Data: " );
          Serial.println(PT2622::parseData(adValue, 8), 16);
        }
        else if(codeType == 2)
        {
          Serial.println("Code Type: EV1527" );
          //24位数据中,地址占20为,数据占4位
          Serial.print("Address: " );
          Serial.println(EV1527::parseAddress(adValue), 16);
          Serial.print("Data: " );
          Serial.println(EV1527::parseData(adValue), 16);
        }
        else
          Serial.println("Other code type..." );
      }
      else
      {
        Serial.println("RF decode error...");
      }
      //准备取下一个遥控编码
      rfRecv.resume();
    }
}
 
int main()
{
  //初始化Rainbow
  boardInit();
  setup();
  while(1) loop();
}
 
    这个程序的功能是接收射频遥控编码,并进行解码和显示,运行的效果如下:

 
    在软件包的“Projects\EV1527”文件夹包含了发射EV1527遥控编码的完整工程,可以直接编译、烧写和调试。程序代码如下:
#include "WProgram.h"
#include "RFRemote.h"
 
//定义射频编码发送对象,使用PA0作为输出端口
RFSend rfSend(PA0);
 
void setup()
{
  //初始化默认串口
  Serial.begin();
  Serial.println("EV1527 encode start...");
}
 
void loop()
{
  rfSend.ev1527Send(0x0FE018, 7);
  delay(3000);
}
 
int main()
{
  //初始化Rainbow
  boardInit();
  setup(); 
  while(1) loop();
}
 
    将315M无线发射模块的DATA和PA0相连,软件将每隔3秒钟通过无线发射模块发送指定的地址码和数据。PT2622编码调用方式类似,可以参考“Projects\PT2622”这个工程。
关闭窗口