2.4G模組NRF24L01除錯經驗
阿新 • • 發佈:2019-01-09
參照野火STM32程式除錯NRF24L01成功,頗獲喜感
nRF24L01是一款工作在2.4~2.5GHz世界通用ISM頻段的單片無線收發器晶片。無線收發器包括:頻率發生器、增強型SchockBurstTM模式控制器、功率放大器、警惕振盪器、調製器、解調器。輸出功率、頻道選擇和協議的設定可以通過SPI介面進行設定。
模組外形圖如下圖所示: PCB和引腳示意圖如下圖所示:
電路圖如圖所示:
VDD電壓範圍為1.9V~3.6V,我使用的是3.3V,與微控制器的通訊介面型別為SPI,讀寫時序如下圖所示:
與開發板硬體連線如下:
* 硬體連線:----------------------------—----|
| PA5-SPI1-SCK : NRF -SCK |
| PA6-SPI1-MISO : NRF -MISO |
| PA7-SPI1-MOSI : NRF -MOSI |
| PA4 : NRF -CE |
* | PA3 : NRF -CSN |
|
PA2 : NRF -IRQ |
* -------------------------------------------
引腳配置如下:
SPI配置如下:/*配置 SPI_NRF_SPI的 SCK,MISO,MOSI引腳,GPIOA^5,GPIOA^6,GPIOA^7 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用功能 GPIO_Init(GPIOA, &GPIO_InitStructure); /*配置SPI_NRF_SPI的CE引腳,GPIOA^4和SPI_NRF_SPI的 CSN 引腳: NSS GPIOC^4*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /*配置SPI_NRF_SPI的IRQ引腳,GPIOA^2*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉輸入 GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //雙線全雙工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //資料大小8位 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //時鐘極性,空閒時為低 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第1個邊沿有效,上升沿為取樣時刻 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS訊號由軟體產生 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //8分頻,9MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //高位在前 SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE);
配置進入接收模式:
void NRF_RX_Mode(void)
{
NRF_CE_LOW();
SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//寫RX節點地址
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //設定RF通訊頻率
SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效資料寬度
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x07); //設定TX發射引數,0db增益,1Mbps,低噪聲增益開啟
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f); //配置基本工作模式的引數;PWR_UP,EN_CRC,16BIT_CRC,接收模式
NRF_CE_HIGH(); /*CE拉高,進入接收模式*/
delay_ms(100); //CE拉高一段時間
}
配置進入發射模式:
void NRF_TX_Mode(void)
{
NRF_CE_LOW();
SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); //寫TX節點地址;
SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //設定TX節點地址,主要為了使能ACK;
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答;
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址;
SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//設定自動重發間隔時間:500us + 86us;最大自動重發次數:10次;
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); //設定RF通道為CHANAL;
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x07); //設定TX發射引數,0db增益,1Mbps,低噪聲增益開啟;
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的引數;PWR_UP,EN_CRC,16BIT_CRC,發射模式,開啟所有中斷;
/*CE拉高,進入傳送模式*/
NRF_CE_HIGH();
delay_ms(100); //CE要拉高一段時間才進入傳送模式
}
NRF24L01的開機自檢:
u8 NRF_Check(void)
{
u8 buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
u8 buf1[5];
u8 i;
SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5); /*寫入5個位元組的地址. */
SPI_NRF_ReadBuf(TX_ADDR,buf1,5); /*讀出寫入的地址 */
for(i=0;i<5;i++) /*比較*/
{
if(buf1[i]!=0xC2)
break;
}
if(i==5)
return SUCCESS ; //MCU與NRF成功連線
else
return ERROR ; //MCU與NRF不正常連線
}
資料傳送:
u8 NRF_Tx_Dat(u8 *txb)
{
u8 state;
NRF_CE_LOW(); /*ce為低,進入待機模式1*/
SPI_NRF_WriteBuf(WR_TX_PLOAD,txb,TX_PLOAD_WIDTH); /*寫資料到TX BUF 最大 32個位元組*/
NRF_CE_HIGH(); /*CE為高,txb非空,傳送資料包 */
while(NRF_Read_IRQ()!=0); /*等待發送完成中斷 */
state = SPI_NRF_ReadReg(STATUS); /*讀取狀態暫存器的值 */
SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); /*清除TX_DS或MAX_RT中斷標誌*/
SPI_NRF_WriteReg(FLUSH_TX,NOP); //清除TX FIFO暫存器
/*判斷中斷型別*/
if(state&MAX_RT) //達到最大重發次數
return MAX_RT;
else if(state&TX_DS) //傳送完成
return TX_DS;
else
return ERROR; //其他原因傳送失敗
}
資料接收,可放在主函式裡迴圈檢測,也可更換為中斷模式檢測:
u8 NRF_Rx_Dat(u8 *rxb)
{
u8 state;
NRF_CE_HIGH(); //進入接收狀態
/*等待接收中斷*/
//while(NRF_Read_IRQ()!=0);///////////////////////////////////////////////
NRF_CE_LOW(); //進入待機狀態
state = SPI_NRF_ReadReg(STATUS); /*讀取status暫存器的值*/
if(state&RX_DR) /*判斷是否接收到資料*/ //接收到資料
{
SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);/* 清除中斷標誌*/
SPI_NRF_ReadBuf(RD_RX_PLOAD,rxb,RX_PLOAD_WIDTH);//讀取資料
// SPI_NRF_WriteReg(FLUSH_RX,NOP); //清除RX FIFO暫存器
return RX_DR;
}else
return ERROR; //沒收到任何資料
}
主迴圈任務程式如下:
void nrf_task(void *pdata)
{
while(NRF_Check()!=SUCCESS){
<span style="white-space:pre"> </span>delay_ms(100);
}
NRF_TX_Mode();//主動請求連線
nrf_Txbuf[0]='H';
nrf_Txbuf[1]='E';
nrf_Txbuf[2]='L';
nrf_Txbuf[3]='L';
nrf_Txbuf[4]='0';
do
{
status = NRF_Tx_Dat(nrf_Txbuf);
}while((status != TX_DS)&(status != MAX_RT));//傳送成功或者到達最大重發次數
<span style="white-space:pre"> </span>if(status == MAX_RT)
{
USART1_printf( USART1,"Connection Failed\r\n");
}
<span style="white-space:pre"> </span>memset(nrf_Txbuf,0,sizeof(nrf_Txbuf));
NRF_RX_Mode();//配置為接收模式
while(1)
{
/*等待接收資料*/
status = NRF_Rx_Dat(nrf_Rxbuf);
/*判斷接收狀態*/
if(status == RX_DR)//接收到資料中斷標誌
{
Usb_SendData((char*)nrf_Rxbuf,strlen((char*)nrf_Rxbuf));//通過USB轉發
}
if(0 != strlen((char*)nrf_Txbuf))//傳送緩衝不為空
{
NRF_TX_Mode();//主動請求連線
do
{
status = NRF_Tx_Dat(nrf_Txbuf);
delay_ms(10);
}while((status != TX_DS)&(status != MAX_RT));//傳送成功或者到達最大重發次數
memset(nrf_Txbuf,0,sizeof(nrf_Txbuf));
NRF_RX_Mode();//配置為接收模式
}
delay_ms(100);
}
}