NRF24l01一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。

  在博客里面潜水了多年,只是在学习别人的博客,有时虽然博客写的不是完整,只能通过好几个博客同时看才能解决问题,但是自己收获颇多,感谢各位的奉献。言归正传,这几天在调NRF24l01的一对多通信,在网上找到的都是一对二的,或者写的比较模糊不清,这对像我这样的新手很不友好,遂,决定写一篇博客记录一下自己的调试过程,在文末附上代码。

  1. 目录

    NRF24l01通信原理

    一对一的配置说明

    一对一的代码

    一对多的配置说明(1对六、六发一收)

    一对多的代码、

NRF通信原理

一对一的原理:

首先在接收端(0通道)配置接收地址、0通道的自动应答功能、使能接收地址,设置通信频率、设置通道0的数据宽度、设置发射参数、设置成为接收模式。

在发送端设置发送地址、接收地址(为了自动应答功能)、0通道的自动应答功能、使能接收地址,设置通信频率、设置通道0的数据宽度、设置发射参数、设置成为发送模式。

然后发送端发送一帧数据(这帧数据带有发送地址)、因为开启了自动应答功能,发送完毕后发送端会立即进入接收模式。此时接收端如果接到数据以后会首先会将发送端的地址和接收端的地址进行对比,如果一致(所以接收端的接收地址和发送端的发送地址要一致)则认为是正确的数据,将会接收。接收端会立即发送出自己的接收地址,这时发送端如果接收到了以后会和自己配置的接收地址比较是否一致,如果一致,则认为此次发送成功。

多对一的原理:

通信逻辑和一对一通信的原理相同。多对一通信的实现可以通过NRF24l01的地址不同或者发射频率不同实现组网设计。如果使用频率不同(优点为实现简单,缺点是在接收端要不断的进行频率切换才能轮询的接收各个发送端的数据)进行多对一通信的话,那就配置成一对一通信模式,然后发送端的发射频率设置不同,则可实现多对一通信(下文会有详细说明),另一个办法就是使用相同频率,使用不同的通道和地址(优点是使用相同频率,不用切换频率,自动识别来自哪个发送端的数据。缺点是配置较多)实现多对一的通信,NRF24l01最多为六通道通信,六通道配置不同的地址,这样就能实现六对一的通信了(下文有详细说明)。

一对一通信配置说明

接收端的配置:

程序:

NRF24L01_CE=0;	  
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH);//写RX节点地址
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);	 //设置RF通信频率  发射频率=2.4G + 40 = 2.44G 
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一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。_第1张图片

1中配置接收端的通道0的接收地址,RX_ADR_WIDTH为地址宽度,在本文里是5.

2中为使能通道0的自动应答和使能通道0的接收地址。这里需要说明一下0x01是怎么来的。

使能通道自动应答功能和接收地址是通过位来使能的,1为使能,0为失能。一共六个通道。如下图所示。

六通道使能和失能自动应答和接收地址示意图
通道5 通道4 通道3 通道2 通道1 通道0 功能
0 0 0 0 0 1 0x01 使能通道0
0 0 0 0 1 0 0x02 使能通道1
0 0 0 0 1 1 0x03 使能通道0和1
. . . . . . . 省略
1 1 1 1 1 1 0x3f 使能所有通道

3为设置发射频率,计算方法为 发射频率 = 2.4GHz+40MHz = 2.4390625GHz

4为设置通道0的数据宽度(本文为32字节)

5为设置发射速率为2M,低噪声增益开启

6为设置为接收模式

发送端的配置:

程序:

 NRF24L01_CE=0;	    
  	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS0,TX_ADR_WIDTH);//写TX节点地址 
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,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后启动发送

NRF24l01一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。_第2张图片

主要是红框位置与接收端不同,这里主要是为了自动应答功能,作用上文已有说明。

多对一(六对一)通信配置说明

接收端配置:(标红处一定要按照我这个写,不然会出错。莫名其妙)

首先给出六通道的地址:(注意标红处)

代码:

const u8 RX_ADDRESS0[] = {0xff,0xff,0xff,0xff,0x00};//
const u8 RX_ADDRESS1[] = {0xfe,0xaa,0xaa,0xaa,0x01};//
const u8 RX_ADDRESS2[] = {0x02};//??2??
const u8 RX_ADDRESS3[] = {0x03};//??3??
const u8 RX_ADDRESS4[] = {0x04};//??4??
const u8 RX_ADDRESS5[] = {0x05};//??5??

const u8 TX_ADDRESS0[] = {0xff,0xff,0xff,0xff,0x00};//
const u8 TX_ADDRESS1[] = {0xfe,0xaa,0xaa,0xaa,0x01};//
const u8 TX_ADDRESS2[] = {0x02};//
const u8 TX_ADDRESS3[] = {0x03};//
const u8 TX_ADDRESS4[] = {0x04};//
const u8 TX_ADDRESS5[] = {0x05};//

这里要注意,通道0的地址和通道1的地址高字节和低字节都要不同,具体原因我也不知道,我最开始设置的只有高字节不同,结果就不稳定,不是每次上电都能正常传数据的。

 

NRF24l01一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。_第3张图片

代码:

	NRF24L01_CE=0;	  
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH);//写RX节点地址
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDRESS1,RX_ADR_WIDTH);//写RX节点地址
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDRESS1,1);
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)RX_ADDRESS2,1);//写RX节点地址
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(u8*)RX_ADDRESS3,1);//写RX节点地址
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P4,(u8*)RX_ADDRESS4,1);//写RX节点地址
	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P5,(u8*)RX_ADDRESS5,1);//写RX节点地址
	
	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f);    //使能通道0的自动应答    
	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f);//使能通道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+RX_PW_P1,RX_PLOAD_WIDTH);	
	NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);	
	NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P3,RX_PLOAD_WIDTH);	
	NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P4,RX_PLOAD_WIDTH);	
	NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P5,RX_PLOAD_WIDTH);
	
	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一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。_第4张图片

由上图所示,一通道的地址要重写,重写的时候只写入一通道低字节数据,然后2、3、4、5通道也只写入低字节就可以了,因为2、3、4、5通道地址是共用一通道的后四个高字节地址的。这里必须注意,我这里调了2天。日了哈士奇了。。。。

发送端一的配置:(废话不多说,直接上代码)

	NRF24L01_CE=0;	    
  	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS0,TX_ADR_WIDTH);//写TX节点地址 
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  

  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f);     //使能通道0的自动应答    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道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后启动发送

发送端二的配置:

	NRF24L01_CE=0;	    
  	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS1,TX_ADR_WIDTH);//写TX节点地址 
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS1,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  

  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f);     //使能通道0的自动应答    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道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后启动发送

 

发送端三的配置:

	NRF24L01_CE=0;	    
  	NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS2,TX_ADR_WIDTH);//写TX节点地址 
  	NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS2,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK	  

  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f);     //使能通道0的自动应答    
  	NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道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后启动发送

发送端四和五的配置就是把地址换了即可,其他不用动。

接下来说一下接收程序,可接收六通道数据。

u8 NRF24L01_RxPacket(u8 *rxbuf)
{
	u8 sta;		    							   
	SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)   
	sta=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值    	 
	NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
	if(sta&RX_OK)//接收到数据
	{
		switch((sta >> 1) & 0x07)
		{
			case 0x00:NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_1,RX_PLOAD_WIDTH);//读取数据
				break;
			case 0x01: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_2,RX_PLOAD_WIDTH);
				break;
			case 0x02: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_3,RX_PLOAD_WIDTH);
				break;
			case 0x03:NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_4,RX_PLOAD_WIDTH);//读取数据
				break;
			case 0x04: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_5,RX_PLOAD_WIDTH);
				break;
			case 0x05: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_6,RX_PLOAD_WIDTH);
				break;
			default: ;
				break;
		}
		
		NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器 
		return 0; 
	}	   
	return 1;//没收到任何数据
}		

 

至此NRF24l01配置已经说明完毕,如果还不通请留言。

你可能感兴趣的:(NRF24l01一对一通信、多对一(一对六、六发一收)通信最终解决办法。亲测好用。)