这次我用的是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”这个工程。