Soc点灯大师 2019-06-03 10:41 采纳率: 0%
浏览 441

nRF24L01 2.4G收发问题

第一次用这个芯片,博主用的是中断的方式读取状态以及接收数据,发现发送端每次读出来的值是0x1F,说明发送到达了最大发送次数而没有被接收?发送是OK的吗?然而接收端怎么也没有数据打印出来,接收不到任何数据,不知道问题出现在哪里,读写寄存器函数是OK的,求大神指点一下。

#ifdef nRF24l01_EN

#define NRF24L01_TX   0  //发送使能      1:发送      0:接收


#define MOSI_PORT JL_PORTB
#define MOSI_BIT  BIT(1)

#define MISO_PORT JL_PORTB
#define MISO_BIT  BIT(0)

#define SCK_PORT JL_PORTB
#define SCK_BIT  BIT(6)

#define CSN_PORT JL_PORTB
#define CSN_BIT  BIT(3)

#define CE_PORT JL_PORTB
#define CE_BIT  BIT(5)


#define MOSI_SET(x) do{x?(MOSI_PORT->OUT|=MOSI_BIT):(MOSI_PORT->OUT&=~MOSI_BIT);}while(0)
#define CSN_SET(x) do{x?(CSN_PORT->OUT|=CSN_BIT):(CSN_PORT->OUT&=~CSN_BIT);}while(0)
#define CE_SET(x) do{x?(CE_PORT->OUT|=CE_BIT):(CE_PORT->OUT&=~CE_BIT);}while(0)


#define SCK_SET(x) do{x?(SCK_PORT->OUT|=SCK_BIT):(SCK_PORT->OUT&=~SCK_BIT);}while(0)


#define MISO_DAT() (MISO_PORT->IN&MISO_BIT)

uint8_t const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
uint8_t const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址

void spi_io_init(void)
{
    MOSI_PORT->DIR &= ~MOSI_BIT;
    MISO_PORT->DIR |= MISO_BIT;
    CE_PORT->DIR &= ~CE_BIT;
    CE_PORT->OUT &= ~CE_BIT;
    CSN_PORT->DIR &= ~CSN_BIT;
    CSN_PORT->OUT |= CSN_BIT;
    SCK_PORT->DIR &= ~SCK_BIT;
    SCK_PORT->OUT &= ~SCK_BIT;

}
void inerDelay_us(unsigned char n)
{
    for(;n>0;n--)
        asm("nop");
}

uint8_t SPI_RW(uint8_t uchar)
{
    uint8_t bit_ctr;
    for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
    {
        MOSI_SET(uchar & 0x80);         // output 'uchar', MSB to MOSI
        uchar = (uchar << 1);           // shift next bit into MSB..
        SCK_SET(1);                      // Set SCK high..
        uchar |= MISO_DAT();              // capture current MISO bit
        SCK_SET(0);                   // ..then set SCK low again
    }
    return(uchar);                    // return read uchar
}


uint8_t SPI_Read(uint8_t reg)
{
    uint8_t reg_val;

    CSN_SET(0);                // CSN low, initialize SPI communication...
    SPI_RW(reg);            // Select register to read from..
    reg_val = SPI_RW(0);    // ..then read registervalue
    CSN_SET(1);                // CSN high, terminate SPI communication

    return(reg_val);        // return register value
}
uint8_t SPI_RW_Reg(uint8_t reg, uint8_t value)
{
    uint8_t status;

    CSN_SET(0);                   // CSN low, init SPI transaction
    status = SPI_RW(reg);      // select register
    SPI_RW(value);             // ..and write value to it..
    CSN_SET(1);                  // CSN high again

    return(status);            // return nRF24L01 status uchar
}
uint8_t SPI_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars)
{
    uint8_t status,uchar_ctr;

    CSN_SET(0);                             // Set CSN low, init SPI tranaction
    status = SPI_RW(reg);               // Select register to write to and read status uchar

    for(uchar_ctr=0;uchar_ctr<uchars;uchar_ctr++)
        pBuf[uchar_ctr] = SPI_RW(0);    //

    CSN_SET(1);

    return(status);                    // return nRF24L01 status uchar
}
uint8_t SPI_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars)
{
    uint8_t status,uchar_ctr;

    CSN_SET(0);           //SPI使能
    status = SPI_RW(reg);
    for(uchar_ctr=0; uchar_ctr<uchars; uchar_ctr++) //
        SPI_RW(*pBuf++);
    CSN_SET(1);         //关闭SPI
    return(status);    //
}


void SetRX_Mode(void)
{
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t *)RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
    SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);           // IRQ收发完成中断响应,16位CRC   ,主接收
}
/*

*/
void nRF24L01_RxPacket(unsigned char* rx_buf)
{
    unsigned char revale=0;
    uint8_t sta=SPI_Read(STATUS);   // 读取状态寄存其来判断数据接收状况
    CE_SET(1);              
//  printf("R:%x ",sta);
    if(sta & BIT(6))                // 判断是否接收到数据
    {
        CE_SET(0);              
        printf("R");
        SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
    }
    SPI_RW_Reg(WRITE_REG+STATUS,sta);   //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志

}

void nRF24L01_TxPacket(unsigned char * tx_buf)
{
    //printf("s");

    CE_SET(0);      //StandBy I模式
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t *)RX_ADDRESS, RX_ADR_WIDTH); // 装载接收端地址
    SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);              // 装载数据
    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e);            // IRQ收发完成中断响应,16位CRC,主发送
    CE_SET(1);   //置高CE,激发数据发送
}
void nrf24l01_irq_init(void);

void NRF24L01_RX_Mode(void)
{

} 
/******************************************************************************
 * \par  Description:  
 * \param[in]    NULL
 * \param[out]    NULL
 * \return       NULL
 * \ note:       
 *******************************************************************************/

void init_NRF24L01(void)
{
    spi_io_init();

    nrf24l01_irq_init();

    CE_SET(0);

    SPI_Write_Buf(WRITE_REG + TX_ADDR, (uint8_t *)TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t *)RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
    SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      //  频道0自动 ACK应答允许
    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21
    SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);        //   设置重发次数
    SPI_RW_Reg(WRITE_REG + RF_CH, 40);        //   设置信道工作为2.4GHZ,收发必须一致
    SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07);         //设置发射速率为2MHZ,发射功率为最大值0dB
#if (NRF24L01_TX == 0)
    SetRX_Mode();
#endif

}


const u8 send_data[32]={0x55,0x5a,0xa5,0xaa};
u8 rx_buf[32];
void nrf24l01_msg_handler(void)
{
#if (NRF24L01_TX == 0)
    //nRF24L01_RxPacket(rx_buf);
#endif
}
/******************************************************************************
 * \par  Description:  1秒消息处理
 * \param[in]    NULL
 * \param[out]    NULL
 * \return       NULL
 * \ note:       
 *******************************************************************************/
void one_second_handler(void)
{
#if (NRF24L01_TX)
    nRF24L01_TxPacket((u8 *)send_data);
#endif
}
u8 nrf24l01_rx_buf[32];

/******************************************************************************
 * \par  Description:  外部中断服务
 * \param[in]    NULL
 * \param[out]    NULL
 * \return       NULL
 * \ note:       
 *******************************************************************************/
void nrf24l01_isr(void)
{
/*  CE_SET(0);    
    uint8_t sta = SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况

    printf("%x ",sta);

    SPI_RW_Reg(WRITE_REG+STATUS,sta);   //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
    if (sta & 0x10){
        CE_SET(1);    // chip enable
        SPI_RW_Reg(WRITE_REG+FLUSH_TX,0xff);
    }*/
    nRF24L01_RxPacket(nrf24l01_rx_buf);

    JL_WAKEUP->CON2 |= BIT(12);//clean pending

}

IRQ_REGISTER(IRQ_PORT_IDX, nrf24l01_isr);
/******************************************************************************
 * \par  Description:  外部中断初始化
 * \param[in]    NULL
 * \param[out]    NULL
 * \return       NULL
 * \ note:       下降沿触发
 *******************************************************************************/
void nrf24l01_irq_init(void)
{

    JL_PORTB->DIR |=BIT(4);
    JL_PORTB->DIE |= BIT(4);
    JL_PORTB->PU |=BIT(4);
    JL_PORTB->PD &=~BIT(4);
    printf("*****nrf24l01_irq_init init***\n");


    JL_WAKEUP->CON0 |= BIT(12);//检查PA8电平触发
    JL_WAKEUP->CON1 |= BIT(12);//下降沿触发

    IRQ_REQUEST(IRQ_PORT_IDX, nrf24l01_isr);
}



#endif

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-09-09 16:30
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 建议你看下这篇博客👉 :NRF24L01

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 以帮助更多的人 ^-^
    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?