調試備忘錄-nRF24L01P的使用(教程 + 源碼)


目錄--點擊可快速直達

MCU:KEAZ64A

MDK:CodeWarrior 11.0

寫在前面

因為最近在重寫之前項目的代碼,以提升系統的穩定性和代碼的可讀性,所以重新選擇了一塊nRF24L01P,進行調試。

以下算是一些調試的備忘錄吧,如有問題可以通過私信或者郵箱聯系我。

什么是nRF24L01P?

nRF24L01P是一顆工作在 2.4GHz ISM 頻段,專為低功耗無線場合設計,集成嵌入式 ARQ基帶協議引擎的無線收發器芯片。

工作頻率范圍為 2400MHz-2525MHz,共有 126 個 1MHz帶寬的信道。

簡單來說,就是一塊基於民用頻段的無線通信芯片,可以用於無線鼠標、無線鍵盤、遙控器、工業傳感器等應用。

后面我要使用的模塊是在某寶上買的澤耀的nRF24L01P無線通信模塊,以下的一些圖片也是截取自它家的產品資料。

nRF24L01P模塊的簡單介紹

nRF24L01P模塊一共有八個引腳,其中4個SPI引腳,一共工作模式切換引腳和一個終端引腳。

推薦與MCU的連接圖

nRF24L01P的工作模式

nRF24L01P使用SPI進行通訊,可以通過SPI設置nRF24L01P的寄存器來改變nRF24L01P的工作模式。

如圖所示,nRF24L01P的工作模式有如上幾種,我們主要使用的就是接收模式、發射模式以及在兩者之間過渡的待機模式II。

通過改變CONFIG寄存器中的PRIM_RX的值和模塊引腳CE的高低電平,就可以切換工作模式了。

工作模式之間切換是有延時的,如果不加延時,可能導致未知的問題。一定要按照芯片手冊中的資料來增加延時。

nRF24L01P模塊的初始化簡易配置

(一對一模式,使用接收通道0,禁止自動重發)

寄存器 位名 推薦值 備注
TX_ADDR None 0x34 0x43 0x10 0x10 0x01 發射地址
RX_ADDR_P0 None 0x34 0x43 0x10 0x10 0x01 接收通道0地址
EN_AA None 0 禁止自動應答
SETUP_RETR None 0 禁止自動重發
EN_RXADDR ERX_P0 0x01 使能通道0
RF_CH None 40 設置通道頻率
RX_PW_P0 None 0x05 設置P0通道的數據寬度
RF_SETUP None 0x07 設置發射功率以及數據傳輸數率
CONFIG None 0x3e 禁止發射中斷,使能發射模式

注:
1.配置寄存器時,一定要按照SPI的指令格式進行配置。如下圖。

nRF24L01P模塊調試的一些小技巧

1.剛開始調試的時候一定要選擇一個模塊為發射模式,一個模塊為接收模式。發射的開啟發射中斷,接收的開啟接收中斷。這樣就可以用過在中斷中加入顯示(例如LED)開觀察是否發射成功或者接收成功。

2.剛開啟中斷的時候一定要記得清除中斷標志位,中斷標志位有兩個,一個是模塊的中斷標志位,一個是MCU的中斷標志位。

3.對於發射模式,切換發射模式的時候,最好把發射地址(TX_ADDR)也重新寫一遍,因為我在調試的時候發現,如果不重寫一遍地址,就會出問題。當然,這個可能是模塊的BUG,因人而異把。

4.如果有問題,記得使用示波器查看SPI引腳、CE和IRQ的運行情況。

5.寫入寄存器的時候記得拉低CE引腳。

6.如果還是有未知的問題,可以試試延長一下操作IO的時間。

附上源碼

軟件模擬的SPI通信,方便移植。

/**
  ******************************************************************************
  * @file    drv_spi.c
  * @author  xxx
  * @version V1.0
  * @date    2020-1-04
  * @brief   SPI配置C文件
  ******************************************************************************
  */



#include "common.h"





/*
* PTB2->SCK		PTF0->CE
* PTB3->MOSI	        PTE2->MISO
* PTD2->CSN		IRQ->PTA6 
* 
* PTE0->SCK		PTG3->CE
* PTE1->MOSI	        PTE2->MISO
* PTE3->CSN		IRQ->PTC7 
*/

void spi_set_clk_low( )
{
	//GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_LOW);
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_LOW);
}
void spi_set_clk_high( )
{
	//GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_HIGH);
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_HIGH);
}

void spi_set_mosi_low( )
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_LOW);
}
void spi_set_mosi_hight( )
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_HIGH);
}

unsigned char spi_get_miso( )
{
	return GPIO_Get_IO_Value(PORT_E,GPIO_PIN_2);
}

void spi_set_nss_low( )
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW);
}
void spi_set_nss_high( )
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH);
}


/** 軟件SPI */


/**
  * @brief :SPI初始化(軟件)
  * @param :無
  * @note  :無
  * @retval:無
  */
void drv_spi_init( void )
{
	/*GPIO_Init_IO(PORT_B,GPIO_PIN_2,OUTPUT);
		
	GPIO_Init_IO(PORT_B,GPIO_PIN_3,OUTPUT);
		
	GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT);
	
	GPIO_Init_IO(PORT_D,GPIO_PIN_2,OUTPUT);*/
	GPIO_Init_IO(PORT_E,GPIO_PIN_0,OUTPUT);
		
	GPIO_Init_IO(PORT_E,GPIO_PIN_3,OUTPUT);
		
	GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT);
	
	GPIO_Init_IO(PORT_E,GPIO_PIN_1,OUTPUT);
	
}

/**
  * @brief :SPI收發一個字節
  * @param :
  *			@TxByte: 發送的數據字節
  * @note  :非堵塞式,一旦等待超時,函數會自動退出
  * @retval:接收到的字節
  */
uint8_t drv_spi_read_write_byte( uint8_t TxByte )
{
	uint8_t i = 0, Data = 0;
	
	spi_set_clk_low( );
	
	for( i = 0; i < 8; i++ )			//一個字節8byte需要循環8次
	{
		/** 發送 */
		if( 0x80 == ( TxByte & 0x80 ))
		{
			spi_set_mosi_hight( );		//如果即將要發送的位為 1 則置高IO引腳
		}
		else
		{
			spi_set_mosi_low( );		//如果即將要發送的位為 0 則置低IO引腳
		}
		TxByte <<= 1;					//數據左移一位,先發送的是最高位
		
		spi_set_clk_high( );			//時鍾線置高
		asm ("nop; nop");
		asm ("nop; nop");
		
		/** 接收 */
		Data <<= 1;						//接收數據左移一位,先接收到的是最高位
		if( 1 == spi_get_miso( ))
		{
			Data |= 0x01;				//如果接收時IO引腳為高則認為接收到 1
		}
		
		spi_set_clk_low( );				//時鍾線置低
		asm ("nop; nop");
		asm ("nop; nop");
	}
	
	return Data;		//返回接收到的字節
}

/**
  * @brief :SPI收發字符串
  * @param :
  *			@ReadBuffer: 接收數據緩沖區地址
  *			@WriteBuffer:發送字節緩沖區地址
  *			@Length:字節長度
  * @note  :非堵塞式,一旦等待超時,函數會自動退出
  * @retval:無
  */
void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length )
{
	spi_set_nss_low( );			//片選拉低
	
	while( Length-- )
	{
		*ReadBuffer = drv_spi_read_write_byte( *WriteBuffer );		//收發數據
		ReadBuffer++;
		WriteBuffer++;			//讀寫地址加1
	}
	
	spi_set_nss_high( );		//片選拉高
}


/** 軟件SPI */


RF24L01的驅動函數,主要調用NRF24L01_Gpio_Init() RF24L01_Init() NRF24L01_check() RF24L01_Set_Mode() NRF24L01_TxPacket() 這幾個函數就夠用了。

/**
  ******************************************************************************
  * @file    dev_RF24L01.c
  * @author  xxx
  * @version V1.0.0
  * @date    2020-1-03
  * @brief   NRF24L01配置C文件
  ******************************************************************************
  */
  
  
  
#include "common.h"

const char *g_ErrorString = "RF24L01 is not find !...";

/*
* PTB2->SCK		PTF0->CE
* PTB3->MOSI	PTE2->MISO
* PTD2->CSN		IRQ->PTA6 
* 
* PTE0->SCK		PTG3->CE
* PTE1->MOSI	PTE2->MISO
* PTE3->CSN		IRQ->PTC7 
*/
void RF24L01_SET_CS_LOW()
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW);
}
void RF24L01_SET_CS_HIGH()
{
	GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH);
}

void RF24L01_SET_CE_LOW()
{
	GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_LOW);
}
void RF24L01_SET_CE_HIGH()
{
	GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_HIGH);
}
unsigned char RF24L01_GET_IRQ_STATUS()
{
	return GPIO_Get_IO_Value(PORT_C,GPIO_PIN_7);
}
/**
  * @brief :NRF24L01讀寄存器
  * @param :
           @Addr:寄存器地址
  * @note  :地址在設備中有效
  * @retval:讀取的數據
  */
uint8_t NRF24L01_Read_Reg( uint8_t RegAddr )
{
    uint8_t btmp;
	
    RF24L01_SET_CS_LOW( );			//片選
	
    drv_spi_read_write_byte( NRF_READ_REG | RegAddr );	//讀命令 地址
    btmp = drv_spi_read_write_byte( 0xFF );				//讀數據
	
    RF24L01_SET_CS_HIGH( );			//取消片選
	
    return btmp;
}

/**
  * @brief :NRF24L01讀指定長度的數據
  * @param :
  *			@reg:地址
  *			@pBuf:數據存放地址
  *			@len:數據長度
  * @note  :數據長度不超過255,地址在設備中有效
  * @retval:讀取狀態
  */
void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    uint8_t btmp;
	
    RF24L01_SET_CS_LOW( );			//片選
	
    drv_spi_read_write_byte( NRF_READ_REG | RegAddr );	//讀命令 地址
    for( btmp = 0; btmp < len; btmp ++ )
    {
        *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF );	//讀數據
    }
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :NRF24L01寫寄存器
  * @param :無
  * @note  :地址在設備中有效
  * @retval:讀寫狀態
  */
void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value )
{
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );	//寫命令 地址
    drv_spi_read_write_byte( Value );			//寫數據
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :NRF24L01寫指定長度的數據
  * @param :
  *			@reg:地址
  *			@pBuf:寫入的數據地址
  *			@len:數據長度
  * @note  :數據長度不超過255,地址在設備中有效
  * @retval:寫狀態
  */
void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
{
    uint8_t i;
	
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );	//寫命令 地址
    for( i = 0; i < len; i ++ )
    {
        drv_spi_read_write_byte( *( pBuf + i ) );		//寫數據
    }
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :清空TX緩沖區
  * @param :無
  * @note  :無
  * @retval:無
  */
void NRF24L01_Flush_Tx_Fifo ( void )
{
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( FLUSH_TX );	//清TX FIFO命令
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :清空RX緩沖區
  * @param :無
  * @note  :無
  * @retval:無
  */
void NRF24L01_Flush_Rx_Fifo( void )
{
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( FLUSH_RX );	//清RX FIFO命令
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :重新使用上一包數據
  * @param :無
  * @note  :無
  * @retval:無
  */
void NRF24L01_Reuse_Tx_Payload( void )
{
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( REUSE_TX_PL );		//重新使用上一包命令
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :NRF24L01空操作
  * @param :無
  * @note  :無
  * @retval:無
  */
void NRF24L01_Nop( void )
{
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( NOP );		//空操作命令
	
    RF24L01_SET_CS_HIGH( );		//取消片選
}

/**
  * @brief :NRF24L01讀狀態寄存器
  * @param :無
  * @note  :無
  * @retval:RF24L01狀態
  */
uint8_t NRF24L01_Read_Status_Register( void )
{
    uint8_t Status;
	
    RF24L01_SET_CS_LOW( );		//片選
	
    Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS );	//讀狀態寄存器
	
    RF24L01_SET_CS_HIGH( );		//取消片選
	
    return Status;
}

/**
  * @brief :NRF24L01清中斷
  * @param :
           @IRQ_Source:中斷源
  * @note  :無
  * @retval:清除后狀態寄存器的值
  */
uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source )
{
    uint8_t btmp = 0;

    //IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT );	//中斷標志處理
    btmp = NRF24L01_Read_Status_Register( );			//讀狀態寄存器
			
    RF24L01_SET_CS_LOW( );			//片選
    drv_spi_read_write_byte( NRF_WRITE_REG + STATUS );	//寫狀態寄存器命令
    drv_spi_read_write_byte( IRQ_Source | btmp );		//清相應中斷標志
    RF24L01_SET_CS_HIGH( );			//取消片選
	
    return ( NRF24L01_Read_Status_Register( ));			//返回狀態寄存器狀態
}

/**
  * @brief :讀RF24L01中斷狀態
  * @param :無
  * @note  :無
  * @retval:中斷狀態
  */
uint8_t RF24L01_Read_IRQ_Status( void )
{
    return ( NRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT )));	//返回中斷狀態
}
 
 /**
  * @brief :讀FIFO中數據寬度
  * @param :無
  * @note  :無
  * @retval:數據寬度
  */
uint8_t NRF24L01_Read_Top_Fifo_Width( void )
{
    uint8_t btmp;
	
    RF24L01_SET_CS_LOW( );		//片選
	
    drv_spi_read_write_byte( R_RX_PL_WID );	//讀FIFO中數據寬度命令
    btmp = drv_spi_read_write_byte( 0xFF );	//讀數據
	
    RF24L01_SET_CS_HIGH( );		//取消片選
	
    return btmp;
}

 /**
  * @brief :讀接收到的數據
  * @param :無
  * @note  :無
  * @retval:
           @pRxBuf:數據存放地址首地址
  */
uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf )
{
    uint8_t Width, PipeNum;
	
    PipeNum = ( NRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07;	//讀接收狀態
    Width = NRF24L01_Read_Top_Fifo_Width( );		//讀接收數據個數

    RF24L01_SET_CS_LOW( );		//片選
    drv_spi_read_write_byte( RD_RX_PLOAD );			//讀有效數據命令
	
    for( PipeNum = 0; PipeNum < Width; PipeNum ++ )
    {
        *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF );		//讀數據
    }
    RF24L01_SET_CS_HIGH( );		//取消片選
    NRF24L01_Flush_Rx_Fifo( );	//清空RX FIFO
	
    return Width;
}

 /**
  * @brief :發送數據(帶應答)
  * @param :
  *			@pTxBuf:發送數據地址
  *			@len:長度
  * @note  :一次不超過32個字節
  * @retval:無
  */
void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len )
{
    uint8_t btmp;
    uint8_t length = ( len > 32 ) ? 32 : len;		//數據長達大約32 則只發送32個

    NRF24L01_Flush_Tx_Fifo( );		//清TX FIFO
	
    RF24L01_SET_CS_LOW( );			//片選
    drv_spi_read_write_byte( WR_TX_PLOAD );	//發送命令
	
    for( btmp = 0; btmp < length; btmp ++ )
    {
        drv_spi_read_write_byte( *( pTxBuf + btmp ) );	//發送數據
    }
    RF24L01_SET_CS_HIGH( );			//取消片選
}

 /**
  * @brief :發送數據(不帶應答)
  * @param :
  *			@pTxBuf:發送數據地址
  *			@len:長度
  * @note  :一次不超過32個字節
  * @retval:無
  */
void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len )
{
    if( len > 32 || len == 0 )
    {
        return ;		//數據長度大於32 或者等於0 不執行
    }
	
    RF24L01_SET_CS_LOW( );	//片選
    drv_spi_read_write_byte( WR_TX_PLOAD_NACK );	//發送命令
    while( len-- )
    {
        drv_spi_read_write_byte( *pTxBuf );			//發送數據
		pTxBuf++;
    }
    RF24L01_SET_CS_HIGH( );		//取消片選
}

 /**
  * @brief :在接收模式下向TX FIFO寫數據(帶ACK)
  * @param :
  *			@pData:數據地址
  *			@len:長度
  * @note  :一次不超過32個字節
  * @retval:無
  */
void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len )
{
    uint8_t btmp;
	
	len = ( len > 32 ) ? 32 : len;		//數據長度大於32個則只寫32個字節

    RF24L01_SET_CS_LOW( );			//片選
    drv_spi_read_write_byte( W_ACK_PLOAD );		//命令
    for( btmp = 0; btmp < len; btmp ++ )
    {
        drv_spi_read_write_byte( *( pData + btmp ) );	//寫數據
    }
    RF24L01_SET_CS_HIGH( );			//取消片選
}

 /**
  * @brief :設置發送地址
  * @param :
  *			@pAddr:地址存放地址
  *			@len:長度
  * @note  :無
  * @retval:無
  */
void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len )
{
	len = ( len > 5 ) ? 5 : len;					//地址不能大於5個字節
    NRF24L01_Write_Buf( TX_ADDR, pAddr, len );	//寫地址
}

 /**
  * @brief :設置接收通道地址
  * @param :
  *			@PipeNum:通道
  *			@pAddr:地址存肥着地址
  *			@Len:長度
  * @note  :通道不大於5 地址長度不大於5個字節
  * @retval:無
  */
void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len )
{
    Len = ( Len > 5 ) ? 5 : Len;
    PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum;		//通道不大於5 地址長度不大於5個字節

    NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len );	//寫入地址
}

 /**
  * @brief :設置通信速度
  * @param :
  *			@Speed:速度
  * @note  :無
  * @retval:無
  */
void NRF24L01_Set_Speed( nRf24l01SpeedType Speed )
{
	uint8_t btmp = 0;
	
	btmp = NRF24L01_Read_Reg( RF_SETUP );
	btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
	
	if( Speed == SPEED_250K )		//250K
	{
		btmp |= ( 1<<5 );
	}
	else if( Speed == SPEED_1M )   //1M
	{
   		btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
	}
	else if( Speed == SPEED_2M )   //2M
	{
		btmp |= ( 1<<3 );
	}

	NRF24L01_Write_Reg( RF_SETUP, btmp );
}

 /**
  * @brief :設置功率
  * @param :
  *			@Speed:速度
  * @note  :無
  * @retval:無
  */
void NRF24L01_Set_Power( nRf24l01PowerType Power )
{
    uint8_t btmp;
	
	btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x07;
    switch( Power )
    {
        case POWER_F18DBM:
            btmp |= PWR_18DB;
            break;
        case POWER_F12DBM:
            btmp |= PWR_12DB;
            break;
        case POWER_F6DBM:
            btmp |= PWR_6DB;
            break;
        case POWER_0DBM:
            btmp |= PWR_0DB;
            break;
        default:
            break;
    }
    NRF24L01_Write_Reg( RF_SETUP, btmp );
}

 /**
  * @brief :設置頻率
  * @param :
  *			@FreqPoint:頻率設置參數
  * @note  :值不大於127
  * @retval:無
  */
void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint )
{
    NRF24L01_Write_Reg(  RF_CH, FreqPoint & 0x7F );
}

/**
  * @brief :NRF24L01檢測
  * @param :無
  * @note  :無
  * @retval:無
  */ 
void NRF24L01_check( void )
{
	uint8_t i;
	uint8_t buf[5]={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };
	uint8_t read_buf[ 5 ] = { 0 };
	 
	while( 1 )
	{
		NRF24L01_Write_Buf( TX_ADDR, buf, 5 );			//寫入5個字節的地址
		NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 );		//讀出寫入的地址  
		for( i = 0; i < 5; i++ )
		{
			if( buf[ i ] != read_buf[ i ] )
			{
				break;
			}	
		} 
		
		if( 5 == i )

		{
			break;
		}
		else
		{
			//drv_uart_tx_bytes( (uint8_t *)g_ErrorString, 26 );
		}
		//Delay_1ms( 4 * 500 );
		Delay_1ms( 4 * 5 );
	}
}

 /**
  * @brief :設置模式
  * @param :
  *			@Mode:模式發送模式或接收模式
  * @note  :無
  * @retval:無
  */
void RF24L01_Set_Mode( nRf24l01ModeType Mode )
{
    uint8_t controlreg = 0;
    RF24L01_SET_CE_LOW( );		
	controlreg = NRF24L01_Read_Reg( CONFIG );
	
    if( Mode == MODE_TX )       
	{
		controlreg &= ~( 1<< PRIM_RX );
	}
    else 
	{
		if( Mode == MODE_RX )  
		{ 
			uint8_t addr[5] = {INIT_ADDR};
			NRF24L01_Set_RxAddr( 0, &addr[0], 5 ); 
			controlreg |= ( 1<< PRIM_RX ); 
			controlreg &= ~( 1<< MASK_RX_DR ); 
		}
	}

    NRF24L01_Write_Reg( CONFIG, controlreg );
    RF24L01_SET_CE_HIGH( );
    Delay_1us(130);		
}

/**
  * @brief :NRF24L01發送一次數據
  * @param :
  *			@txbuf:待發送數據首地址
  *			@Length:發送數據長度
  * @note  :無
  * @retval:
  *			MAX_TX:達到最大重發次數
  *			TX_OK:發送完成
  *			0xFF:其他原因
  */ 
uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length )
{
	uint8_t l_Status = 0;
	uint8_t addr[5] = {INIT_ADDR};
	RF24L01_SET_CE_LOW( );
	  
	NRF24L01_Set_TxAddr( &addr[0], 5 );                 //設置TX地址
	NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length );	//寫數據到TX BUF 32字節  TX_PLOAD_WIDTH.
	RF24L01_SET_CE_HIGH( );
	Delay_1us(130);		
	l_Status = NRF24L01_Read_Reg(STATUS);						//讀狀態寄存器
	NRF24L01_Write_Reg( STATUS, l_Status );						//清除TX_DS或MAX_RT中斷標志
	if( l_Status & MAX_TX )	//達到最大重發次數
	{
		NRF24L01_Write_Reg( FLUSH_TX,0xff );	//清除TX FIFO寄存器
		drv_spi_read_write_byte( FLUSH_TX );
		return MAX_TX; 
	}
	if( l_Status & TX_OK )	//發送完成
	{
		return TX_OK;
	}
	return 0xFF;	//其他原因發送失敗
}

/**
  * @brief :NRF24L01接收數據
  * @param :
  *			@rxbuf:接收數據存放地址
  * @note  :無
  * @retval:接收的數據個數
  */ 
uint8_t NRF24L01_RxPacket( uint8_t *rxbuf )
{
	uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
	l_Status = NRF24L01_Read_Reg( STATUS );		//讀狀態寄存器
	NRF24L01_Write_Reg( STATUS,l_Status );		//清中斷標志
	/*RF24L01_SET_CS_LOW( );		//片選
	drv_spi_read_write_byte( FLUSH_RX );
	RF24L01_SET_CS_HIGH( );*/
	
	//while( 0 != RF24L01_GET_IRQ_STATUS( ))
	/*{
		Delay_1ms( 100 );
		
		if( 30 == l_100MsTimes++ )		//3s沒接收過數據,重新初始化模塊
		{
			NRF24L01_Gpio_Init( );
			RF24L01_Init( );
			RF24L01_Set_Mode( MODE_RX );
			//break;
		}
	}
	
	l_Status = NRF24L01_Read_Reg( STATUS );		//讀狀態寄存器
	NRF24L01_Write_Reg( STATUS,l_Status );		//清中斷標志
	if( l_Status & RX_OK)	//接收到數據
	{
		l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID );		//讀取接收到的數據個數
		NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength );	//接收到數據 
		NRF24L01_Write_Reg( FLUSH_RX,0xff );				//清除RX FIFO
		return l_RxLength; 
	}	
	
	return 0;				//沒有收到數據	*/
}

 /**
  * @brief :RF24L01引腳初始化
* PTB2->SCK		PTF0->CE
* PTB3->MOSI	PTE2->MISO
* PTD2->CSN		IRQ->PTA6 
* 
* PTE0->SCK		PTG3->CE
* PTE1->MOSI	PTE2->MISO
* PTE3->CSN		IRQ->PTC7 
  * @param :無
  * @note  :無
  * @retval:無
  */
void NRF24L01_Gpio_Init( void )
{
	GPIO_Init_IO(PORT_C,GPIO_PIN_7,INPUT);
	GPIO_Init_IO(PORT_G,GPIO_PIN_3,OUTPUT);
	KBI_Init(PORT_C,GPIO_PIN_7,FALLING);
}

 /**
  * @brief :RF24L01模塊初始化
  * @param :無
  * @note  :無
  * @retval:無
  */
void RF24L01_Init( void )
{
    uint8_t addr[5] = {INIT_ADDR};

    RF24L01_SET_CE_LOW( );

    NRF24L01_Write_Reg( RX_PW_P0, 8 );
    NRF24L01_Write_Reg( CONFIG, 0x7e ); 			//接收中斷
                                         	 	 	
    NRF24L01_Write_Reg( EN_AA, ( 0  ) );   			//禁止通道0自動應答
    NRF24L01_Write_Reg( EN_RXADDR, ( 1  ) );		//通道0接收
    NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES );     	//地址寬度 5個字節
    NRF24L01_Write_Reg( SETUP_RETR, 0x0a );         //重復等待時間 250us
    NRF24L01_Write_Reg( RF_CH, 40 );             	//初始化通道
    NRF24L01_Write_Reg( RF_SETUP, 0x07 );

    NRF24L01_Set_TxAddr( &addr[0], 5 );             //設置TX地址
    NRF24L01_Set_RxAddr( 0, &addr[0], 5 );          //設置RX地址
    RF24L01_SET_CE_HIGH( );
    Delay_1ms(1);
}


IRQ接收中斷處理函數

void KBI0_IRQHandler() 
{
	uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
	unsigned char rxbuf[8];
	l_Status = NRF24L01_Read_Reg( STATUS );		//讀狀態寄存器
	NRF24L01_Write_Reg( STATUS,l_Status );		//清中斷標志
	if( l_Status & RX_OK)	//接收到數據
	{
		l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID );		//讀取接收到的數據個數
		NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength );	//接收到數據 
		NRF24L01_Write_Reg( FLUSH_RX,0xff );				//清除RX FIFO
		
		GPIO_Toggle_IO_Value(PORT_C,GPIO_PIN_0);
		return l_RxLength; 
	}	
	KBI0_SC |= KBI_SC_KBACK_MASK;                     // clear interrupt flag 
	
}


免責聲明!

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



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