2.4G模塊NRF24L01調試經驗

參照野火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_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配置如下:

  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);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章