寫在前面的話:
最近在做畢業(yè)設(shè)計(jì),有一項(xiàng)任務(wù)是翻譯英文資料,要求翻譯成漢文約5K字。我以前從未做過翻譯工作,不過還是硬著頭皮做了下來。下面與大家分享一下我的譯文,如果大家能夠從我的譯文弄懂關(guān)于nRF24L01的一些知識(shí),說明我的翻譯還是成功的;如果大家感到一頭霧水說明我還要繼續(xù)努力了。(當(dāng)然要是IT相關(guān)的人才行,學(xué)文科的估計(jì)是看不懂的,嘿嘿)。對(duì)于nRF24L01,我是做畢設(shè)時(shí)要用才學(xué)習(xí)的,剛接觸,具體的我也不是很了解,所以才選了兩篇介紹nRF24L01的英文文章翻譯的。希望有高手不吝賜教!
第二章 :帶有增強(qiáng)型Shockburst的Sweet硬件鏈路層
引言
現(xiàn)在我有兩份有關(guān)學(xué)習(xí)24L01的放映片已經(jīng)做好,而你仍然跟著我學(xué)習(xí)的話,這再好不過了!在這一章,我們將探討關(guān)于24L01的帶有增強(qiáng)型Shockburst的集成鏈路層。
開始之前應(yīng)該了解的
在我們開始之前,你要知道這一章是建立在已經(jīng)授完的第一章的基礎(chǔ)上的。事實(shí)上,對(duì)于每個(gè)主程序只有大約5行代碼或者更少是不同的。由于這個(gè)原因,如果你先打算讓這章代碼運(yùn)行的話,最好在開始這章之前你已經(jīng)將第一章的代碼運(yùn)行過了。如果你只是想了解一些背景而不想要完全測(cè)試代碼,那么不考慮這些而繼續(xù)學(xué)習(xí)也是可以的。
差不多這一章與第一章的不同僅僅在于,在這一章,我們將用增強(qiáng)型的Shockburst模式去處理nRF24L01的硬件鏈路層。這種模式允許我們讓 24L01能自動(dòng)的處理應(yīng)答信號(hào)和重發(fā)數(shù)據(jù)。這種功能的實(shí)現(xiàn)不需要額外的硬件甚至不需要額外的代碼,這使得我們工作的鏈路層功能比以前更為強(qiáng)勁。唯一不好的是如果采用這種模式,鏈路的速度會(huì)稍微有所下降,但是只要你不需要24L01提供帶寬的每一個(gè)部分,增強(qiáng)型的Shockburst模式顯然是非常合適的。
Nutshell中的增強(qiáng)型Shockburst
你也許想知道增強(qiáng)型Shockburst到底是什么。它實(shí)質(zhì)上是24L01硬件中可以被執(zhí)行的一種模式,這種模式下系統(tǒng)會(huì)接受數(shù)據(jù)接收的應(yīng)答信號(hào),并且在數(shù)據(jù)丟失的情況下系統(tǒng)會(huì)自動(dòng)的重發(fā)。當(dāng)需要一個(gè)強(qiáng)勁的鏈路使得傳輸大部分?jǐn)?shù)據(jù)的時(shí)候,增強(qiáng)型Shockburst模式可以將用戶從繁重的軟件工作中解脫出來。
如果你非常熟知英特網(wǎng)協(xié)議,那么使用增強(qiáng)型Shockburst模式很像使用TCP,而常規(guī)的Shockburst就像是網(wǎng)絡(luò)協(xié)議中的UDP。然而增強(qiáng)型 Shockburst并不像TCP那樣建立和關(guān)閉一個(gè)連接,它提供的是某種可以使你的數(shù)據(jù)順利傳輸?shù)牟煌耆珦?dān)保。和TCP類似,增強(qiáng)型 Shockburst對(duì)于沒有應(yīng)答(這種應(yīng)答是由接收端的增強(qiáng)型Shockburst發(fā)出的)的數(shù)據(jù),會(huì)重發(fā)很多次直到達(dá)到它設(shè)置的最大重復(fù)次數(shù)而形成中斷標(biāo)志。
有一些寄存器和控制增強(qiáng)型Shockburst模式有關(guān)。EN_AA寄存器通過置1和置0打開或者關(guān)閉每個(gè)數(shù)據(jù)通道的自動(dòng)應(yīng)答功能。當(dāng)一個(gè)發(fā)送的數(shù)據(jù)沒有應(yīng)答的時(shí)候,可以在SETUP_RETR寄存器的ARC區(qū)域設(shè)置你想要重發(fā)的次數(shù)(設(shè)置成0000代表不重發(fā))。在SETUP_RETR寄存器的ARD區(qū)域可以設(shè)置兩次重發(fā)操作之間的時(shí)間間隔(數(shù)值越低,時(shí)間越短)。你可以利用CONFIG寄存器的MAX_RT中斷使能位將MAX_RT中斷的狀態(tài)傳達(dá)給 IRQ針腳。你也可以利用STATUS寄存器的MAX_RT位來判斷MAX_RT是否中斷。
增強(qiáng)型Shockburst的設(shè)置很簡(jiǎn)單。首先,你需要確定在發(fā)射設(shè)備中,通道0的接收地址(在RX_ADDR_P0 寄存器)和你的發(fā)射地址(在TX_ADDR寄存器)要相同。這是因?yàn)槭峭ㄟ^發(fā)射設(shè)備中的通道0來接收應(yīng)答信號(hào)的。其次,你要確保發(fā)射設(shè)備的通道0的自動(dòng)應(yīng)答和接收端的某一個(gè)你用來接收信號(hào)的通道正常工作。最后,你要在發(fā)射端的SETUP_RETR寄存器中設(shè)置最大重復(fù)次數(shù)和重發(fā)延遲時(shí)間。
一旦增強(qiáng)型Shockburst模式設(shè)置完畢后,一切都變得明朗了,因?yàn)樗械牟僮鞫际亲詣?dòng)完成的。你真正要做的是你要觀察MAX_RT中斷或者觀察 TX_DS中斷,因?yàn)槟骋粫r(shí)刻你得到的是二者之一的結(jié)果,而二者不會(huì)同時(shí)中斷。如果數(shù)據(jù)被發(fā)送并且接收到了應(yīng)答信號(hào),然后TX_DS就會(huì)中斷。如果沒有收到數(shù)據(jù)發(fā)送成功的應(yīng)答信號(hào),在達(dá)到設(shè)置的最大重發(fā)次數(shù)之前,MAX_RT也會(huì)中斷。
在這里,增強(qiáng)型Shockburst模式和常規(guī)Shockburst模式有一個(gè)非常重要的區(qū)別需要引起注意。在增強(qiáng)型Shockburst模式中,如果數(shù)據(jù)被成功發(fā)送,TX_DS中斷后,像在常規(guī)Shockburst模式下一樣,TX FIFO中的數(shù)據(jù)就會(huì)被清除;然而,如果數(shù)據(jù)被發(fā)送后沒有收到應(yīng)答信號(hào),然后MAX_RT中斷,但是數(shù)據(jù)并不會(huì)從TX FIFO中清除。換句話說,如果你想要重發(fā)數(shù)據(jù),你只需重置CE就可以重發(fā)了。然而,如果你想要丟棄這個(gè)數(shù)據(jù),在你加載任何新的數(shù)據(jù)之前,你必須清除TX FIFO。否則,24L01會(huì)嘗試發(fā)送原本未發(fā)送成功的數(shù)據(jù)和你后來加載的要發(fā)送的數(shù)據(jù),這樣會(huì)擾亂你的發(fā)送進(jìn)程。
本章我所用的硬件
本章我用的硬件和在第一章里用的是一樣的。沒有任何增減,只要你在學(xué)第一章的時(shí)候讓硬件工作,那么在這一章里你肯定可以讓它工作。
本章軟件描述
情況和需要的硬件類似,本章所需要的軟件和第一章的是一樣的,如果你已經(jīng)運(yùn)行過了,那么在本章中,你將有非常清晰的思路。
本地主文件:maintutorial2local.c
假如你看過第一章,那么這個(gè)文件對(duì)你來說極其熟悉。除了要加上用來支持增強(qiáng)型Shockburst的代碼外,操作方式和在運(yùn)行第一章程序時(shí)一樣。
在進(jìn)入主程序之前的部分是相同的。仍然要調(diào)用Initialize()函數(shù),但是考慮到增強(qiáng)型Shockburst模式的使用,這里會(huì)稍有不同:當(dāng)我們調(diào)用nrf24l01_intialize_debug()函數(shù)的時(shí)候,可以給第三個(gè)參數(shù)賦值,這樣就可以使數(shù)據(jù)通道0工作在增強(qiáng)型Shockburst模式下。
現(xiàn)在我們來進(jìn)入程序的主循環(huán)。在這我們接收從USART來的數(shù)據(jù),然后就像第一章我們做的那樣把字節(jié)發(fā)送出去。然而,這里就是程序的不同之處。當(dāng)你使用增強(qiáng)型Shockburst模式,你必須留意MAX_RT中斷,這個(gè)中斷會(huì)被加入到檢查數(shù)據(jù)是否發(fā)送成功的while循環(huán)中。在增強(qiáng)型Shockburst 模式下傳輸數(shù)據(jù),如果數(shù)據(jù)沒有傳輸成功,TX_DS是不會(huì)中斷的。這就是你為什么兩個(gè)中斷都要觀察。
有一點(diǎn)還需要另外說明。當(dāng)我們檢測(cè)MAX_RT是否中斷的時(shí)候,如果沒有中斷我們就像第一章那樣處理數(shù)據(jù);然而,如果中斷了,這表示數(shù)據(jù)沒有被成功的接收,我們添加一個(gè)調(diào)試字符“*”來反映這種信息。當(dāng)數(shù)據(jù)從本地單位發(fā)出后如果沒有收到應(yīng)答信號(hào),通過那種方式我們可以判斷出在接收端是否數(shù)據(jù)被傳輸?shù)搅诉h(yuǎn)程單位。正如我上面討論的那樣,當(dāng)MAX_RT中斷后,數(shù)據(jù)仍留在TX FIFO。由于這個(gè)原因,我們調(diào)用nrf24l01_flush_tx()函數(shù)來清除數(shù)據(jù)。最后我們清除中斷,讓循環(huán)繼續(xù),這樣我們就可以繼續(xù)接受來自 USART的數(shù)據(jù)了。
遠(yuǎn)程主文件:maintutorial2remote.c
就像本地主文件一樣,遠(yuǎn)程主文件和第一章用的基本一樣,它也是只在其中加入了使增強(qiáng)型Shockburst模式啟動(dòng)并運(yùn)行的部分。
在主程序之前的所有聲明和定義和第一章中的遠(yuǎn)程主文件是一樣的。進(jìn)入主程序,我們也要調(diào)用Initialize()函數(shù),但是考慮到增強(qiáng)型 Shockburst模式的使用,這里會(huì)稍有不同:當(dāng)我們調(diào)用nrf24l01_intialize_debug()函數(shù)的時(shí)候,可以給第三個(gè)參數(shù)賦值來啟動(dòng)增強(qiáng)型Shockburst模式,這和在本地主文件中的情況是一樣的。
調(diào)用Initialize()函數(shù)后。我們進(jìn)入主程序循環(huán)。在這,我們等待并接收數(shù)據(jù)。一旦接收到數(shù)據(jù),我們通過RF鏈路將數(shù)據(jù)發(fā)送。一旦我們將數(shù)據(jù)發(fā)送后,我們必須注意TX_DS和MAX_RT中斷,保證它們沒有被屏蔽。無論數(shù)據(jù)被成功的發(fā)送或者發(fā)送失敗被忽略(TX_DS和MAX_RT都能夠正常中斷),我們清除中斷,程序又回到循環(huán)的開始。
程序輸出
在圖一里,你可以看到終端的窗口里的程序正在運(yùn)行。24L01互相之間距離很近(大約是6英寸),所以有極高的數(shù)據(jù)發(fā)送成功率。事實(shí)上只有一個(gè)數(shù)據(jù)沒有發(fā)送成功。這個(gè)數(shù)據(jù)在程序的第三行第三個(gè)字節(jié)的“*”處,而這個(gè)星號(hào)代表發(fā)生了MAX_RT 中斷。
結(jié)論
現(xiàn)在,你應(yīng)該對(duì)增強(qiáng)型Shockburst有了更深刻的了解。如果你有任何問題,可以在合適的時(shí)候發(fā)Email給我:brennen@diyembedded.com
第三章:多通道通信
引言
在這一章,我將向你們展示怎么樣設(shè)置nRF24L01來利用它的六個(gè)數(shù)據(jù)通道進(jìn)行通信。這對(duì)你們中的要做網(wǎng)狀網(wǎng)絡(luò)和其他應(yīng)用的人來講是很急迫的。和以前的要求一樣,在繼續(xù)學(xué)習(xí)之前,你要熟知前面的章節(jié)(尤其是第零章、第一章)。
數(shù)據(jù)通道的構(gòu)架
通道的概念非常容易理解。每一個(gè)通道實(shí)質(zhì)上就是一個(gè)接受數(shù)據(jù)的地址(當(dāng)處于接受模式時(shí))。這就意味著24L01可以同時(shí)成為六個(gè)不同的數(shù)據(jù)接受者。
你會(huì)問,這對(duì)你有什么好處呢?雖然有一些多通道通信的用途,但是我能立即想起來的卻不多。你可以將一個(gè)通道設(shè)置成數(shù)據(jù)通道,同時(shí)你可以將另一個(gè)設(shè)置成控制通道。你也可能讓一個(gè)接受通道有不同的功能,讓它完成相當(dāng)于它接受數(shù)據(jù)的那個(gè)通道的工作。你的想象也僅限于此。
當(dāng)你使用多通道時(shí)有幾點(diǎn)要時(shí)刻注意。首先,所有的通道到用相同的RF信道(無論用哪個(gè)信道都可以在RF_CH寄存器中設(shè)置)。如果你使用增強(qiáng)型 Shockburst模式。為了收到應(yīng)答信號(hào),發(fā)送端的發(fā)送地址和通道0的接受地址(分別存在TX_ADDR和RX_ADDR_P0寄存器中)必須相同。這是一項(xiàng)繁瑣的工作,因?yàn)槟阆胍獙?shù)據(jù)發(fā)往不同的地址必須要改變兩個(gè)地址。但是如果使用nRF24L01程序庫,若你準(zhǔn)備改變發(fā)送地址,則只需要幾行代碼就可以改變RX_ADDR_P0寄存器中的地址。正如旁白所言,在本章并不使用增強(qiáng)型Shockburst模式但一樣可以將問題解釋的盡可能清楚。
多輸入多輸出
在本章,所有的設(shè)置和在第一章或者第二章中是一樣的。這包括將一個(gè)計(jì)算機(jī)網(wǎng)絡(luò)的節(jié)點(diǎn)(uC 和 24L01))連接到你PC機(jī)上的型號(hào)為9600-N-1的串口,并且沒有流量控制。其他的節(jié)點(diǎn)基本上是獨(dú)立的。
在本章,我們的目標(biāo)是測(cè)試遠(yuǎn)程單位的每一個(gè)從本地單元發(fā)來的數(shù)據(jù),并且把統(tǒng)計(jì)結(jié)果顯示出來。在操作中,本地單元會(huì)將它的發(fā)射地址和遠(yuǎn)程單元通道0的接收地址設(shè)置成一樣的。然后發(fā)送一個(gè)字節(jié),等待接收方將字節(jié)發(fā)回。如果返回字節(jié)和發(fā)送字節(jié)是一樣的,那么就可以說我們的測(cè)試是成功的。這樣的操作會(huì)連續(xù)做5次,整個(gè)進(jìn)程是對(duì)24L01的其它五個(gè)通道進(jìn)行測(cè)試,結(jié)果都會(huì)被記錄下來。最后,全部的統(tǒng)計(jì)結(jié)果會(huì)按照進(jìn)行計(jì)算,24L01會(huì)將每個(gè)數(shù)據(jù)通道傳輸?shù)慕Y(jié)果和全部得分顯示在屏幕上。
本章我所用的硬件
本章我用的硬件和在第一章里用的是一樣的。沒有任何增減,只要你在學(xué)第一章的時(shí)候讓硬件工作,那么在這一章里你肯定可以讓它工作。
本章軟件描述
情況和需要的硬件類似,本章所需要的軟件和第一章的是一樣的,如果你已經(jīng)運(yùn)行過了,那么在本章中,你將有非常清晰的思路。
本地主文件:maintutorial2local.c
這個(gè)是本地單位的主驅(qū)動(dòng)文件。這個(gè)文件是在第一章的主文件的基礎(chǔ)上編制而成。因?yàn)橐褂枚嗤ǖ劳ㄐ�,所以文件中有相�?dāng)一部分是需要修改的。
首先,頭文件和宏定義是一樣的。從程序的34行開始,我們會(huì)添加一些新的代碼。第一個(gè)要添加的是Ping()函數(shù)。它會(huì)按照剛才我們敘述的那樣工作:向發(fā)送端發(fā)送一個(gè)字節(jié)的數(shù)據(jù),然后等待對(duì)方回發(fā)。除了用發(fā)送字節(jié)0xFF的操作代替讀取從UART傳來的數(shù)據(jù)的操作外,其他的本程序的內(nèi)容和第一章的內(nèi)容是一樣的。在程序的36行和37行要進(jìn)行一些設(shè)置,包括:進(jìn)行測(cè)試的次數(shù),每個(gè)通道進(jìn)行測(cè)試的次數(shù),以及在兩個(gè)測(cè)試之間的時(shí)間間隔。
在主函數(shù)中,我們通過定義一些變量來計(jì)算次數(shù)、存儲(chǔ)每個(gè)通道的成功測(cè)試的結(jié)果、當(dāng)前的發(fā)送地址以及總共的成功測(cè)試。仍然要調(diào)用Initialize() 函數(shù),對(duì)本地24L01的設(shè)置和第一章的是一樣的(包括發(fā)送地址,發(fā)送數(shù)據(jù)一個(gè)字節(jié),常規(guī)Shockburst模式)。
調(diào)用Initialize() 函數(shù)后,我們要修改一下主程序循環(huán)。首先,我們將每個(gè)通道成功測(cè)試次數(shù)設(shè)置為0。然后打出一條信息,讓用戶知道我們已經(jīng)開始檢測(cè)了。
接下來的循環(huán)是用來執(zhí)行對(duì)每個(gè)通道的檢測(cè)的。循環(huán)要執(zhí)行六次,每一次檢測(cè)一個(gè)通道。首先,switch語句設(shè)定了要重復(fù)的次數(shù),在每次重復(fù)的時(shí)候讓本地單位的發(fā)射地址和遠(yuǎn)程單位的接收通道的地址一致。通道0和通道1的地址都需要進(jìn)行設(shè)定,但是對(duì)于通道2-5只需要對(duì)最低有效位(LSB)進(jìn)行設(shè)置,因?yàn)樗鼈兊刂返母呶缓屯ǖ?是一樣的,而通道1的地址已經(jīng)加載到了TX_ADDR寄存器中。發(fā)送地址設(shè)置完成后,檢測(cè)通道的次數(shù)賦值在變量NUM_PINGS中(默認(rèn)值是5)。如果測(cè)試成功一次,計(jì)數(shù)的變量就會(huì)加1。最后通道檢測(cè)的統(tǒng)計(jì)結(jié)果會(huì)顯示出來。
一旦所有的通道檢測(cè)完畢后,我們打出一條信息來說明對(duì)于總共的測(cè)試共有多少次是成功的。然后我們將變量PING_DELAY中的延時(shí)時(shí)間增加用LED來顯示循環(huán)結(jié)束。重復(fù)執(zhí)行主循環(huán)即可。
遠(yuǎn)程主文件:maintutorial3remote.c
和第二章的遠(yuǎn)程主文件一樣,maintutorial3remote.c和第一章所用的主文件基本類似。唯一的不同是在這里我們使得六個(gè)數(shù)據(jù)通道都能夠工作,這樣可以進(jìn)行多通道通信。
這些差異表現(xiàn)在程序的71行到91行。首先要調(diào)用nrf24l01_initialize()函數(shù)。在調(diào)用函數(shù)的第一行,我們對(duì)CONFIG寄存器進(jìn)行設(shè)置:以字節(jié)為單位的循環(huán)冗余校驗(yàn),選定上電模式,接收模式。第二行取值為真時(shí),RX功能就能夠立即啟動(dòng)。第三行設(shè)置各通道為非自動(dòng)應(yīng)答,第四行開通所有通道。除了RX_PW_P*寄存器,剩余的寄存器都保持在它們的默認(rèn)初態(tài)。將它們?cè)O(shè)置成能接收一個(gè)字節(jié)的數(shù)據(jù)存量,這樣就能用它們接收數(shù)據(jù)了。
如果你沒有學(xué)習(xí)過第一章,這里有一個(gè)對(duì)程序的詳細(xì)說明。等到24L01接收到數(shù)據(jù)程序就開始工作。接收數(shù)據(jù)完畢后,它會(huì)向本地單位的通道0回發(fā)數(shù)據(jù)。然后程序回到循環(huán)的開始繼續(xù)等待數(shù)據(jù)。
遠(yuǎn)程單位可以通過所有的通道接收數(shù)據(jù),對(duì)數(shù)據(jù)處理的差異根據(jù)接收數(shù)據(jù)通道的不同而不同(當(dāng)然在這里這個(gè)例子不會(huì)演示)。程序中是這樣實(shí)現(xiàn)的,函數(shù) nrf24l01_read_rx_payload()會(huì)返回狀態(tài)寄存器的值,值中包含當(dāng)前通信數(shù)據(jù)的數(shù)據(jù)通道的數(shù)量。將這個(gè)值賦給函數(shù) nrf24l01_get_rx_pipe_from_status(),這樣就可以根據(jù)發(fā)送來的數(shù)據(jù)返回給變量pipe一個(gè)數(shù)值�?紤]下面的這個(gè)例子:
unsigned char data, status, pipe;
status = nrf24l01_read_rx_payload(&data, 1);
pipe = nrf24l01_get_rx_pipe_from_status(status);
switch(pipe)
{
case 0://process case 0
break;
case 1://process case 1
break;
case 2://process case 2
break;
default://process any other pipe
}
這段代碼可以讀取發(fā)送過來的數(shù)據(jù)(假定它是存在的,所以你應(yīng)該編制代碼來確保RX FIFO寄存器中有數(shù)據(jù))和狀態(tài)寄存器中的狀態(tài)值。然后就得到了基于狀態(tài)寄存器的通道編號(hào),用switch語句就可處理這些數(shù)據(jù)。我很喜歡用switch語句來處理離散的數(shù)值問題。當(dāng)然,你也可以用if語句或者C語言中的其它結(jié)構(gòu)語句。
程序輸出
在圖一里,你可以看到終端的窗口里的程序正在運(yùn)行。24L01互相之間距離很近(大約是6英寸),所以有極高的數(shù)據(jù)發(fā)送成功率(和第一章、第二章的情況一樣)�?梢钥吹綄�(duì)通道的所有測(cè)試結(jié)果。
圖一:終端輸出窗口
結(jié)論
現(xiàn)在,你應(yīng)該對(duì)24L01提供的六個(gè)數(shù)據(jù)通道進(jìn)行多通道通信有了更深刻的了解。如果你有任何問題,可以在合適的時(shí)候發(fā)Email給我:brennen@diyembedded.com