[STM32F4xx 學習] SPI與nRF24L01+的應用


前面已經總結過STM32Fxx的特點和傳輸過程,下面以nRF24L01+ 2.4GHz無線收發器為例,來說明如何使用SPI。

 

一、nRF24L01+ 2.4GHz無線收發器的介紹

1. 主要特性

  • 全球2.4GHz ISM頻段操作
  • 250Kbps, 1Mbps, 2Mbps三種空中傳輸速率
  • 超低功耗
  • 輸出功率為 0dBm時發射功耗為11.3mA
  • 空中傳輸速率為2Mbps時接收功耗為13.5mA
  • Power down模式功耗低至900nA, Standby-I模式功耗低至26uA
  • 1.9~3.6V的電壓工作范圍
  • 支持6個接收通道(地址)
  • IO口能承受5V電壓
  • ±60ppm 16MHz晶體振盪器
  • 4×4mm QFN封裝

2. SPI操作時序

2.1 讀操作時序圖

圖1. nRF24L01+ 讀操作時序

①:發送指令+寄存器地址,都是從CSN(片選線,下同)的下降沿開始

②:主機(即STM32F4xx,下同)發送8位指令代碼(C7~C0,下同)

③:不管主機發送何指令,從機(即nRF24L01+,下同)第一字節都會返回狀態寄存器的值(寄存器0x07)

④:從機數據在每一個SCK的上升沿輸出,首先輸出的是第一字節(最低字節)的最高位,...,最后輸出的是最高字節的最低位

⑤:讀取操作都是以CSN的上升沿結束

2.2 寫操作時序

圖2. nRF24L01+ 寫操作時序

①:同讀操作

②:同讀操作

③:同讀操作

④:主機數據在每一個SCK的上升沿寫入從機,首先寫入的是第1個字節的最高位,...,最后寫入的是最后一個字節的最低位

⑤:同讀操作

 

2.3 狀態機

 

圖3. nRF24L01+ 狀態圖

  • Power Down 模式

在該模式下,nRF24L01+的功耗最小,不能進行發送或者接收。但是所有寄存器的值保持不變,SPI處於有效狀態,允許對寄存器,TX/RX FIFO進行操作,PWR_UP(此位在CONFIG寄存器中)清0即進入該狀態。

  • Standby-I 模式

將PWR_UP置1,即進入Standby-I模式,該模式既降低了nRF24L01+的平均功耗,同時又保持盡可能短的啟動時間,將CE置1然后后清0,就可以進入TX/RX模式,然后又返回到Standby-I模式。

  • Standby-II 模式

當nRF24L01+設置為接收機(PTX),並且CE=1,TX FIFO為空時即進入該模式。相比Standby-I模式,這種模式相對耗電,一旦發送FIFO有新數據,就會立即將數據打包發送出去。

  • TX 模式

進入該模式需要滿足以下條件:

  • PWR_UP=1
  • PRIM_RX=0
  • TX FIFO不為空
  • CE=1脈沖寬度超過10us
  • RX 模式

 進入該模式需要滿足以下條件

  • PWR_UP=1
  • PRIM_RX=1
  • CE=1

 

二、程序實現

根據上面nRF24L01+的時序,結合前面介紹的STM32F4xx SPI的操作小結,SPI設置成全雙工收發模式,NSS(片選引腳)單獨用一個IO口來控制,對nRF24L01+讀寫操作程序如下:

1. SPI發送/接收子函數

 1 /* SPI 發送*/
 2 void _SPIDataSet(SPI_TypeDef * SPIx, unsigned char *Buf, unsigned char Cnt)
 3 {    
 4     for(; Cnt; Cnt--)
 5     {
 6         while((SPIx -> SR & SPI_SR_TXE) != SPI_SR_TXE);
 7         SPIx -> DR = *Buf++; 
 8     }
 9     while(SPIx -> SR & SPI_SR_BSY);
10     Cnt = SPIx -> DR;
11 }
12 
13 /* SPI 接收*/
14 void _SPIDataGet(SPI_TypeDef * SPIx, unsigned char *Buf, unsigned char Cnt)
15 {
16     for(; Cnt; Cnt--)
17     {
18         while((SPIx -> SR & SPI_SR_TXE) != SPI_SR_TXE);
19         SPIx -> DR = 0xFF;
20         while((SPIx -> SR & SPI_SR_RXNE) != SPI_SR_RXNE);
21         *Buf++ = SPIx -> DR;
22     }
23    24 }

L6:寫入數據前必須保證TX緩存器為空

L9:確保最后一位數據發送完畢

L10:使RXNE位清0(對DR進行讀操作,將使RXNE清0),若RXNE若置1,SPI不會接受新數據。

L19:由於SPI工作與全雙工模式,即發送1位數據才會接收1位數據,此語句本質是讓SPI輸出SCK,使nRF24L01+輸出數據

L20: 確保接收到完整的數據

 

2. 對nRF24L01+寄存器的讀/寫操作

 1 /* 寫nRF24L01+ 寄存器 */
 2 void DataSet(unsigned char CMD,      /* 寄存器地址    */ 
 3              unsigned char *Val,     /* 發送數據指針  */
 4              unsigned char Cnt       /* 數據數量     */)
 5 {    
 6     nRF24L01_CSN  = 0;
 7     _SPIDataSet(SPI1, &CMD, 1);
 8     _SPIDataSet(SPI1, Val, Cnt);
 9     nRF24L01_CSN  = 1;
10 }
11 
12 
13 /* 讀nRF24L01+ 寄存器 */
14 void DataGet(unsigned char CMD,      /* 寄存器地址    */
15              unsigned char *Buf,     /* 接收數據指針  */
16              unsigned char Cnt       /* 數據大小     */) 
17 {
18     nRF24L01_CSN  = 0;
19     _SPIDataSet(SPI1, &CMD, 1);
20     _SPIDataGet(SPI1, Buf, Cnt);
21     nRF24L01_CSN = 1;
22 }

L6, L18: CSN的下降沿開始讀/寫操作

L9, L21: CSN的上升沿結束讀/寫操作

 

下圖所示為通過邏輯分析儀抓取的設置nRF24L01+ pipe0接收地址(寄存器0xA)的波形:

圖4. 設置Pipe0(寄存器0xA)接收地址波形

 

下圖所示為通過邏輯分析儀抓取的讀取nRF24L01+ pipe0接收地址(寄存器0xA)的波形:

圖5. 讀取Pipe0(寄存器0xA)接收地址波形

 

More~

1. 假如使用 Auto Acknowledgment 功能,發送端(PTX)Pipe0接收地址必須和發送地址     相同,這是用於接收接收端(PRX)的相應

2. 接收數據數量(最大32字節)必須寫入RX_PW_Px寄存器(x為通道編號)

3. 調試失敗,排查以下幾點:

  • 硬件連接是否正確
  • 寄存器讀寫操作是否正確
  • 確保Standby-I/II 模式變換到TX 模式時,CE高電平時間足夠(大於130us)
  • 發送端(PTX)和接收端(PRX)數據的大小要一致,比如接收端(PRX)接收數據大小設置為8字節,那么主機就要給發送端(PTX)的TX FIFO傳輸8個字節

/×××××××××××××××××××××××××××××××××××××××× THE END××××××××××××××××××××××××××××××××××××××××××××/


免責聲明!

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



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