mosfet初学 发表于 2020-9-26 23:38

求助,nRF24L01发送接收问题

发送端发32个字节,接收端口也收到32个字节,但都是发送端的第1个节字。不知道怎么回事,初学这个模块,还清知道的大神告知一二。感激不尽

chunyang 发表于 2020-9-28 18:10

程序问题,好好查吧。

土豆日了马铃薯 发表于 2020-9-30 15:49

检查配置(又不贴代码 怎么看嘛)

mosfet初学 发表于 2020-10-9 18:14

#include "drv_RF24L01.h"
#include "drv_spi.h"

/**
* @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:无
*/
uint8_t NRF24L01_check( void )
{
        uint8_t i;
        uint8_t buf={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };
        uint8_t read_buf[ 5 ] = { 0 };
       
        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 )
        {
                return 0;//检测设备成功,返回0
        }
        else
        {
                return 1;//检测设备失败,返回1
        }
        drv_delay_ms( 2000 );
}

/**
* @brief :设置模式
* @param :
*                        @Mode:模式发送模式或接收模式
* @note:无
* @retval:无
*/
void RF24L01_Set_Mode( nRf24l01ModeType Mode )
{
    uint8_t controlreg = 0;
        controlreg = NRF24L01_Read_Reg( CONFIG );
       
    if( Mode == MODE_TX )      
        {
                controlreg &= ~( 1<< PRIM_RX );
        }
    else
        {
                if( Mode == MODE_RX )
                {
                        controlreg |= ( 1<< PRIM_RX );
                }
        }

    NRF24L01_Write_Reg( CONFIG, controlreg );
}

/**
* @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;
        uint16_t l_MsTimes = 0;
       
        RF24L01_SET_CS_LOW( );                //片选
        Drv_Spi_Read_Write_Byte( FLUSH_TX );
        RF24L01_SET_CS_HIGH( );
       
        RF24L01_SET_CE_LOW( );               
        NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length );        //写数据到TX BUF 32字节TX_PLOAD_WIDTH
        RF24L01_SET_CE_HIGH( );                        //启动发送
        GCC_DELAY(20);
        while( 0 != RF24L01_GET_IRQ_STATUS( ))
        {
                drv_delay_ms( 1 );
                if( 500 == l_MsTimes++ )                                                //500ms还没有发送成功,重新初始化设备
                {
                        //DRV_SPI_GPIO_Init( );
                        RF24L01_Init( );
                        RF24L01_SET_CE_LOW();
                        RF24L01_Set_Mode( MODE_TX );
                        RF24L01_SET_CE_HIGH();
                        break;
                }
        }
        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寄存器
                return MAX_TX;
        }

        if( l_Status & TX_OK )        //发送完成
        {
                return TX_OK;
        }
       
        return 0xFF;        //其他原因发送失败
}

/**
* @brief :NRF24L01接收数据
* @param :
*                        @rxbuf:接收数据存放地址
* @note:无
* @retval:
*                        0:接收完成
*                        1:没有接收到数据
*/
uint8_t NRF24L01_RxPacket( uint8_t *rxbuf )
{
        uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
       
        RF24L01_SET_CS_LOW( );                //片选
        Drv_Spi_Read_Write_Byte( FLUSH_RX );
        RF24L01_SET_CS_HIGH( );
       
        while( 0 != RF24L01_GET_IRQ_STATUS( ))
        {
                drv_delay_ms( 100 );
               
                if( 30 == l_100MsTimes++ )                //3s没接收过数据,重新初始化模块
                {
                        DRV_SPI_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 0;
        }       
       
        return 1;                                //没有收到数据       
}

/**
* @brief :RF24L01模块初始化
* @param :无
* @note:无
* @retval:无
*/
void RF24L01_Init( void )
{
    uint8_t addr = {INIT_ADDR};

    //RF24L01_SET_CE_HIGH( );
    RF24L01_SET_CE_LOW();
    RF24L01_SET_CS_HIGH();
    SPI_SET_CLK_LOW();
    NRF24L01_Clear_IRQ_Flag( IRQ_ALL );
#if DYNAMIC_PACKET == 1

    NRF24L01_Write_Reg( DYNPD, ( 1 << 0 ) );         //使能通道1动态数据长度
    NRF24L01_Write_Reg( FEATRUE, 0x07 );
    NRF24L01_Read_Reg( DYNPD );
    NRF24L01_Read_Reg( FEATRUE );
       
#elif DYNAMIC_PACKET == 0

    L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN );        //固定数据长度
       
#endif        //DYNAMIC_PACKET

    NRF24L01_Write_Reg( CONFIG, /*( 1<<MASK_RX_DR ) |*/                //接收中断
                                    ( 1 << EN_CRC ) |   //使能CRC 1个字节
                                    ( 1 << PWR_UP ) );    //开启设备
    NRF24L01_Write_Reg( EN_AA, ( 1 << ENAA_P0 ) );                   //通道0自动应答
    NRF24L01_Write_Reg( EN_RXADDR, ( 1 << ERX_P0 ) );                //通道0接收
    NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES );                           //地址宽度 5个字节
    NRF24L01_Write_Reg( SETUP_RETR, ARD_4000US |
                        ( REPEAT_CNT & 0x01 ) );                 //重复等待时间 250us
    NRF24L01_Write_Reg( RF_CH, 60 );                                     //初始化通道
    NRF24L01_Write_Reg( RF_SETUP, 0x26 );

    NRF24L01_Set_TxAddr( &addr, 5 );                      //设置TX地址
    NRF24L01_Set_RxAddr( 0, &addr, 5 );                   //设置RX地址
    //RF24L01_SET_CE_HIGH( );
}



u8 TxData = {0xAA,0x07,0x0F,0xFF};
u8 RxData = {0};

void main()
{
        //单片机SPI端口初始化
        DRV_SPI_GPIO_Init();
        Key_Init();
        //检测RF24L01
        while(NRF24L01_check());
        //初始货RF24L01
        RF24L01_Init();
       
/******************************************************************
******************** 发送 *********************************
******************************************************************/
        RF24L01_SET_CE_LOW();
#ifdef NRF24L01_TX
        RF24L01_Set_Mode(MODE_TX);        //发送模式
#else
         RF24L01_Set_Mode(MODE_RX);        //接收模式
#endif       
         RF24L01_SET_CE_HIGH();
        delay_us(130);
        while(1)
        {
#ifdef NRF24L01_TX
                if(KeyPress)//按下按键发送一次
                {
                            NRF24L01_TxPacket(TxData,4);       
                }
#else
               NRF24L01_RxPacket(RxData,4);
#endif
        }
}


以上代码在网上找到了些方法,改来改去,有点乱了

mosfet初学 发表于 2020-10-11 00:22

仿真时设置断点,有时可以接收到完整的数据。大多数时间接收到四个字节都是数组的第一个字节0xAA

mosfet初学 发表于 2020-10-13 18:09

问题已解决
while( 0 != RF24L01_GET_IRQ_STATUS( ))
      {
                drv_delay_ms( 100 );
               
                if( 30 == l_100MsTimes++ )                //3s没接收过数据,重新初始化模块
                {
                        DRV_SPI_GPIO_Init( );
                        RF24L01_Init( );
                        RF24L01_Set_Mode( MODE_RX );
                        break;
                }
      }
这段代码我用的时候把里面重新初始化屏蔽了。
解除屏蔽接收数据就正常了。原来找的一些资料上面,也有人把这段屏蔽的。这里需要重启的目的是什么还懂。

mosfet初学 发表于 2020-10-13 18:10

土豆日了马铃薯 发表于 2020-9-30 15:49
检查配置(又不贴代码 怎么看嘛)

谢谢,问题找到了。

mosfet初学 发表于 2020-10-13 18:11

chunyang 发表于 2020-9-28 18:10
程序问题,好好查吧。

是程序问题,谢谢
页: [1]
查看完整版本: 求助,nRF24L01发送接收问题