nRF24L01+不能接收或接收偶爾異常等問題實戰分享


nRF24L01+接收異常問題綜述

在調試nRF24L01+無線收發模塊的時候,最具標志性的環節就是在接收端可以收到數據。在實際應用調試中,會出現很多意想不到的情況,造成nRF24L01+模塊接收端無法收到發送端發出的數據。

根據以往對nRF24L01+模塊的N多次調試的經驗,總結大致可以分為如下幾種情況:
現象1:一次也收不到發送端發送的數據
現象2:只能在發送端或接收端重新上電的時候收到一次
現象3:偶爾在發送完數據轉為接收模式后就不能接收了
現象4:大功率帶PA的模塊工作一段時間就不能接收了
現象5:無規律偶發不能接收
下面將根據這5中現象分別有針對性的分享實戰中的解決方法。

如何快速判斷nRF24L01+通信失敗問題是出在接收端

在調試nRF24L01+模塊通信過程中,當發生通信失敗時,如何才能快速確定問題是出在接收端,而不是發送端的問題呢?這里給他家推薦個方法:
首先使用廠家提供的測試代碼,不做任何改動,燒錄到兩個模塊中,如果硬件電路沒有問題,一般都是可以正常發送接收的,如發生不能通信,請檢查單片機型號變動帶來的IO口設置是否正確,千萬不要隨意改動邏輯代碼和nRF24L01+驅動部分代碼,只查找IO口相關配置的宏定義修改正確即可。

如果這樣可以通信,說明模塊硬件電路沒有問題。否則問題出在硬件電路上,仔細檢查電路部分,參見下面的“正常接收數據時硬件電路必需的基本保障”。

當利用廠家提供的測試代碼可以通信之后,把作為接收端的模塊里的代碼燒錄成自己的代碼。燒錄前參照廠家測試代碼中的接收配置部分,更改你項目中的頻道、速率、地址、是否自動應答等,與測試項目保持一致。

經過這樣調整后,如果還是收不到,那就是你的接收端代碼有問題,參見下面的幾種現象。

正常接收數據時硬件電路必需的基本保障

在調試代碼前,首先要保證硬件電路是正常的,下面是必需具備的前提條件:
1、單片機與模塊之間的IO口電路連接正常。單片機代碼SPI腳序配置與電路連接實際相符。
2、nRF24L01+模塊電源腳附近(越近越好)有濾波電容,最好是兩個,一個104,一個22uF或以上。
3、處於接收模式時,CE引腳應為高電平(足夠高,3.1V以上)。
4、電源電壓穩定在3.3V,波紋低於80mV,波紋越小越好。

以上條件必需具備,否則不能接收那就再正常不過了。

現象1:一次也收不到發送端發送的數據

這種現象多數發生在我們最初調試模塊的時候,那么我們要分兩個方向來排除。

先排除硬件部分,參照上面“正常接收數據時硬件電路必需的基本保障”一節提到的,仔細檢查有沒有不能滿足的。根據以往經驗,最容易被大家忽視的就是nRF24L01+模塊電源腳附近的兩個電容,如果已經有了,那也更換一套新的試試,排除元件本身問題,最好用電容表或萬用表電容檔測量一下。如果有但是距離模塊不是很近(應小於0.5CM的距離),最好直接在模塊引腳上先臨時焊上一個,以排除這個原因。

然后測量CE腳是否為3.3V,如果是大於0V且低於3.1V以下,說明CE電平不正常,應檢查單片機IO口的上拉能力。如果單片機IO口模式是可以配置上拉模式的(如STC單片機),請使用推挽模式。如果單片機是不能配置上拉模式的,請加上拉電阻,以滿足在CE腳拉高時,能維持到3.1V以上的電平。

如果硬件部分沒有問題,CE腳也能正常上拉,那重點檢查設置接收模式的代碼,參考代碼如下:

/*-----------------------------------------------------------------------------
函數名稱:NRF24_RxMode
輸入參數:pSelfAddr:本機硬件地址;ch:通信頻道
功能描述:設置nRF24L01+工作在接收模式
------------------------------------------------------------------------------*/
void NRF24_RxMode(U8 *pSelfAddr, U8 ch){
	CE = 0;																	// 拉低CE進入配置模式
	nRF24L01P_Write_Buf(WRITE_REG + RX_ADDR_P0, pSelfAddr, TX_ADR_WIDTH);	// 設置接收設備自己的通道0地址
	nRF24L01P_Write_Reg(WRITE_REG + EN_AA, 0x01);               			// 使能接收通道0自動應答
	nRF24L01P_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);           			// 使能接收通道0
	nRF24L01P_Write_Reg(WRITE_REG + RF_CH, ch);                 			// 選擇射頻通道為變量ch
	nRF24L01P_Write_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  			// 設置接收通道0有效數據寬度
	nRF24L01P_Write_Reg(WRITE_REG + RF_SETUP, RF_date_rate|dBm);            // 設置數據傳輸率、發射功率      
	nRF24L01P_Write_Reg(WRITE_REG + CONFIG, 0x0f);              			// 使能16位CRC校驗,上電,接收模式
	nRF24L01P_Write_Reg(WRITE_REG + STATUS, 0xff);  						// 清除所有的中斷標志位
	CE = 1;                                            						// 拉高CE啟動接收設備
}

在上述代碼中,要注意:
pSelfAddr:接收端自己的硬件設備地址,要與發送端的發送目標地址一致,否則收不到。
ch:射頻工作頻道號,可設置值為1-125,要與發送端保持一致,否則收不到。
RF_date_rate:數據的傳輸速率,可設置值為0x00、0x08、0x20,分別代表1Mbds、2Mbds、250Kbds,必須與發送端的設置保持一致,否則收不到。
dBm:發射功率,在接收模式下沒有實際作用,但設置值不能大於0x07,否則影響到速率的配置位。
TX_ADR_WIDTH:描述地址寬度,必須與發送端一致,建議測試時設置為5。
TX_PLOAD_WIDTH:描述傳輸數據寬度,必須與發送端一致,建議測試時設置為32。

現象2:只能在發送端或接收端重新上電的時候收到一次

原因1:一直發送相同的數據包,也就是每次發送的數據都是相同。
nRF24L01+的接收端首先是根據PID位來區分數據包是否相同的,如果第二次接收的PID與第一次相同,那就視為數據重發,會直接丟棄不處理,也不會產生接收成功的中斷。
數據手冊中說這個PID是每次寫發送FIFO的時候會自動累加,也就是每寫一次就會改變一次,但在多次的實驗中(使用的是SI24R1模塊),發現如果兩次寫入的是相同的內容,PID並沒有變化,接收端會直接拋棄后面接收到的相同數據。
這樣就產生了只能接收成功一次,然后就收不到了這個現象。重新上電后,所有寄存器的值都是重新配置的,之前的PID也不一樣了,所以就可以再接收到一次,之后就又不能接收了。
解決方法:在你發送的數據內容中選一個字節讓它每次都是變的,就不會出現了。

原因2、發送端發送速度比較快而連續,接收端處理比較慢切沒有清接收FIFO。
發送端連續發送3組數據后,接收端的96字節緩沖器就會填滿,這個時候如果沒有讀出,那就不會再接收了。發送端仍然以同樣的速度再發送幾個,在這個時候接收端雖然讀出一組32個字節,如果處理的比較慢,那很快接收緩沖區可能被又填滿了。
而接收端處理完邏輯代碼再去查接收數據的時候,如中間有過模式轉換,清除了中斷標志,因沒有再產生接收成功的中斷標志(使用中斷IRQ首先判斷接收成功的,接收緩沖區滿就不會再產生中斷了),則認為沒有收到數據,所以就再也收不到數據了。
這樣就產生了只能接收一次就收不到了這個現象,重新上電后,所有寄存器的值都是重新配置的,中斷和緩沖器都是被清除過,所以可以再接收。
解決方法:在每次收到數據讀出之后,在處理邏輯完成后,如果經過接收發送模式轉換的,轉換后清除一下接收FIFO。

原因3、沒有及時清除中斷標志,接收一次后IRQ一直維持在低電平。
如果單片機使用外部中斷,在接收到一次有效數據沒有清除中斷標志的話,再收到有效數據就不會再產生下一個中斷。
解決方法:接收成功一次,清除一次中斷。
下面單片機通過查詢IRQ的方式識別是否收到數據的代碼,結合中斷與查詢兩種方式:

/*-----------------------------------------------------------------------------
函數名稱:RF24_RxData
返回數據:是否收到數據,1收到,0未收到
功能描述:nRF24L01P+判斷是否收到數據,若收到直接取出,應在主循環中調用
------------------------------------------------------------------------------*/
bit RF24_RxData(){
	U8 state;

	if(IRQ == 0){														//有中斷觸發,提高CPU效率,減少SPI通訊量
		state = nRF24L01P_Read_Reg(STATUS);								//讀取狀態寄存器的值    	  
		nRF24L01P_Write_Reg(WR_STATUS, state);							//清除RX_DS中斷標志
		if(state & RX_DR)												//接收到數據
		{
			nRF24L01P_Read_Buf(RD_RX_PLOAD, RF24Buf, TX_PLOAD_WIDTH);	//讀取數據
			nRF24L01P_Write_Reg(FLUSH_RX,0xFF);							//清除RX FIFO寄存器
			return TRUE; 
		}
	}	   																
	return FALSE;														//沒收到任何數據
}

以上代碼注意“清除RX_DS中斷標志”和“清除RX FIFO寄存器”的作用,保證每次設置為接收的時候,都能使nRF24L01+全新開始接收。

現象3:偶爾在發送完數據轉為接收模式后就不能接收了

原因1、發送失敗后,沒有清除發送FIFO寄存器,造成轉接收模式時異常。
nRF24L01+在發送達到最大發送次數仍然沒有收到ACK的時候(啟用ACK的情況下),是不會自動清除發送緩沖區的。而在發送模式轉到待機模式的時候,根據手冊的狀態圖,必須是發送緩沖區沒有數據的情況下,CE=0才可進入待機模式。在待機模式,才可以設置為接收模式。但是數據手冊中文字介紹部分又說任何狀態下,只要CE=0就可以進入待機模式,出現了描述矛盾。
我們在調試的時候,遇到了這個問題,經過N多次實驗,在發送緩沖區還有數據的情況下,直接轉接收模式,是會不穩定的,所以在發送結束后,如果是發送次數達到了最大值不再繼續發送,一定要記得清洗TX_FIFO。
解決方法:發送完判斷發送狀態,如果是達到最大發送次數,則清洗TX_FIFO。
參考代碼如下:

/*-----------------------------------------------------------------------------
函數名稱:RF24_TxData
輸入參數:*buf:待發送的數據緩沖區指針
返回數據:是否發送成功,1發送成功,0發送失敗
功能描述:nRF24L01P+發送數據
------------------------------------------------------------------------------*/
bit RF24_TxData(U8 *buf){
	U8 state;

	CE = 0;													//使能24L01配置
	nRF24L01P_Write_Buf(WR_TX_PLOAD, buf, TX_PLOAD_WIDTH);	//寫數據到TX FIFO,32個字節
	CE = 1;													//使能發送	   

	while(IRQ == 1);										//等待發送完成
	state=nRF24L01P_Read_Reg(STATUS);  						//讀取狀態寄存器的值	   
	nRF24L01P_Write_Reg(WR_STATUS, state); 					//清除TX_DS或MAX_RT中斷標志
	if(state&MAX_RT)
		nRF24L01P_Write_Reg(FLUSH_TX, 0xff);				//達到最大發送次數,清除TX FIFO寄存器
	if(state&TX_DS)
		return TRUE;										//發送完成	
	return FALSE;											//發送失敗
}

原因2、在發送完一次就自動轉為接收模式的代碼邏輯下,循環發送時,中間收到3次及以上的數據。
因在發送一組數據就會自動置為接收(這樣寫的邏輯也是有好處的,可以避免某些地方忘記置為接收),那在發送下一組數據之前,是有一段時間間隔的,這個時候如果有數據進來,是可以接收的。但是上層代碼並沒有處理接收數據,也就是沒有去讀,而是循環發送完才會進入處理接收階段。這樣如果在循環發送期間受到3次數據,接收緩沖區就滿了,而產生的中斷也在每次轉換模式的時候都被清除了。等循環結束,再判斷是否有接收到數據的時候,因接收緩沖區滿而不能再產生接收中斷了,所以不能再收到數據了。
解決方法 :在每次設置接收模式的時候,清洗一下RX_FIFO。

原因3、置接收模式的代碼沒有操作所有相關寄存器,其他代碼更改過相關寄存器。
在本次置為接收模式之前,其他代碼可能更改過與接收相關的寄存器,造成與發送端不一致或更改為錯誤的值,造成不能正常接收。
解決方法:置為接收模式的函數,完整的操作一遍相關寄存器,這樣可以規避這種問題。

現象4:大功率帶PA的模塊工作一段時間就不能接收了

經過測試多個廠家的多款不同nRF24L01+模塊,發現帶屏蔽罩並帶功率放大的模塊,在近距離密集應用的時候,損壞率比較高。PA會先過熱然后接收不正常,接收模式下電流大增,表面溫度會燙手。
建議勁量不要使用帶PA的,如果必需使用,不要密集應用,盡量使用板載天線並不帶屏蔽罩的。
這個是目前的實際應用測試經驗,不代表全部是這樣,不排除有的廠家帶屏蔽罩的會更好用。

現象5:無規律偶發不能接收

以上問題都排除的話,如果還是偶爾會發生不能接收的情況,那就重點檢查電源和濾波電容,建議更換一個電源,保證電源的低波紋,電壓的穩定性要好。濾波電容質量要好,要盡量靠近模塊,越近越好。

關於nRF24L01+作為接收端的的常見問題,先分享到這里,其他方面另外分享。


免責聲明!

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



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