鄔芝權(quán) 靳桅
摘 要: 在無線通信環(huán)境下,基于UART接口的無線模塊可以釋放CPU軟硬件資源、使用方便、用途廣泛。通過介紹一種廉價的無線模塊設(shè)計(jì)方案,根據(jù)nRF24L01 封裝無線數(shù)據(jù)包和UART接口速度慢的特點(diǎn),設(shè)計(jì)了對UART數(shù)據(jù)的發(fā)送和接收雙緩沖器,開發(fā)軟硬件,實(shí)現(xiàn)了可靠的無線數(shù)據(jù)通信。實(shí)驗(yàn)表明無線模塊UART接口的可靠通信速率可以達(dá)到128 000 b/s,達(dá)到預(yù)期效果,滿足大部分網(wǎng)絡(luò)化條件下無線通信功能要求。
關(guān)鍵詞: UART; NRF24L01; 緩沖器; 無線模塊
中圖分類號: TN911?34; TP368.1 文獻(xiàn)標(biāo)識碼: A 文章編號: 1004?373X(2015)05?0005?04
Design of UART wireless module based on double buffers
WU Zhi?quan, JIN Wei
(Department of Computer and Communication Engineering in Emei Branch, Southwest Jiaotong University, Emei 614202, China)
Abstract: In the wireless communication environment, the wireless module based on UART interface can release the hardware and software resources of CPU. It′s easy to use, and has a wide range of applications. A low cost scheme to design wireless module is introduced in this paper. According to the encapsulation wireless data packet of nRF24L01 and the slow?speed feature of the UART interface, the double?buffer transmitting and receiving the UART data was designed, the corresponding software and hardware were developed, and the reliable wireless data communication was realized. Experiments show that the wireless module with UART interface achieves the desired effect, which implements a reliable transmission rate of [128 000 b/s,]and meets the most requirements of wireless communication function.
Keywords: UART; NRF24L01; buffer; wireless module
0 引 言
隨著物聯(lián)網(wǎng)技術(shù)發(fā)展需要,2.4 GHz 頻段的無線應(yīng)用得到了空前發(fā)展,無線空中傳輸速率較快,無線模塊提供給用戶使用的大多為SPI接口。相對于UART接口來說,SPI接口采用同步串行傳輸,傳輸速度較快,但是通信時傳輸距離短、要占用更多的CPU、內(nèi)存和I/O接口資源。UART接口是全雙工異步接口,大部分MCU自帶這種接口,使用時編程簡單,占用內(nèi)存少。根據(jù)用戶需要,可以將UART接口轉(zhuǎn)換為RS 232電平或RS 422電平,延長傳輸距離,所以UART接口在控制類領(lǐng)域仍大量使用。
基于UART接口的無線模塊,不用設(shè)計(jì)額外的電路和程序,可以按有線方式使多個節(jié)點(diǎn)進(jìn)行通信,并且受地理?xiàng)l件限制少、安裝靈活。本文依據(jù)市場發(fā)展需求,研究和設(shè)計(jì)了一種基于STC15W204S單片機(jī)和nRF24L01無線射頻收發(fā)芯片實(shí)現(xiàn)的小成本、低功耗UART無線模塊。
1 UART無線模塊傳輸數(shù)據(jù)面臨的問題及解決
方案
UART無線模塊接口示意如圖1所示,單片機(jī)STC15W204S一方面接收UART接口的數(shù)據(jù)和配置命令,另一方面通過SPI接口與nRF24L01進(jìn)行通信,傳送數(shù)據(jù)、命令、啟動發(fā)送和檢測接收等功能。在設(shè)計(jì)時一方面要解決各種接口速度不匹配問題,另一方面還要盡量提高數(shù)據(jù)傳輸速度。
1.1 速度匹配問題
通過對UART、SPI和無線這三種通信模式的數(shù)據(jù)傳輸速度分析來看,SPI通信的速度是由STC15W204S提供的時鐘信號決定的,可以達(dá)到5 Mb/s;nRF24L01的無線數(shù)據(jù)包空中速率可以設(shè)置為250 Kb/s,1 Mb/s和2 Mb/s,速度雖然快,但數(shù)據(jù)是以數(shù)據(jù)包方式在空中傳輸,不具備連續(xù)性;UART傳送數(shù)據(jù)的速度范圍為每秒幾百位到1.5 Mb/s,其速率受發(fā)送和接收線對距離(線長度)的影響非常大,常用速度一般不會超過128 Kb/s。由于三種通信模式的數(shù)據(jù)傳輸速度不一致,在數(shù)據(jù)傳輸過程中難免會有部分?jǐn)?shù)據(jù)積壓,需要合理的設(shè)置一段存儲區(qū)來處理數(shù)據(jù)。
1.2 無線通信有效數(shù)據(jù)傳輸速率問題
nRF24L01的無線數(shù)據(jù)包包含前導(dǎo)碼、地址、標(biāo)志位、數(shù)據(jù)(1~32 B)和校驗(yàn),發(fā)射時消耗在啟動、發(fā)送接收模式切換和應(yīng)答時間較長。由于數(shù)據(jù)包中數(shù)據(jù)長度可以設(shè)置1~32 B,其有效數(shù)據(jù)傳輸率相差很大。下面以發(fā)送一包數(shù)據(jù)時序來分析其有效數(shù)據(jù)傳輸速率,如圖2所示,為增強(qiáng)型SchockBurstTM模式發(fā)送一個有效字節(jié)的數(shù)據(jù)包所需時間為339 μs,每增加一個有效字節(jié)僅需4 μs,設(shè)發(fā)送一包數(shù)據(jù)的時間為[TECB,]MCU上傳數(shù)據(jù)至nRF24L01的時間為[TUL,]發(fā)送的有效字節(jié)數(shù)為[N,]則根據(jù)時序圖可以得到公式(1):
當(dāng)STC15W204S的晶振設(shè)為22.118 4 MHz時,經(jīng)編程測試,[TUL]消耗時間為250 μs,故[TECB=250+][335+4N=][585+4N。]
其有效數(shù)據(jù)通信頻率設(shè)為[F,]則得到公式(2):
[F=106TECB?N×8] (2)
將[TECB]的值代入公式(2)得到:
[F=106(585+4N)?N×8] (3)
當(dāng)[N=1 ]B時,[F=]13.582 Kb/s;
當(dāng)[N=32 ]B時,[F=]359.04 Kb/s。
由此可見,數(shù)據(jù)長度的大小很大程度上影響了無線數(shù)據(jù)傳輸效率,一個數(shù)據(jù)包中數(shù)據(jù)長度越大,則數(shù)據(jù)傳輸效率越高。
為了提高數(shù)據(jù)傳輸速率,每個無線數(shù)據(jù)包盡量包含更多的有效數(shù)據(jù),但是兩個無線數(shù)據(jù)包之間會有一定時間間隔,如果每個數(shù)據(jù)包都按最大有效數(shù)據(jù)量來打包,當(dāng)UART接收數(shù)據(jù)量達(dá)不到打包條件時,則會使程序處于等待打包狀態(tài),即使可以增加延時退出程序來解決,由于消耗CPU時間較長導(dǎo)致實(shí)時性差。
如果每從UART接收一個數(shù)據(jù)就打包發(fā)送,雖然實(shí)時性高,但傳輸效率很差,經(jīng)測試,在這種情況下,UART速度最大可設(shè)置為4 800 b/s。
所以在無線數(shù)據(jù)打包時,變長長度的數(shù)據(jù)包可以有效地解決數(shù)據(jù)傳輸速度和實(shí)時性問題。
2 解決方案
STC15W204S單片機(jī)的UART為全雙工通信方式,但發(fā)送和接收緩沖器只有1個字節(jié),為了解決數(shù)據(jù)傳輸?shù)乃俣绕ヅ浜蜔o線數(shù)據(jù)實(shí)時性較差這兩個問題,需要設(shè)計(jì)一個緩沖區(qū)對接收和發(fā)送的數(shù)據(jù)進(jìn)行緩存。在設(shè)計(jì)緩沖區(qū)時,除了考慮其大小來滿足通信需要,還要考慮如何減少CPU處理數(shù)據(jù)的時間。首先確定UART數(shù)據(jù)緩沖區(qū)大小,設(shè)置數(shù)據(jù)寫入和讀出操作指針,指針通過取模的方式循環(huán)指向緩沖區(qū)內(nèi)的位置。當(dāng)接收新數(shù)據(jù)時,數(shù)據(jù)寫入指針通過加1取模調(diào)整,然后寫入數(shù)據(jù),當(dāng)從緩沖區(qū)讀數(shù)據(jù)時,數(shù)據(jù)讀出指針通過加1取模調(diào)整,然后取出數(shù)據(jù)。這樣,緩沖區(qū)內(nèi)部數(shù)據(jù)不需要進(jìn)行移動,大大節(jié)省了CPU處理數(shù)據(jù)的時間。
當(dāng)UART向無線接口發(fā)送數(shù)據(jù)時,將無線數(shù)據(jù)包的數(shù)據(jù)長度設(shè)置為32個字節(jié),最后1個字節(jié)定義為有效數(shù)據(jù)長度,為了保障通信的實(shí)時性,只要UART接收緩沖區(qū)中有數(shù)據(jù)就啟動一次無線打包發(fā)送程序,將數(shù)據(jù)全部打包傳輸,數(shù)據(jù)包的長度是變長的,不超過31個字節(jié),最后1個字節(jié)為有效數(shù)據(jù)長度。這樣既提高了數(shù)據(jù)傳輸效率,又保證傳輸實(shí)時性。
3 程序設(shè)計(jì)
在RAM中定義兩個存儲區(qū),一個為接收緩沖區(qū),一個為發(fā)送緩沖區(qū)。接收緩沖區(qū)長度宏定義為RECV_BUF_ LEN,發(fā)送緩沖區(qū)長度定義為TRANS_BUF_LEN,具體值通過宏定義設(shè)置。定義變量Recv_In_Pointer和Recv_Out_Pointer分別為接收緩沖區(qū)數(shù)據(jù)寫入和讀出指針,Trans_In_Pointer和Trans_Out_Pointer為發(fā)送緩沖區(qū)數(shù)據(jù)寫入和讀出指針,調(diào)整指針后,對指針取模,則指針固定指向某個范圍區(qū)域,構(gòu)成循環(huán)緩沖區(qū)。下面討論UART接收數(shù)據(jù)緩沖區(qū)工作原理。
為了避免UART的接收和發(fā)送數(shù)據(jù)時使CPU處于等待狀態(tài),UART的接收和發(fā)送采用中斷模式,在中斷服務(wù)程序中再判斷是接收中斷還是發(fā)送中斷。如果是接收中斷則將UART數(shù)據(jù)寫入接收緩沖區(qū),并調(diào)整寫入數(shù)據(jù)指針,使之指向下一個空數(shù)據(jù)項(xiàng)。如果是發(fā)送中斷,則調(diào)整數(shù)據(jù)讀出指針,如果發(fā)送緩沖區(qū)沒有數(shù)據(jù),則將發(fā)送數(shù)據(jù)結(jié)束標(biāo)志置位。
設(shè)置RECV_BUF_LEN=16,在接收數(shù)據(jù)緩沖區(qū),其初始狀態(tài)為輸入指針Recv_In_Pointer和輸出指針Recv_Out_職Pointer都指向接收緩沖區(qū)位置0處,如圖3(a)所示。當(dāng)UART接收到數(shù)據(jù),進(jìn)入UART中斷服務(wù)程序,將數(shù)據(jù)寫入接收緩沖區(qū)Recv_In_Pointer指向的位置,然后調(diào)整指針Recv_In_Pointer,使其指向空數(shù)據(jù)項(xiàng),同時將位變量Recv_End置1,表示接收緩沖區(qū)已有新數(shù)據(jù),如圖3(b)所示。當(dāng)接收緩沖區(qū)有數(shù)據(jù)(Recv_End=1),CPU處理UART數(shù)據(jù)時,從接收緩沖區(qū)Recv_Out_Pointer指向的位置讀出數(shù)據(jù),然后調(diào)整指針Recv_Out_Pointer,使其指向下一個數(shù)據(jù)項(xiàng),當(dāng)Recv_In_Pointer和Recv_ Out_Pointer的值相同則表示接收緩沖區(qū)中無數(shù)據(jù),同時將Recv_End清1。如果CPU不及時處理接收緩沖區(qū)中的數(shù)據(jù),當(dāng)UART接收數(shù)據(jù)過多時,就會使接收緩沖區(qū)溢出,如圖3(d)所示。
下面介紹從UART接收到無線發(fā)送的部分程序。
UART中斷接收部分程序如下:
void Serial_Int(void) interrupt 4 //串行口中斷服務(wù)程序
{
if (_testbit_(RI)) //接收中斷
{
Recv_Buf[Recv_In_Pointer]=SBUF;
//接收數(shù)據(jù)入接收緩沖區(qū)
Recv_Data=Recv_Buf[Recv_In_Pointer]; Recv_In_Pointer=(Recv_In_Pointer+1)%RECV_BUF_LEN;
Recv_End=1; //置串行口接收完成標(biāo)志
}
……
}
CPU從UART讀出一個字節(jié)程序如下:
unsigned char Serial_In(void)
{
unsigned char Temp_Data;
while ( Recv_Out_Pointer==Recv_In_Pointer ) ;
//無數(shù)據(jù)等待
Temp_Data=Recv_Buf[Recv_Out_Pointer];
//從接收緩沖區(qū)中讀數(shù)據(jù)
Recv_Out_Pointer=(Recv_Out_Pointer+1)%RECV_BUF_ LEN;
if (Recv_Out_Pointer==Recv_In_Pointer )
Recv_End=0;
return Temp_Data; //返回接收數(shù)據(jù)
}
在無線打包程序設(shè)計(jì)過程中,數(shù)據(jù)包最大數(shù)據(jù)長度為32 B,采用變長數(shù)據(jù)發(fā)送模式,將數(shù)據(jù)包的最后1個字節(jié)用來表示有效數(shù)據(jù)長度,有效數(shù)據(jù)長度宏定義為TX_PLOAD_WIDTH,可以在編譯之前設(shè)置,最大長度為31 B,無線打包發(fā)送程序如下:
if (Recv_End) //判斷串行口緩沖器中是否有接收數(shù)據(jù)
{
if (nRF24L01_Tx_End==1)
{
Recv_Char = Serial_In(); //讀UART接收數(shù)據(jù)
Tx_Buf[0] = Recv_Char; //寫入無線發(fā)送緩沖區(qū)
nRF24L01_Tx_Len=1; //無線初始發(fā)送設(shè)置為1
while (Recv_End==1) //判斷接收緩沖器還有數(shù)據(jù)
{
Tx_Buf[nRF24L01_Tx_Len]=Serial_In();
//寫無線緩沖區(qū)
nRF24L01_Tx_Len++;
//無線發(fā)送有效數(shù)據(jù)長度加1
if (nRF24L01_Tx_Len>=(TX_PLOAD_WIDTH-1))
//過長
{
break;
}
}
Tx_Buf[TX_PLOAD_WIDTH-1]=Nrf24L01_Tx_Len;
//將無線發(fā)送緩沖區(qū)最后一個字節(jié)置為無線
發(fā)送的有效數(shù)據(jù)長度
nRF24L01_TxPacket(Tx_Buf);
//將啟動nRF24L01發(fā)送
nRF24L01_Tx_End=0; //無線發(fā)送模式結(jié)束
}
對于UART發(fā)送數(shù)據(jù)緩沖區(qū),它的工作是接收無線數(shù)據(jù)包至無線接收緩沖區(qū),然后對數(shù)據(jù)進(jìn)行分析,提取有效數(shù)據(jù),通過UART口發(fā)出。由于無線數(shù)據(jù)包數(shù)據(jù)項(xiàng)的最后一個字節(jié)表示有效數(shù)據(jù)長度,通過這個字節(jié)就可以知道應(yīng)該從無線接收緩沖區(qū)取出多少字節(jié)的數(shù)據(jù)。單片機(jī)在這方面處理的速度遠(yuǎn)遠(yuǎn)高于無線打包程序處理速度,所以這方面程序不需要過多優(yōu)化。
4 測 試
測試時采用長數(shù)據(jù)串連續(xù)傳輸,傳輸時會將數(shù)據(jù)分成多個數(shù)據(jù)包,根據(jù)UART接收數(shù)據(jù)量的多少變長打包,當(dāng)UART接收數(shù)據(jù)速度越快,則無線數(shù)據(jù)包中含有的有效數(shù)據(jù)量越大。由于無線數(shù)據(jù)包中的數(shù)據(jù)長度設(shè)置為32個字節(jié),最后1個字節(jié)表示有效數(shù)據(jù)個數(shù),只要有效數(shù)據(jù)量不超過31,就說明緩沖區(qū)不會溢出。
將兩個UART無線模塊連接至計(jì)算機(jī),在程序代碼中插入測試代碼,將數(shù)據(jù)包中有效數(shù)據(jù)量返回,使用串口調(diào)試軟件進(jìn)行數(shù)據(jù)通信測試。其中一個無線模塊用于接收數(shù)據(jù),如圖4(a)所示,串口號為COM8,另一個無線模塊用于發(fā)送數(shù)據(jù),如圖4(b)所示,串口號是COM9,串口速率都設(shè)置為128 000 b/s,連續(xù)發(fā)送1 000個字符數(shù)據(jù)用于測試。測試結(jié)果表明,無線數(shù)據(jù)發(fā)送時封裝為70個數(shù)據(jù)包,其中數(shù)據(jù)包最大有效數(shù)據(jù)長度為15,小于31個,從COM8接收到的數(shù)據(jù)也是1 000個字符,說明無線模塊在該速率下傳輸是準(zhǔn)確、可靠的。
根據(jù)這個方法對不同速率情況下,數(shù)據(jù)傳輸和打包情況測試結(jié)果如表1所示。
該結(jié)果說明當(dāng)速率設(shè)置為4 800 b/s及以下時,可以實(shí)現(xiàn)串口數(shù)據(jù)實(shí)時打包傳輸,即每接收一個串口數(shù)據(jù)就立刻打包從無線端口送出,不需要設(shè)置緩沖區(qū)。當(dāng)速率設(shè)置為9 600 b/s及以上時,會出現(xiàn)幾個數(shù)據(jù)封裝為一個無線數(shù)據(jù)包的情況,這種情況就必須要設(shè)置UART接收和發(fā)送緩沖區(qū),才能實(shí)現(xiàn)可靠傳輸。
5 結(jié) 語
本無線模塊經(jīng)過多次測試檢驗(yàn)是非常可靠的。考慮到無線模塊不同的使用用戶,作者為無線模塊編寫了配置程序,配置信息保存在E2PROM。配置內(nèi)容包括波特率、無線頻道、發(fā)送和接收通道地址、接收運(yùn)行和自動應(yīng)答等,用戶在使用時只需配置一次即可。作者設(shè)計(jì)時采用了STC新款寬電壓1T單片機(jī)STC15W204S,工作可靠,速度快,價格便宜。由于無線模塊采用UART接口后,用戶只需要安裝UART接口編程即可,不用考慮無線數(shù)據(jù)收發(fā)問題,使用非常方便。
參考文獻(xiàn)
[1] 李輝,宋詩,周建江.基于ARM和nRF24L01的無線數(shù)據(jù)傳輸系統(tǒng)[J].國外電子元器件,2008(12):44?46.
[2] 曾勇,楊濤,馮月暉.基于nRF24L01的超低功耗無線傳感器網(wǎng)絡(luò)節(jié)點(diǎn)設(shè)計(jì)[J].電子技術(shù)應(yīng)用,2008(7):45?48.
[3] 劉志平,趙國良.基于nRF24L01的近距離無線數(shù)據(jù)傳輸[J].應(yīng)用科技,2008(3):55?58.
[4] 劉超偉,趙俊淋,易衛(wèi)東.基于nRF24L01的無線圖像傳感器節(jié)點(diǎn)設(shè)計(jì)實(shí)現(xiàn)[J].電子測量技術(shù),2008(6):136?139.
[5] 黃秀節(jié),顏可煌,趙偉.基于nRF24L01的無線USB控制系統(tǒng)[J].國外電子測量技術(shù),2009(12):43?46.
[6] 韋積慧.基于nRF24L01的無線網(wǎng)絡(luò)設(shè)計(jì)與實(shí)現(xiàn)[D].長春:吉林大學(xué),2012.
[7] 郝文延,焦明華.基于DSP和nRF24L01的無線環(huán)境監(jiān)測系統(tǒng)設(shè)計(jì)[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2011(3):51?54.
[8] 楊旭,李德敏,張謙益.基于nRF24L01的一種無線通信協(xié)議設(shè)計(jì)[J].通信技術(shù),2011(7):57?59.
[9] 朱慧彥,林林.基于MCU和nRF24L01的無線通信系統(tǒng)設(shè)計(jì)[J].電子科技,2012(4):81?83.