一、NRF24L01模塊介紹
引腳介紹

NRF24L01所使用的通訊協議為SPI,SPI又可分為軟件SPI和硬件SPI。
硬件SPI與軟件SPI相比,硬件SPI是靠硬件上面的SPI控制器,所有的時鐘邊緣采樣,時鐘發生,還有時序控制,都是由硬件完成的。它降低了CPU的使用率,提高了運行速度。軟件SPI就是用代碼控制IO輸出高低電平,模擬SPI的時序,這種方法通信速度較慢,且不可靠。
想要使用硬件SPI驅動,需要確定使用的引腳是否有SPI外設功能。可以通過用戶手冊146頁進行查看。
當前使用的是硬件SPI接口,而NRF24L01我們需要與它發送數據也需要接收數據,故使用的是4線的SPI,使用到了時鐘線SCK、主機輸出從機輸入線MOSI、主機輸入從機輸出線MISO和軟件控制的片選線NSS。所以除了這些引腳需要使用硬件SPI功能的引腳外,其他引腳都可以使用開發板上其他的GPIO。這里選擇使用PB13/PB14/PB15的SPI復用功能 。其他對應接入的引腳請按照你的需要。這里選擇的引腳見下表。

模塊在開發板上的接線為:
GND ->GND
VCC ->3.3V
CSN ->PA10
CE ->PA9
MOSI->PB15
MISO->PB14
SCK ->PB13
IRQ ->PB8
模塊接口原理圖

在我們小車主控板中,NRF24L01接口如上,注意不要插反。
二、工程代碼
在NRF24L01.H文件中宏定義引腳以及寄存器
//通信引腳 #define IRQ_Pin GPIO_PIN_8 #define CE_Pin GPIO_PIN_9 #define CS_Pin GPIO_PIN_10 #define SCK_Pin GPIO_PIN_13 #define MISO_Pin GPIO_PIN_14 #define MOSI_Pin GPIO_PIN_15 //寄存器地址代碼 #define CONFIG 0x00 // 配置寄存器 #define EN_AA 0x01 // 自動應答功能使能寄存器 #define EN_RXADDR 0x02 // 接收地址使能寄存器 #define SETUP_AW 0x03 // 設置地址寬度寄存器 #define SETUP_RETR 0x04 // 設置重發寄存器 #define RF_CH 0x05 // 射頻通道寄存器 #define RF_SETUP 0x06 // 射頻設置寄存器 #define STATUS 0x07 // 狀態寄存器 #define OBSERVE_TX 0x08 // 發送觀察寄存器 #define CD 0x09 // 載波檢測寄存器 #define RX_ADDR_P0 0x0A // 接收地址數據通道0 #define RX_ADDR_P1 0x0B // 接收地址數據通道1 #define RX_ADDR_P2 0x0C // 接收地址數據通道2 #define RX_ADDR_P3 0x0D // 接收地址數據通道3 #define RX_ADDR_P4 0x0E // 接收地址數據通道4 #define RX_ADDR_P5 0x0F // 接收地址數據通道5 #define TX_ADDR 0x10 // 發送地址寄存器 #define RX_PW_P0 0x11 // 接收數據通道0有效數據寬度 #define RX_PW_P1 0x12 // 接收數據通道1有效數據寬度 #define RX_PW_P2 0x13 // 接收數據通道2有效數據寬度 #define RX_PW_P3 0x14 // 接收數據通道3有效數據寬度 #define RX_PW_P4 0x15 // 接收數據通道4有效數據寬度 #define RX_PW_P5 0x16 // 接收數據通道5有效數據寬度 #define FIFO_STATUS 0x17 // FIFO狀態寄存器 #define DYNPD 0x1C // 動態有效數據長度寄存器 #define FEATURE 0x1D // 特性寄存器 //操作指令代碼 #define R_REGISTER 0x00 // 讀寄存器命令 #define W_REGISTER 0x20 // 寫寄存器命令 #define R_RX_PAYLOAD 0x61 // 讀取接收有效數據命令 #define W_TX_PAYLOAD 0xA0 // 寫入發送有效數據命令 #define FLUSH_TX 0xE1 // 清空發送FIFO命令 #define FLUSH_RX 0xE2 // 清空接收FIFO命令 #define NOP 0xFF // 無操作命令 //狀態 #define RX_OK 0X40 #define TX_OK 0X20 #define MAX_OK 0X10
然后在NRF24L01.C文件中先配置SPI,隨后配置NRF24L01寄存器
void NRF24L01_GPIO_Init(void)
{
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_SPI2,ENABLE);
__RCC_GPIOA_CLK_ENABLE();
__RCC_GPIOB_CLK_ENABLE();
PB13_AFx_SPI2SCK();//開啟引腳復用功能
PB14_AFx_SPI2MISO();
PB15_AFx_SPI2MOSI();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.IT=GPIO_IT_NONE;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pins=MOSI_Pin | SCK_Pin;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.IT=GPIO_IT_NONE;
GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pins=CS_Pin | CE_Pin;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.IT=GPIO_IT_NONE;
GPIO_InitStruct.Mode=GPIO_MODE_INPUT_PULLUP;
GPIO_InitStruct.Pins=MISO_Pin | IRQ_Pin;
GPIO_InitStruct.Speed=GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOB, &GPIO_InitStruct);
W_CS(1);
SPI_InitTypeDef SPI_InitStructure; // SPI 初始化結構體
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 雙線全雙工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主機模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 幀數據長度為8bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 時鐘空閑電平為低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 第1個邊沿采樣
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片選信號由SSI寄存器控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 波特率為PCLK的8分頻
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 最高有效位 MSB 收發在前
SPI_InitStructure.SPI_Speed = SPI_Speed_Low; // 低速SPI
SPI_Init(CW_SPI2, &SPI_InitStructure); // 初始化
SPI_Cmd(CW_SPI2, ENABLE); // 使能SPI1
}
uint8_t SPI_SwapByte(uint8_t TxByte)
{
uint16_t l_Data = 0;
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);
SPI_SendData(CW_SPI2, TxByte);
while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_RXNE) == RESET);
l_Data = SPI_ReceiveData(CW_SPI2);//讀取接收數據
return l_Data; //返回
}
void W_Reg(uint8_t Reg,uint8_t value)//寫字節
{
W_CS(0);
SPI_SwapByte(Reg);
SPI_SwapByte(value);
W_CS(1);
}
uint8_t R_Reg(uint8_t Reg)//讀字節
{
uint8_t value;
W_CS(0);
SPI_SwapByte(Reg);
value=SPI_SwapByte(NOP);
W_CS(1);
return value;
}
void W_Buf(uint8_t Reg, uint8_t* Buf, uint8_t Len)//連續寫
{
uint8_t i;
W_CS(0);
SPI_SwapByte(Reg);
for(i=0;i
三、實驗現象
在發送端main函數中寫入如下代碼
int main(void)
{
uint8_t Buf[32]={0x00,0x67,0x68,0x69,0x70},num=0;
OLED_Init();//初始化
NRF24L01_Init();
OLED_ShowString(1,1,"Send ok");
while(1)
{
num++;
Buf[0]=num;
Send(Buf);
Delay_s(1);
}
}
在接收端main函數中寫入如下代碼
int main(void)
{
uint8_t Buf[32]={0};
OLED_Init();//初始化
NRF24L01_Init();
OLED_ShowString(1,1,"Receive ok");
while(1)
{
Receive(Buf);
if(Receive_Flag()==1)
{
OLED_ShowNum(3,1,Buf[0],3);
OLED_ShowHexNum(2,4,Buf[1],2);
OLED_ShowHexNum(2,7,Buf[2],2);
OLED_ShowHexNum(2,10,Buf[3],2);
OLED_ShowHexNum(2,13,Buf[4],2);
}
}
}
然后現象如下
發送端發送四個十六進制數據以及一個遞增的十進制數據,OLED屏幕顯示 Send ok

接收端第一行顯示Receive OK,第二行顯示接收到的固定十六進制數據,第三行顯示接收到的十進制數據

-
SPI
+關注
關注
17文章
1892瀏覽量
101643 -
智能小車
+關注
關注
87文章
565瀏覽量
83495 -
CW32
+關注
關注
1文章
323瀏覽量
1924
發布評論請先 登錄
基于nRF24L01的無線通信系統
nRF24L01無線2.4G通信模塊的詳細研究資料說明
nrf24l01是什么模塊_nrf24l01工作原理
nRF24L01無線通信模塊使用簡介
NRF24L01無線通信介紹
CW32L012/F030靈眸X1智能小車——使用NRF24L01通信
評論