nRF24L01+啟用自動應答ACK及自動重發的實戰分享


ACK模式(自動應答)功能的官方說明

  當用W_TX_PAYLOAD命令對發送端TX FIFO寫數據時,將數據打包后,數據包中包控制字段NO_ACK 標志位復位。接收端接收到一幀有效數據后, 產生RX_DR中斷后,會自動發送一幀ACK信號,發送端接收到ACK信號,則自動清除TX FIFO數據並產生TX_DS發射中斷,表明此次通信成功。

  接收端在發送ACK信號時,取接收管道地址作為目標地址來發送ACK信號,所以發送端需要設置接收管道0地址與自身發送地址相同,以便接收ACK信號。

  如果發送端在ARD時間內沒有接收到ACK信號,則重新發送上一幀數據。當重發次數達到最大,仍沒有收到確認信號時,發送端產生MAX_RT中斷。MAX_RT中斷在清除之前不能進行下一步的數據發送。所有中斷通過對狀態寄存器進行寫操作來清除。PLOS_CNT寄存器在每產生一個MAX_RT中斷后加1,用來記錄當前頻段下,丟失的數據包的數量。ARC_CNT寄存器記錄當前數據重發的次數,在發送一包新數據時使其復位。最大重發次數與ARD時間通過SETUP_RETR寄存器來進行配置。接收端開啟自動回復ACK信號由EN_AA寄存器來控制。

  發送端每當發射一個新數據包,數據對應的PID自動加1,因此發送的相鄰的兩個數據包中,PID應互不相同。如果鏈路中連續幾幀數據丟失,接收端接收到的連續兩幀數據的PID可能相同。

  接收端如果發現接收到數據與上一幀數據PID相同,則比對CRC,如果CRC也相同,則判斷為上一幀數據的重發,將數據丟棄,並重新回復ACK信號。圖4.4發送端第一次數據發送沒有接收到ACK信號,進行重發后,接收到ACK信號,數據通信成功完成。

解讀啟用ACK模式必需的寄存器配置

這里只介紹與ACK模式相關的寄存器配置,默認理解為其他配置都正確的情況下。

發送方的必要配置
  nRF24L01+的ACK自動應答功能,原理是在接收方收到數據后立刻自動回復給發送方一個ACK確認數據包,發送方如果收到確認的數據包,認為發送成功,否則認為本次失敗,是否再次發送,決定於自動重發的配置。

  那帶來的疑問是,接收方收到數據后,在回復的時候,是怎樣知道發送方的地址的呢?數據包中並沒有攜帶地址,如果攜帶會多占用5個字節,影響了傳輸有效數據的相對速率。設計團隊最后使用的是在發送時,先將發送方的接收通道0的接收地址設置為要發送的目標地址,這樣執行完發送就立刻等待接收,並自己的地址是與目標地址一樣的。接收方收到數據回復ACK的時候,就不需要知道發送方的地址,按照自己的地址作為目標地址發出即可。因自己處在發送狀態,所以自己不會接收,而發送方這時剛好處在接收狀態,地址剛好是接收方的地址,也是接收方回復時的目標地址,所以發送方可以收到回復的ACK數據。因此下面的這行配置必需存在:

spi_write_buf(RX_ADDR_P0, TX_ADDRESS, 5);		//接收通道0地址和發射地址相同,等待接收來自接收方的ACK數據

  ACK模式的整個工作過程中,自動重發功能為確保數據有效到達起了很大作用。因為無線電信號很難在任何環境下都十分穩定,也極容易受到各種干擾,那么如果一次發送沒有收到ACK數據,就可以認為本次發送失敗。接下來稍等一下可以再次發送,經過多次嘗試,成功率就大大增加了。所以就要啟用自動重發功能,當達到重發次數的上限的時候,仍然沒有收到ACK數據,則宣告本輪發送徹底失敗。因此下面的配置也是必需存在的:

spi_write_reg(SETUP_RETR, 0x15); 		//自動重發延時等待500us,自動重發5次,根據自己需要設置

  SETUP_RETR寄存器的說明見下圖(0x15的二進制是00010101):

接收方的必要配置
  接收方為了可以在收到數據后,執行自動回復功能,需要開啟相應的控制寄存器,否則無法實現自動回復,因為下面這行配置是必需存在的:

spi_write_reg(EN_AA, 0x01);               							//使能接收通道0的自動應答

  如果啟用了ACK功能,那么CRC校驗功能就必須啟用,因為需要避免接收到重復的數據包產生多次接收成功和造成多次回復的現象。因此下面的配置也是必需存在的:

spi_write_reg(CONFIG, 0x0F);              							//CRC使能,16位CRC校驗,開機,接收模式

  CONFIG寄存器的說明見下圖(0x0F的二進制是00001111):

ACK模式的發送過程

  發送方先置為發送模式,以上介紹的發送模式的寄存器也在置為發送模式時配置完畢。
  接下來使用W_TX_PAYLOAD命令寫入待發送的數據,參考代碼如下:

CE = 0;														//CE拉低,使能24L01配置
spi_write_buf(WR_TX_PLOAD, RF24Buf, TX_PLOAD_WIDTH);		//寫數據到TX FIFO,TX_PLOAD_WIDTH個字節
CE = 1;														//CE置高,使能發送

  模塊在發送完發送緩沖區的數據后,自動立刻轉入接收狀態,並將自己的地址臨時修改為剛才發送的目標地址(即接收方地址,因為接收方回復的時候,它的目標地址會是這個),等待接收方回復ACK,收到ACK后產生發送成功TX_DS(0x20)中斷。

  如果在SETUP_RETR寄存器設置的時間間隔內沒有收到ACK回復,將再次發送,直到收到ACK或達到SETUP_RETR寄存器設置的最大發送次數。如達到最大發送次數則產生MAX_RT(0x10)中斷,表示已經嘗試發送到最大次數仍然沒有成功。

  以上狀態都可通過讀狀態寄存器STATUS得到(其實單片機每次與模塊通信,SPI指令返回的都是這個寄存器的值),下圖是STATUS寄存器的說明:

  有關nRF24L01+的ACK模式的調試重點就介紹到這里,其他關於nRF24L01+的問題請看本人博客的其他文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM