前兩天用軟件實(shí)現(xiàn)了EV1527及PT2622射頻編碼功能,周末在家閑來無事,我就琢磨用軟件來實(shí)現(xiàn)射頻編碼接收并對(duì)PT2622和EV1527格式的編碼進(jìn)行解析,說干就干,周天上午一早就開始,晚上也是邊看電視邊做,經(jīng)過一天的努力,終于在睡覺前完整了主要程序的編寫,周一又花了些時(shí)間來檢查,最后終于搞定。
這次我用的是315M無線接收模塊,就是這種的模塊:
按照資料說明這個(gè)模塊需要5V供電,我本來還擔(dān)心3.3V下面可能不工作,不過實(shí)踐證明,是可行的。將這個(gè)模塊的DATA管腳接到開發(fā)板的PA8,PA8是TIM1的CH1,對(duì)于射頻遙控編碼的采集我用了定時(shí)器的PWM捕獲功能,這點(diǎn)和紅外遙控編碼采集方式類似,不同之處在于,紅外遙控編碼用的是下降沿觸發(fā)采集,而射頻遙控編碼采用的上升沿觸發(fā)進(jìn)行采集。還有一點(diǎn)特別重要:紅外遙控編碼接收模塊HX1838在平時(shí)沒有收到紅外信號(hào)的時(shí)候是高電平,當(dāng)收到信號(hào)過后才產(chǎn)生脈沖,但是射頻采用電磁波進(jìn)行傳輸,而平時(shí)我們所在的空間中存在各種電磁波,所以即便沒有信號(hào)的時(shí)候,也會(huì)出現(xiàn)不規(guī)則的波形輸入,我們需要做的就是將有用的信號(hào)從各種干擾信號(hào)中提取出來,這一點(diǎn)是與紅外遙控編碼接收的最大不同。
將有用的射頻遙控編碼信號(hào)從雜波中提取出來還是比較容易的,射頻遙控的一個(gè)字碼是由同步編碼+地址碼+數(shù)據(jù)碼構(gòu)成,我們只需要甄別出同步碼,然后從同步碼開始進(jìn)行波形采集即可。射頻編碼一般一次至少發(fā)送4個(gè)以上的字碼,由于無線傳輸過程中可能出現(xiàn)干擾信號(hào),導(dǎo)致信號(hào)失真,因此我們必須對(duì)收到的多個(gè)字碼進(jìn)行驗(yàn)證,保證至少有兩個(gè)以上的連續(xù)字碼相同,這一點(diǎn)也是和紅外遙控編碼提取的最大不同。
經(jīng)過過濾雜波、驗(yàn)證有效的射頻遙控編碼之后,我們就可以得到一個(gè)有效的射頻編碼原始數(shù)據(jù),接下來我們就需要判斷是EV1527還是PT2622以及其它類型的編碼,除了EV1527和PT2622之外的編碼暫時(shí)不支持解碼,只保留了原始采集的時(shí)長(zhǎng)數(shù)據(jù),而EV1527和PT2622的編碼都是由50個(gè)高低電平來表示的,怎么樣進(jìn)行區(qū)分呢?
PT2622是用兩個(gè)脈沖來表示一個(gè)位,有0,1,F三種狀態(tài):兩個(gè)窄脈沖表示0,兩個(gè)寬脈沖表示1,一個(gè)窄脈沖+一個(gè)寬脈沖表示F;而EV1527用一個(gè)脈沖來表示0和1:窄脈沖表示0,寬脈沖表示1。所以在PT2622編碼中不可能出現(xiàn)一個(gè)寬脈沖+窄脈沖的組合,通過這個(gè)特征就可以很方便將兩種編碼進(jìn)行區(qū)分。進(jìn)行了編碼區(qū)分之后,接下來的事情就比較簡(jiǎn)單了,只需要根據(jù)兩種編碼格式的規(guī)則進(jìn)行解析,得到真實(shí)的二進(jìn)制編碼即可。
根據(jù)上述原理,我編寫了一個(gè)類RFRecv,這個(gè)類里面封裝了射頻編碼采集、解碼的功能;同時(shí)又對(duì)之前編寫的PT2622和EV1527編碼程序進(jìn)行了封裝,寫了一個(gè)類RFSend,用于實(shí)現(xiàn)對(duì)原始編碼時(shí)長(zhǎng)數(shù)據(jù)發(fā)送、EV1527和PT2622進(jìn)行編碼發(fā)送的功能。
在軟件包的“Projects\RF-Recv”文件夾包含了射頻接收的完整工程,可以直接編譯、燒寫和調(diào)試。程序代碼如下:
#include "WProgram.h"
#include "RFRemote.h"
//創(chuàng)建射頻遙控接收實(shí)例,射頻接收模塊接到TIM1的CH1,即:PA8
RFRecv rfRecv;
void setup()
{
//初始化默認(rèn)串口
Serial.begin();
rfRecv.enableRFIn();
Serial.println("RFRemote start...");
}
void loop()
{
uint16_t* rawBuf;
int16_t len = rfRecv.available();
//判斷射頻遙控編碼采集是否完成
if(len > 0)
{
//取采集的原始編碼
awBuf = rfRecv.getRawCode();
//將接收到的原始編碼通過默認(rèn)串口輸出
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();
//二進(jìn)制方式顯示解碼結(jié)果
Serial.print("RF adValue:");
Serial.println(adValue, 16);
if(codeType == 1)
{
Serial.println("Code Type: PT2622" );
//12位數(shù)據(jù)中,地址為占8位,數(shù)據(jù)占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位數(shù)據(jù)中,地址占20為,數(shù)據(jù)占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...");
}
//準(zhǔn)備取下一個(gè)遙控編碼
rfRecv.resume();
}
}
int main()
{
//初始化Rainbow
boardInit();
setup();
while(1) loop();
}
這個(gè)程序的功能是接收射頻遙控編碼,并進(jìn)行解碼和顯示,運(yùn)行的效果如下:
在軟件包的“Projects\EV1527”文件夾包含了發(fā)射EV1527遙控編碼的完整工程,可以直接編譯、燒寫和調(diào)試。程序代碼如下:
#include "WProgram.h"
#include "RFRemote.h"
//定義射頻編碼發(fā)送對(duì)象,使用PA0作為輸出端口
RFSend rfSend(PA0);
void setup()
{
//初始化默認(rèn)串口
Serial.begin();
Serial.println("EV1527 encode start...");
}
void loop()
{
rfSend.ev1527Send(0x0FE018, 7);
delay(3000);
}
int main()
{
//初始化Rainbow
boardInit();
setup();
while(1) loop();
}
將315M無線發(fā)射模塊的DATA和PA0相連,軟件將每隔3秒鐘通過無線發(fā)射模塊發(fā)送指定的地址碼和數(shù)據(jù)。PT2622編碼調(diào)用方式類似,可以參考“Projects\PT2622”這個(gè)工程。