qq_51382033 2024-10-17 10:20 采纳率: 0%
浏览 109
已结题

NRF24L01能发送但是不能接收

大手子们,请问一下,我用的一对NRF24L01进行一对一通信,不过一个是自己设计的芯片加外围电路,能接收和发送成功,状态寄存器(sta)能显示0x2e和0x3e,另一个是市面上买的NRF24L01模块,能发送但是不能接收,状态寄存器没有出现0x3e,只出现过两次能接收的情况,相对于不能接收的情况只能说是寥寥无几。
我两个NRF24L01的收发逻辑都是依靠IRQ中断服务函数来切换的,这两个NRF都能发送,应该不是程序问题吧?是硬件电源电压的问题吗?模块我也加了10uF电容,同时也在他要安装的电路板上也加了两个10uF以上的电容,是不是滤波不彻底呀,还是其他的原因。以下是几个主要函数和配置:

/*配置*/
CE_LOW;    //拉低CE,注意:读/写nRF寄存器均需要将CE拉低,使其进入待机或者掉电模式才可以
    
    //初始化SI24R1
    SPI_Write_Byte(WRITE_REG_CMD + SETUP_AW, 0x03);                            //配置通信地址的长度,默认值时0x03,即地址长度为5字节
    SPI_Write_Byte(FLUSH_RX,0xff);                                    //清除RX FIFO寄存器  
    SPI_Write_Buf(WRITE_REG_CMD + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);        
    SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);     //与发送端的发送目标地址一致
    SPI_Write_Byte(WRITE_REG_CMD + SETUP_RETR, 0x1a);                         //自动重发延迟为500+86us,重发次数10次
    SPI_Write_Byte(WRITE_REG_CMD + EN_AA, 0x01);                              //接收数据后,只允许频道0自动应答
    SPI_Write_Byte(WRITE_REG_CMD + EN_RXADDR, 0x01);                          //只允许频道0接收数据
    
    SPI_Write_Byte(WRITE_REG_CMD + RF_SETUP, 0x27);                           //设置发射速率为2MHZ,发射功率为最大值0dB
    SPI_Write_Byte(WRITE_REG_CMD + RF_CH, 40);                                //设置通道通信频率,工作通道频率可由以下公式计算得出:Fo=(2400+RF_CH)MHz.并且射频收发器工作的频率范围从2.400-2.525GHz
    SPI_Write_Byte(WRITE_REG_CMD + RX_PW_P0, RX_PLOAD_WIDTH);                 //设置接收数据长度,本次设置为5字节,只有接收的数据达到此长度时,才会触发RX_DS中断
    
    SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0f);                           //默认处于接收模式
    SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0xff);                           // 清除所有的中断标志位
    CE_HIGH;
void SI24R1_SendPacket(u8* tfbuf)
{
    CE_LOW;        //拉低CE,进入待机模式,准备开始往SI24R1中的寄存器中写入数据
//    SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);     //装载接收端地址,由于这里只有一个通道通讯,不用改变接收端的SI24R1的接收通道地址,所以,这句可以注释掉
    SPI_Write_Buf(WR_TX_PLOAD, tfbuf, TX_PLOAD_WIDTH);             //将数据写入TX端的FIFO中,写入的个数与TX_PLOAD_WIDTH设置值相同
    
    SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0e);                 //将SI24R1配置成发射模式
    SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);                //0111 xxxx 给STATUS,清除所有中断标志,防止一进入发射模式就触发中断
    
    CE_HIGH;                                                    //拉高CE,准备发射TX端FIFO中的数据
    
    delay_us(200);                                                //CE拉高后,需要延迟至少130us  
}


void EXTI1_IRQHandler(void)/*NRF24L01中断处理函数*/
{
    if (EXTI_GetITStatus(EXTI_Line1)!=RESET)
    {
        sta = SPI_Read_Byte(READ_REG_CMD+STATUS);           // 读取状态寄存其来判断数据接收状况 
        printf("statuas:%x\r\n",sta);
        if(sta & 0x40)//bit6:数据接收中断
        {
            FLY_Connect_OK    = 1;                        //飞机与遥控器已连接
            SI24R1_ReceivePacket(RxBuf);                //将数据从RX端的FIFO中读取出来
            FLYDataRx_OK     = 1;
            SPI_Write_Byte(WRITE_REG_CMD+STATUS,RX_DR);    //清除RX_DR中断
        }
        else if((sta&0x10)>0)//达到最大发送次数中断 
        {
            LED_Off(LED1);                                      //LED1灭时,表示和飞机通讯中断
            RX_Mode();                                          //将SI24R1的模式改为接收模式,等待接收数据
            SPI_Write_Byte(WRITE_REG_CMD+STATUS,MAX_RT);      //清除MAX_RT中断
            SPI_Write_Byte(FLUSH_TX,0xff); 
        }
        else if((sta&0x20)>0)//TX发送完成中断
        {
            RX_Mode();                                     //将SI24R1的模式改为接收模式,等待接收数据
            if(Fly_Lock == 0x01)
            {
                LED_On(LED1);                             //LED1常亮表示飞机已经解锁成功,并正在进行数据通讯
            }else
            {
                LED_Toggle(LED1);                         //LED1闪烁表示飞机加锁模式中,但是和飞机通讯成功
            }
            SPI_Write_Byte(WRITE_REG_CMD+STATUS,TX_DS);    //清除TX_DS中断
            SPI_Write_Byte(FLUSH_TX,0xff);              //清空TX_FIFO
        }
    EXTI_ClearITPendingBit(EXTI_Line1); //清除标志
}
}
void RX_Mode(void)/*接收模式*/
{
    CE_LOW;                                            //拉低CE,进入待机模式,准备开始往SI24R1中的寄存器中写入数据
    
    SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0f);     //配置为接收模式
    SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);    //0111 xxxx 给STATUS,清除所有中断标志,防止一进入接收模式就触发中断
    
    CE_HIGH;                                         //拉高CE,准备接受从外部发送过来的数据
    delay_us(100);
}
void SI24R1_SendPacket(u8* tfbuf)/*发送数据包*/
{
    CE_LOW;        //拉低CE,进入待机模式,准备开始往SI24R1中的寄存器中写入数据
    SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);     //装载接收端地址,由于这里只有一个通道通讯,不用改变接收端的SI24R1的接收通道地址,所以,这句可以注释掉
    SPI_Write_Buf(WR_TX_PLOAD, tfbuf, TX_PLOAD_WIDTH);             //将数据写入TX端的FIFO中,写入的个数与TX_PLOAD_WIDTH设置值相同
    
    SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0e);                 //将SI24R1配置成发射模式
    SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);                //0111 xxxx 给STATUS,清除所有中断标志,防止一进入发射模式就触发中断
    
    CE_HIGH;                                                    //拉高CE,准备发射TX端FIFO中的数据
    
    delay_us(150);                                                //CE拉高后,需要延迟至少130us  
}

  • 写回答

29条回答 默认 最新

  • 叫兽-郭老师 新星创作者: Java技术领域 2024-10-17 10:25
    关注
    获得0.30元问题酬金

    🕖上午好,题主!目前:🟢[在线]
    📢参考通义千问、由郭老师整理提供!
    📣今日诗号:七弦抚尽,何处觅知音,但向朗月空林。翰墨残迹,谁得千秋理,且听松涛竹意。

    根据你的描述,你遇到的问题可能是由于多个因素导致的。下面我会从几个方面来分析可能的原因,并提供一些解决方案和建议。

    1. 硬件兼容性

    首先,确保两块NRF24L01模块在硬件上的兼容性。尽管NRF24L01是标准的无线模块,但市场上不同供应商的产品可能会有不同的内部实现细节,这可能导致某些特定情况下的兼容性问题。

    2. 电源问题

    你提到已经添加了电容来稳定电源,这是一个很好的做法。但是,还需要确保电源的稳定性。你可以尝试使用示波器检查电源线上的噪声,如果存在大量噪声,可能需要进一步改善电源去耦。

    3. 配置一致性

    从你的代码来看,配置看起来是合理的,但仍有一些地方需要注意:

    • 地址匹配:确保两个模块的地址完全匹配。
    • 中断配置:确保两个模块的中断配置一致。例如,你提到的状态寄存器0x2e和0x3e,这些值代表不同的状态,需要确保它们被正确解析。

    4. 软件实现

    你的代码中有一些细节需要注意:

    • SI24R1_SendPacket函数中,你先拉低CE,然后配置TX地址,这看起来是合理的。但是,如果你在发送数据之前频繁更改TX地址,可能会导致问题。
    • delay_us(200)delay_us(150)的延迟时间是否足够?虽然官方文档建议至少130us,但实际测试中可能需要更长的时间。
    • 在中断处理函数中,你清除了一些中断标志位,这通常是正确的做法。但是,确保在清除之前,这些中断已经被正确处理。

    5. 调试和日志

    为了更好地调试,可以增加更多的日志输出。例如,在发送和接收数据之前和之后,打印出当前的状态寄存器值,这样可以帮助你更好地理解每个步骤的状态变化。

    示例代码优化

    这里是一个优化后的代码示例,主要是增加了一些日志输出,以便于调试:

    void SI24R1_SendPacket(u8* tfbuf)
    {
        CE_LOW;  // 拉低CE,进入待机模式
        SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);
        SPI_Write_Buf(WR_TX_PLOAD, tfbuf, TX_PLOAD_WIDTH);
        
        printf("Sending packet...\r\n");
        SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0e);  // 将SI24R1配置成发射模式
        SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);  // 清除所有中断标志
        
        CE_HIGH;  // 拉高CE,准备发射
        delay_us(200);  // 延迟至少130us
        
        printf("Packet sent.\r\n");
    }
    
    void EXTI1_IRQHandler(void)
    {
        if (EXTI_GetITStatus(EXTI_Line1) != RESET)
        {
            u8 sta = SPI_Read_Byte(READ_REG_CMD + STATUS);
            printf("status: %x\r\n", sta);
            
            if (sta & 0x40)  // 数据接收中断
            {
                printf("Data received.\r\n");
                FLY_Connect_OK = 1;
                SI24R1_ReceivePacket(RxBuf);
                FLYDataRx_OK = 1;
                SPI_Write_Byte(WRITE_REG_CMD + STATUS, RX_DR);
            }
            else if (sta & 0x10)  // 达到最大发送次数中断
            {
                LED_Off(LED1);
                RX_Mode();
                SPI_Write_Byte(WRITE_REG_CMD + STATUS, MAX_RT);
                SPI_Write_Byte(FLUSH_TX, 0xff);
            }
            else if (sta & 0x20)  // TX发送完成中断
            {
                RX_Mode();
                if (Fly_Lock == 0x01)
                {
                    LED_On(LED1);
                }
                else
                {
                    LED_Toggle(LED1);
                }
                SPI_Write_Byte(WRITE_REG_CMD + STATUS, TX_DS);
                SPI_Write_Byte(FLUSH_TX, 0xff);
            }
            
            EXTI_ClearITPendingBit(EXTI_Line1);
        }
    }
    

    希望这些建议能够帮助你解决问题。如果还有其他具体问题或需要进一步的帮助,请随时告知。

    评论

报告相同问题?

问题事件

  • 系统已结题 10月25日
  • 赞助了问题酬金15元 10月17日
  • 创建了问题 10月17日