歷盡千辛萬苦,失敗了無數回……終于把NRF24L01+所有通道全調通了。在調試過程中,總結了一些經驗。(下載成功計數又刷了幾百~~~~(T o T)~~~~) 總體來看,NRF24L01+模塊最麻煩的就是寄存器配置問題了,搞定了各個寄存器的配置,模塊就通了。而通道設置也到處是寄存器的身影,一不小心就會通信失敗,所以在準備調試NRF24L01+前一定要準備好資料。如果失敗了,不要著急,一點一點來,排除所有可能的故障,如果人品不錯的話,一會就搞定了……(╮(╯▽╰)╭我是沒這個運氣了……) 很多人卡在通道調試這里,那就說說NRF24L01+通道的事情吧,一共有6個通道(數據手冊里的pipe),其中通道0最容易了,去網上隨便找個程序就搞定,比如我找的這個,連通道1也稍帶上了。關鍵是剩下的那幾個,尤其是通道2(2~5是極其相似的),在網上看到了很多人調不通,可是又沒有專門的解決辦法,只有多對一的通信范例,最后還是不知道問題出在哪。今天我試了一下,確實不易……但是經過大量實驗,發現了很多不容易想到問題,都是不能調通的原因。
通道1調試: 發送部分: 通道1其實不只是把通道0程序里有關通道0的部分直接改成通道1的那么簡單,別的通道更麻煩一點,這就是很多人調不通的原因。我剛開始也是直接改的,果然失敗了……(⊙﹏⊙)b……然后又去看原來的程序,看到發送的數據不論是哪個通道,都裝給了通道0的地址,不知道為什么,但是實驗證明,確實必須這樣……其中TX_ADDR地址要和發送的地址一樣。 1. /*裝載數據*/ 2. SPI_Write_Buf(WRITE_REG + TX_ADDR, (uint8_t*)ADDRn, TX_ADR_WIDTH);//寫TX節點地址 3. SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK
不論通道是幾,其中要改動的只有(uint8_t*)ADDRn這個東西,其實就是對應的通道地址。不要動RX_ADDR_P0。 然后是寄存器配置,原貼里的注釋有這么一行:“要配置第N個的通道,前N個通道也必須被配置,要不然配置不成功。”瞬間恍然大悟( ⊙ o ⊙ )!,上回太心急,拿了程序就走了……正如原帖代碼所示: 1. SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f); //使能通道所有的自動應答 2. SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);//使能通道所有的接收地址
這個是發送函數void NRF24L01_Init_TX(uint8_t*ADDRn)里的一段,作者把所有通道都打開了。其實經過試驗,這里的通道必須把當前配置的通道和它前面的都配置。比如現在是通道1,就要至少使能為0x03,而不能是只打開通道1的0x02。 下面的選擇通道n有效數據寬度,實驗證明沒有用,我一次只發1個字節,寬度設置成32,發過來還是1個字節……所以可以去掉。不過留著也不會出錯。
接收部分: 首先經過試驗,不設置TX_ADDR和RX_ADDR_P0沒出錯,所以可以去掉。 但是然后發生了奇怪的問題,經過大量試驗,我這里通道1地址設置完了以后還要重新設置低位地址,不然沒法調通,不知道為什么。如代碼所示: SPI_Write_Buf(WRITE_REG +RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK SPI_Write_Buf(WRITE_REG +RX_ADDR_P1, RX_ADDRESS1, 1); //設置RX節點地址,主要為了使能ACK (奇怪的NRF24L01+(O__O"…),然后我想……我刪掉的部分可能在別人那里就不一樣了……可能。如果最后調不通就把我刪掉的加上試試。) 后面的就是很正常的設置了,可以只開對應通道,比如通道1:0x02,對應數據寬度什么的……不用管別的通道怎么樣。
通道2~5調試: 發送部分: 和通道1的調試方法一樣,注意: 1.不要動RX_ADDR_P0。 2.配置第N個的通道,前N個通道也必須被配置。
接收部分: 也和通道1一樣……但是需要注意的是數據地址的寫入,在定義數據地址的時候,根據數據手冊,通道2~5與通道1共用32位地址,只有低8位可以改變且不能一樣。如圖:
360截圖20150726222239348.jpg (63.93 KB, 下載次數: 433)
下載附件
2015-7-26 22:51 上傳
所以改通道2~5地址的話只能通過改通道1的,然后寫入對應通道低8位地址。數據手冊里的RX_ADDR_P1表格里還有一句話:LSByteis written first。(先寫最低位。)這很重要。所以根據寫入字節的程序,地址要定義為:
360截圖20150726223241252.jpg (29.87 KB, 下載次數: 431)
下載附件
2015-7-26 22:51 上傳
這樣,看懂沒?除了通道0,只有地址數組的第0個元素在變化。網上很多程序是最后一個元素在變,好像數據手冊的表里似的,這樣就會導致只有通道0和1能調通,別的不能用。因為通道0和1是40位地址寫入的,隨便改,但是后面的地址必須只能改低位,如果高低位弄混了,改錯了當然就不能調通了。當然我(Copy)的程序是先寫第0個元素,如果別人的程序不一樣那要另當別論。 知道了順序以后就好辦了,但是要注意寫入的時候先寫通道1的40位地址,再寫所用通道的低8位地址,但是經過多次試驗,那32位不要重復寫入,數值一樣也不行。這樣就OK,程序如下: SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK SPI_Write_Buf(WRITE_REG + RX_ADDR_P2, RX_ADDRESS2, 1); //設置RX節點地址,主要為了使能ACK(地址長度只能是1,不能多寫,寫一樣的值也不行) 然后剩下的就簡單了,數據通道和數據寬度該是幾就設置幾,不用管別的通道。
對,結束了,其實并不難,只是可能有的問題沒想到而已……我把原程序重新改了一下,進行了通道變換的封裝,輸入對應通道就可以在對應通道上點對點通信了,像這樣: - /***************************************************************************
- 函數名稱:void NRF24L01_Init_TX(uchar pipe)
- 函數功能:初始化NRF24L01
- 函數備注:在調用NRF24L01作為發射時,都要先調用該函數對NRF24L01進行初始化
- ***************************************************************************/
- void NRF24L01_Init_TX(uchar pipe)//輸入通道值
- {
- /*待機模式*/
- CE=0;
- CSN=1;
- SCK=0;
- /*裝載數據*/
- SPI_Write_Buf(WRITE_REG + TX_ADDR, pipe_add[pipe], TX_ADR_WIDTH);//寫TX節點地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, pipe_add[pipe], RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 0x3F); //使能所有通道自動應答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3F);//使能所有通道的接收地址(這兩項定義的通道數不得小于當前使用的通道數,奇怪的NRF24L01+(O__O "…))
- SPI_Write_Reg(WRITE_REG + RF_CH, 40);//設置RF通道為40 收發必須一致!
- SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0xFF);//自動重發 4000+86us 重發15次
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F); //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟 收發必須一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,發送模式,開啟所有中斷
- }
- /***************************************************************************
- 函數名稱:void NRF24L01_Init_RX(uchar pipe)
- 函數功能:初始化NRF24L01
- 函數備注:在調用NRF24L01作為接收時,都要先調用該函數對NRF24L01進行初始化
- ***************************************************************************/
- void NRF24L01_Init_RX(uchar pipe)//輸入通道值
- {
- /*待機模式*/
- CE=0;
- CSN=1;
- SCK=0;
- /*裝載數據*/
- if(pipe == 0) //通道,對應設置40位地址
- {
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS0, RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK
- SPI_Write_Buf(WRITE_REG + (RX_ADDR_P0+pipe), RX_ADDRESS0+pipe, RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK
- }
- else //其他通道,對應設置通道1公共地址和相應8位地址
- {
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); //設置RX節點地址,主要為了使能ACK
- SPI_Write_Buf(WRITE_REG + (RX_ADDR_P0+pipe), pipe_add[pipe], 1); //設置RX節點地址,主要為了使能ACK(地址長度只能是1,不能多寫,寫一樣的值也不行)
- }
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 1<<pipe);//使能通道的自動應答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 1<<pipe); //使能通道的接收地址
- SPI_Write_Reg(WRITE_REG + RF_CH, 40); //設置RF通道為40 收發必須一致!
- SPI_Write_Reg(WRITE_REG + (RX_PW_P0+pipe), RX_PLOAD_WIDTH); //選擇通道的有效數據寬度
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F); //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟 收發必須一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0F); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
- }
復制代碼
親測通道0~5均可用。如果想多對一通信,只需增加相應通道即可,反正配置方法已經告訴你了,這下沒問題了吧。O(∩_∩)O哈哈~。當然,這樣做了沒問題卻還是調不通的朋友可以在論壇里搜索,搜不到就去百度,百度不到可以用雅虎,不行再用谷歌,不行再用搜狗,不行再用360搜索,不行再用好搜,不行再用搜搜,不行再用Bing……要是還不行,可以選擇聯系我……w(゚Д゚)w。
附上我稍作修改后的代碼,太長,而且有3段,就打包了。
NRF24L01 .zip
(36.7 KB, 下載次數: 780)
2015-7-26 23:01 上傳
點擊文件名下載附件
代碼~ 下載積分: 黑幣 -5
NRF24L01 資料.rar
(10.58 MB, 下載次數: 451)
2015-7-26 23:02 上傳
點擊文件名下載附件
某寶找的資料,比百度強多了…… 下載積分: 黑幣 -5
|