檢測信道占用的需求場景
在使用nRF24L01模塊做一對多或多對一的組網通信中,大家都會擔心一個問題就是在發送的時候,希望不要有其他的模塊也進行發送,因為這樣就會使無線信號發生碰撞,信道被堵塞,造成通信失敗。
為了避免這種情況發生,就希望在發送前能知道當前信道是否處於空閑,如果空閑就發送,否則就等待一會,直到空閑下來再執行發送。利用這個機制,可以很大程度上規避碰撞的發生。
在nRF24L01+中怎樣知道信道被占用了
在nRF24L01+中有個RSSI寄存器,地址是0x09,該寄存器的0號位是代表當前信道信號強度的。當接收信號強度小於-60dBm時0號位為0,大於-60dBm時為1,該寄存器7-1號位是保留位,固定為0。這樣我們通過直接讀取該寄存器的值是0還是大於0就知道信道是否被占用了。
下面是該寄存器在一些模塊廠家官方例程里的定義:
#define RPD 0x09 //接收功率檢測寄存器
或
#define RSSI 0x09 //接收功率檢測寄存器
下面是通過讀寄存器函數讀取該寄存器的狀態值的代碼:
StatusRPD = nRF24L01P_Read_Reg(RPD); //如果定義的是RSSI,那語句中RPD換成RSSI
通過上面語句得到的StatusRPD值,如果大於0則是信道被占用,在邏輯代碼中通過這個判斷就可以識別信道是否被占用了。也可以在發送前用循環等待這個值的變化,直到為0時進入發送狀態。如下面的代碼:
while(nRF24L01P_Read_Reg(RPD));
為什么用循環等待,有時候會死循環(一直返回1)
在實際應用中,使用上述方法的確可以得到當前的信道信號強度,達到判斷信道是否占用的目的。但是在循環等待的時候,偶爾會出現死循環的現象。也就是讀回來的狀態值一直是1,但是的確沒有模塊在發送,已經將其他模塊全部斷電了,周圍也沒有強信號干擾,那么問題出在哪里呢?
仔細查看芯片手冊,只找到下面這段話:
在接收模式下,可以通過RSSI寄存器檢測接收信號功率。當接收到的信號強度大於-60dBm時,RSSI寄存器的RSSI位的值將被設置為1。否則,RSSI=0。。RSSI寄存器的更新方法有兩種:當接收到有效的數據包后,RSSI會自動更新,此外,將芯片從RX模式換到Standby模式時RSSI也會自動更新。RSSI的值會隨溫度的變化而變化,范圍在±5dBm以內
經過仔細分析和反復試驗,理解了這段話所描述的具體內涵:
1、這個信號強度檢測必須在接收模式下進行,在發送模式下是不准確的。
2、並不是無論什么情況下,這個寄存器都會被更新,只有CE由1變為0時才更新一次;或者在接收到有效數據的時候,會自動更為1。
3、當收到有效數據將該寄存器置1后,只有將接收FIFO寄存器的數據讀出后,才會變為0,否則你變化幾次CE都無效(這是手冊沒有提到的,多數會踩到這個坑)。
上面的死循環情況一般發生在執行發送的前夕,剛好收到一個有效數據時,RSSI寄存器被置1,而代碼正在處理發送,又沒有去讀出數據,所以就一直保持着1,所以循環條件一直滿足,就成了死循環了。
解決辦法建議是在檢測到為RSSI為1的時候,判斷一下是否收到數據,如果收到數據先讀出來,至於讀出來的數據要不要處理,根據您自己的業務邏輯決定即可。然后操作一次CE引腳,再次更新檢測一下是否有信號占用信道。此方法經過實際應用是有效的。