NRF24L01发送端发送正常,接收端始终接收不到数据问题排查 您所在的位置:网站首页 nrf24l01发送数据都是0000 NRF24L01发送端发送正常,接收端始终接收不到数据问题排查

NRF24L01发送端发送正常,接收端始终接收不到数据问题排查

2024-06-16 20:32| 来源: 网络整理| 查看: 265

发现问题

在调试NRF24L01进行无线通信过程中,一开始裸机跑没问题。当主从都加上freertos的时候,通信出现了异常。具体问题,发送端发送数据可以正常发送,接收端接收不到数据。代码使用CUBEmx生成。

排查问题

首先将主从两个模块拿出来单独调试,即不使用自动重发机制。 针对发送方,在配置为发送模式的时候,具体配置代码如下:

//该函数初始化NRF24L01到TX模式 //设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR //PWR_UP,CRC使能 //当CE变高后,即进入RX模式,并可以接收数据了 //CE为高大于10us,则启动发送. void NRF24L01_TX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断 NRF24L01_CE=1;//CE为高,10us后启动发送 }

注意:这里的配置都配置成了失能,这样可以保证没有接收方的时候,可以调试发送方。 好了,配置好发送模式,然后就需要进行发送了,在freerots.c中开了一个任务,代码如下:

void StartTask02_IMU_Data(void const * argument) { /* USER CODE BEGIN StartTask02_IMU_Data */ /* Infinite loop */ for(;;) { // AHRS_getYawPitchRoll(ypr); //姿态更新 // Math_hz++; //解算次数 ++ // BMP180_Routing(); //处理BMP018 事务 开启转换和读取结果将在这个子程序中进行 // BMP180_getTemperat(&Temperature); //读取最近的温度值 // BMP180_getPress(&Pressure); //读取最近的气压测量值 // BMP180_getAlt(&Altitude); //读取相对高度 // Math_hz=0; // MPU6050_getlastMotion6(&ax, &ay, &az, &gx, &gy, &gz); // HMC58X3_getRaw(&hx,&hy,&hz); NRF24L01_TxPacket(senddata); //printf("rccreg.CR is %x\r\n",RCC->CR); //printf("sysclocksource is %d\r\n",HAL_RCC_GetSysClockFreq()); // printf("sysclksource is %d\r\n",clkdef.SYSCLKSource); //printf("pllsource is %d\r\n",clktyp.PLL.PLLSource); //printf("data to be sent is %s\r\n",senddata); //osMessagePut(myQueue01Handle,hx,0); osDelay(50); } /* USER CODE END StartTask02_IMU_Data */ }

这样就可以循环发送数据了,当然你也可以用printf打印出来,看看你发送的数据,但是,关键是要看你是否发出去了。我在发送打包函数中添加了两个检查STATUS寄存器和FIFO_STATUS寄存器的语句,并将寄存器值打印出来。

//启动NRF24L01发送一次数据 //txbuf:待发送数据首地址 //返回值:发送完成状况 u8 NRF24L01_TxPacket(u8 *txbuf) { u8 sta,fifo_sta; SPI1_SetSpeed(SPI_BAUDRATEPRESCALER_8);//spi速度为10.5Mhz(24L01的最大SPI时钟为10Mhz) NRF24L01_CE=0; NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF 32个字节 NRF24L01_CE=1;//启动发送 while(NRF24L01_IRQ!=0);//等待发送完成 sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值 读配置寄存器命令是0, fifo_sta= NRF24L01_Read_Reg(NRF_FIFO_STATUS); printf("send status is %x \r\n",sta); printf("send fifo_status is %x \r\n",fifo_sta); NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志 if(sta&MAX_TX)//达到最大重发次数 { NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; } if(sta&TX_OK)//发送完成 { return TX_OK; } return 0xff;//其他原因发送失败 }

好,两个printf函数就将两个寄存器值打印出来了,如果你手上已经看过了NRF的手册,那你就可以对照寄存器查看这两个值的意义了。我这边打印出来的值,STATUS寄存器的值是0x2e,FIFO_STATUS寄存器的值是0x11,通过看手册,说明我发送已经成功了! 既然可以发送,那是不是接收端有问题?同样的方法,我把接收端也配置一下,如下

//该函数初始化NRF24L01到RX模式 //设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR //当CE变高后,即进入RX模式,并可以接收数据了 void NRF24L01_RX_Mode(void) { NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x00); //失能通道0的自动应答 NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通信频率 NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度 NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启 NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式 NRF24L01_CE = 1; //CE为高,进入接收模式 }

**注意:这里配置仍然是失能。然后又配置了一下接收打包函数,和发送一样的方法,把寄存器的值打出来看看,如下:

//启动NRF24L01接收一次数据 //rxbuf:待接收数据首地址 //返回值:0,接收完成;其他,错误代码 u8 NRF24L01_RxPacket(u8 *rxbuf) { u8 sta; SPI1_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为10.5Mhz(24L01的最大SPI时钟为10Mhz) sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值 printf("status data is %x\r\n",sta); NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志 if(sta&RX_OK)//接收到数据 { NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据 NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; } return 1;//没收到任何数据 }

好,我这里的printf函数打印出的STATUS寄存器的值是0x0e,意思是说我的接收FIFO为空,那就是说没接收到东西嘛,怪不得,问题貌似就发现了,那么接下来就是解决问题了。

解决问题

接收端出了问题,首先我检查了一下发送和接收端的配置,没有问题。说明你只要参考我上面的配置,就不会出大问题。然后。。。然后我就开始走偏了,我怀疑是不是我MCU有问题,因为主控是我刚焊的,元件都是从废旧板子拆下来的。我接下来又把两个主控板的时钟检查了一下,确定sysclk输出是正确的,就是把时钟的寄存器值检查了一下,没问题,那板子应该没问题。然后,我也看不出啥情况,开始把两个模块主从对调了一下,发现还是发送正常,接收有问题,那就说明不是NRF模块的问题了。 尴尬了,找到问题却解决不了问题。 忽然想到一个问题,之前裸机的程序,那个是可以的。但是cubemx生成的不行。裸机的配置都是自己手动配置的,而自动生成这个都是cubemx自动配置的,会不会是这里的问题?不知道是什么力量指引着我,我在代码里一眼看中了NRF24L01_CE=1;//CE为高,10us后启动发送这条语句,CE这个IO有问题吧? 于是我看了下GPIO部分的配置,果然,裸机和带系统的配置是有区别的,对比

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8; //PG8 7 推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//普通输出模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化指定IO

这个是裸机的配置

/*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = SPI_CE_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SPI_CE_GPIO_Port, &GPIO_InitStruct);

这个是带操作系统的配置 区别就在于,cubemx生成的代码,将这个IO口上拉了!!!直觉告诉我,注释掉它!!!重新编译下载,接收端,成功接收到来自发送端的问候。 在这里插入图片描述

总结

以上贴出代码为调试代码,具体通信还是需要加上自动重发机制,即将原来的失能的地方都改成使能就可以了。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有