前言
怎么说呢,今天又看了一天的nrf,很多东西看起来特别简单,但实际用起来,你会发现漏洞百出。根本不知从何下手。下来就分享一下我的经验。对你应该会有所帮助。以下是基于stm32实现的nrf无线通信。
必看
这篇博客不适合无基础的人来看,因为下面程序我只给出部分程序,所以没基础你可能看不懂程序配置的是什么。我主要分享的是多对一通信时不同通道寄存器的参数如何求取
NRF一对一通信
首先NRF一对一通信没得说很简单,而且出问题的几率很小。一对一通信我就不多讲了,给出主要配置收发的程序。
例(1)一对一通信,发送模式的主要配置
如果单做一对一通信建议就用通道p0吧。
//设置发送地址
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //地址可以随便修改(仅针对通道P0的地址)
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收地址
/*******************************************************************/
//配置发送模式
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); //设置接收节点的地址
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //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); //设置通信频率
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //发射参数0db,2Mbps
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式
NRF24L01_CE=1;//CE为高
}
/********************************************************************/
//发送一次数据
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 sta;
SPI2_SetSpeed(SPI_BaudRatePrescaler_4);// spi速度
NRF24L01_CE=0;
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据
NRF24L01_CE=1;//启动发送
while(NRF24L01_IRQ!=0);//等待发送完成
sta=NRF24L01_Read_Reg(STATUS); //读取寄存器状态值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清楚TX-DS中断标志
if(sta&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清楚TX-FIFO
return MAX_TX;
}
if(sta&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//发送失败
}
例(2)一对一接收主要配置
//设置接收地址
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //地址可以随便修改(仅针对通道P0的地址)
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};//接收地址
/************************************************************/
//配置接受模式
void NRF24L01_RX_Mode(void)
//接收程序注释和发送程序注释基本一样
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//配置接收地址
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+RF_CH,40); //通信频率
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//P0为通道0接收
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//
NRF24L01_CE = 1; //
}
/***************************************************************/
//接收程序
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 sta;
SPI2_SetSpeed(SPI_BaudRatePrescaler_8);
sta=NRF24L01_Read_Reg(STATUS); //
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //
if(sta&RX_OK)//
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//将接收到的数据传入参数rxbuf中
NRF24L01_Write_Reg(FLUSH_RX,0xff);//
return 0;
}
return 1;//
}
NRF多对一通信
首先地址的配置要注意,通道P0随意但P1-P5就要注意,给一张图,规律自己找。
多对一接收配置
在我初步接触时我也很不了解为什么0x01是使能通道0,0X02是使能通道1而0X03却是使能通道1和0,而不是通道2。手册告诉我们这个参数一共有8位其中后6位设制通道。1有效,0无效。接下来我就图解解释吧。
再来看看接收程序,因为翻了好多博客,大多只给出了多对一的接收配置程序,而没给出如何接收并判断不同通道的数据。
很多人看到这就产生了疑问,为什么0X00是通道0而0X02是通道1?我继续给大家图解状态寄存器,官方给出,第0位默认为0,1到3位是代表通道号
所以将sta值与0X0e相与是为了求出通道号,然后用switch语句判断此刻接收的是那个通道的值,然后付给相应的参数。
至于发送程序,配置和一对一发送程序配置一样。只要发送地址和相应通道的接收地址一样即可。
总结
因为之前看了好多博客,对这方面的值是怎么来的都没提及,今天还是看技术手册才明白,虽然STM32的开发大多都是Copy,但我们还是要看懂程序,万一出错,也有个经验。知道大概错那了。
遇到的问题
我不知道是我配置的问题还是nrf的问题,在我配置完之后从机B用通道0单独与主机A
通信正常,从机C用通道1和主机A通信正常,但从机C和从机B同时与主机通信,主机数据接收速度变慢,而且偶尔会出错。不知道是不是我忘记配置什么了还是手上的NRF有问题。分开单独测试都没问题,但一起测试就出问题。你们是否在多对一通信时遇到这种问题(通信变慢或者出错),或者有更好的解决方法评论区请告诉我。谢谢。
来源:CSDN
作者:捉猫的耗子
链接:https://blog.csdn.net/qq_25939803/article/details/97797454