调试备忘录-nRF24L01P的使用(教程 + 源码)

Posted snowsad

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调试备忘录-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 
    
}

以上是关于调试备忘录-nRF24L01P的使用(教程 + 源码)的主要内容,如果未能解决你的问题,请参考以下文章

arduino+nrf24l01摇杆控制小车程序

NRF24L01--使用STM32F103

nRF24L01/nRF24L01+应用总结

nRF2401A/nRF24L01/nRF24L01+无线模块最常见问题汇集(转)

NRF24L01 Protocol decoder:nrf24l01

nRF24L01+组网方式及防撞(防冲突)机制的实战分享