NRF24L01一对多通信方法

如果你还是搞不懂两个NRF24L01之间的通信,请阅读瑞升写的这两篇文章《初学者如何快速打通NRF24L01通信》和《NRF24L01中文资料_原理_程序详解》。

 

一旦两个NRF24L01相互通信,一对多实际上非常容易。 你要记住,一对多的通信实际上同时也是一对一的通信。 一次通信只需要几毫秒。 如果一个人与一个人沟通,再与另一个人沟通,再与另一个人沟通……如果中间没有延迟程序,就人的反应而言,都是同时进行的。 。 这个原理和操作系统是一样的。 同时,你还可以打字、聊天、看电影。

下面的视频是 Latson 和 Watkins 完成的一个项目。 它是一个一拖五的模块,总共使用了6个NRF24L01模块,一个在一个盒子里。

视频地址:

上面视频中的例子,如果只看NRF24L01,可以总结为下图:

NRF24L01一对多通信图/

我们知道2个NRF24L01通信需要具备相同的4个条件。

现在假设主站和5个从站的4个条件都设置为相同。 如果主机发送数据,理论上5个从机都会收到数据,但实际上由于干扰,它们不会全部收到数据。 而且,此时如果从机1向主机发送数据,从机2~5也会收到数据。 所以这行不通!

一对多,有两种方式,一种是修改为不同的通道,一种是修改为不同的地址,也可以修改为不同的通道+不同的地址。

上面视频中使用的修改为不同的通道。 例如从机1的通道为10,从机2的通道为30,从机3的通道为50,从机4的通道为70,从机4的通道为70。5的通道为90 (注意通道的值可以是0~125,共126个通道),如果通道接近的话,可能会出现问题,比如从机1的通道是20,如果从机2的通道是设置为21 这种情况下,当主机向从机1发送数据时,从机2也可能接收到数据。 所以同上,通道距离应该更宽一些。 这时候可能有人会有疑问,如果我有几十台从机,通道不是很近吗? 恭喜你,你得到了正确的答案。 如果有多个从机,建议不要使用不同的通道,但同一个通道有不同的地址。 由于地址为5字节,理论上可以有数亿个从站。

从机的通道定义好了,那么主机的程序怎么写呢? 这个很容易。 例如,如果主机要与从机1通信,则将信道更改为与从机1相同的信道10,然后可以发送数据。 此时从机2~5由于通道不同而无法接收数据。 类似地,如果主设备想要与从设备 2 通信,则将其信道更改为与从设备 2 相同的通道 30,然后就可以发送数据。 这时候,有的孩子还会问,我怎么知道我要和谁交流呢? 如何改变呢? 类似这样的童鞋还有不少,我来给大家解释一下。 我不好意思说,太简单了。 假设我的主机有 5 个按钮。 按按键1,向从机1发送数据; 按下按钮 2 将数据发送到从机 2…等等。 然后,宿主程序如下所示:

if(KEY==0)//按下KEY1
{
 NRF_CE=0;	//拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,10);//修改为从机1的频道
 NRF_CE=1;	//拉高CE引脚
 NRF24L01_TxPacket(rece_buf);//发送数据
}
else if(KEY2==0)//按下KEY2
{
 NRF_CE=0;	//拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,30);//修改为从机2的频道
 NRF_CE=1;	//拉高CE引脚
 NRF24L01_TxPacket(rece_buf);//发送数据
}
else if(KEY2==0)//按下KEY3
{
 NRF_CE=0;	//拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,50);//修改为从机3的频道
 NRF_CE=1;	//拉高CE引脚
 NRF24L01_TxPacket(rece_buf);//发送数据
}
else if(KEY2==0)//按下KEY4
{
 NRF_CE=0;	//拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,70);//修改为从机4的频道
 NRF_CE=1;	//拉高CE引脚
 NRF24L01_TxPacket(rece_buf);//发送数据
}
else if(KEY2==0)//按下KEY5
{
 NRF_CE=0;	//拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,90);//修改为从机5的频道
 NRF_CE=1;	//拉高CE引脚
 NRF24L01_TxPacket(rece_buf);//发送数据
}

 

说到这里,有童鞋还有疑问:“那如果我的5个从机要给master发送数据怎么办?按照你上面的程序,master的通道不固定,一会儿一个,一会儿一个是的,当slave要与master通信时,如何判断当前master的通道与当前slave的通道是否相同,如果不同,则无法通信!”。 确实有不少孩子会问这个问题。 这个问题稍微思考一下就可以想通了。 请参阅下面的解决方案:

假设有5个温室和1个机房。 机房需要无线采集5个温室的温度。 每个温室里都有一块电路板,板上有温度传感器+单片机+NRF24L01。 单片机通过温度传感器采集温度后,通过NRF24L01发送到机房。 这个例子正是上面童鞋所问的。 温室需要将温度发送到机房。

解决办法是:主机改为从机1的通道后,发送数据命令,从机收到命令后,向主机发送温度数据,主机响应从机收到的数据; 然后主机将通道更改为从机2通道,发送数据命令,从机收到命令后,将温度数据发送给主机,主机响应从机收到的数据……等等。

有些人听了就觉得麻烦。 事实上,机房按照上面的描述采集了5个机房的温度,眨眼间就完成了。

假设机房每5分钟采集一次温室温度,示例程序如下:

main()
{
 //各种初始化配置
 while(1)
 {
 delay()//延时5分钟(每5分钟采集一次数据)
 NRF_CE=0; //拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,10);//修改为从机1的频道
 NRF_CE=1; //拉高CE引脚
 rece_buf[0]=0x66;//这是我规定的从机发送温度命令
 NRF24L01_TxPacket(rece_buf);//告诉从机我要你给我发温度数据
 NRF24L01_RX_Mode();// 配置为接收模式
 while(IRQ==1);//等待发来数据
 NRF24L01_RxPacket(rece_buf);//接收温度数据
 wendu[0]=rece_buf[1];//把采集到的温度数据给了wendu[0]变量
 NRF24L01_TX_Mode();//配置为发送模式
 rece_buf[0]=0x88;//这是我规定的主机接收到温度的回应数据
 NRF24L01_TxPacket(rece_buf);//告诉从机1我收到数据了
 NRF_CE=0; //拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,30);//修改为从机2的频道
 NRF_CE=1; //拉高CE引脚
 rece_buf[0]=0x66;//这是我规定的从机发送温度命令
 NRF24L01_TxPacket(rece_buf);//告诉从机我要你给我发温度数据
 NRF24L01_RX_Mode();// 配置为接收模式
 while(IRQ==1);//等待发来数据
 NRF24L01_RxPacket(rece_buf);//接收温度数据
 wendu[1]=rece_buf[1];//把采集到的温度数据给了wendu[1]变量
 NRF24L01_TX_Mode();//配置为发送模式
 rece_buf[0]=0x88;//这是我规定的主机接收到温度的回应数据
 NRF24L01_TxPacket(rece_buf);//告诉从机1我收到数据了
 NRF_CE=0; //拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,50);//修改为从机3的频道
 NRF_CE=1; //拉高CE引脚
 rece_buf[0]=0x66;//这是我规定的从机发送温度命令
 NRF24L01_TxPacket(rece_buf);//告诉从机我要你给我发温度数据
 NRF24L01_RX_Mode();// 配置为接收模式
 while(IRQ==1);//等待发来数据
 NRF24L01_RxPacket(rece_buf);//接收温度数据
 wendu[2]=rece_buf[1];//把采集到的温度数据给了wendu[2]变量
 NRF24L01_TX_Mode();//配置为发送模式
 rece_buf[0]=0x88;//这是我规定的主机接收到温度的回应数据
 NRF24L01_TxPacket(rece_buf);//告诉从机1我收到数据了
 NRF_CE=0; //拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,70);//修改为从机4的频道
 NRF_CE=1; //拉高CE引脚
 rece_buf[0]=0x66;//这是我规定的从机发送温度命令
 NRF24L01_TxPacket(rece_buf);//告诉从机我要你给我发温度数据
 NRF24L01_RX_Mode();// 配置为接收模式
 while(IRQ==1);//等待发来数据
 NRF24L01_RxPacket(rece_buf);//接收温度数据
 wendu[3]=rece_buf[1];//把采集到的温度数据给了wendu[3]变量
 NRF24L01_TX_Mode();//配置为发送模式
 rece_buf[0]=0x88;//这是我规定的主机接收到温度的回应数据
 NRF24L01_TxPacket(rece_buf);//告诉从机1我收到数据了
 NRF_CE=0; //拉低CE引脚
 NRF24L01_Write_Reg(WRITE_REG+RF_CH,90);//修改为从机5的频道
 NRF_CE=1; //拉高CE引脚
 rece_buf[0]=0x66;//这是我规定的从机发送温度命令
 NRF24L01_TxPacket(rece_buf);//告诉从机我要你给我发温度数据
 NRF24L01_RX_Mode();// 配置为接收模式
 while(IRQ==1);//等待发来数据
 NRF24L01_RxPacket(rece_buf);//接收温度数据
 wendu[4]=rece_buf[1];//把采集到的温度数据给了wendu[4]变量
 NRF24L01_TX_Mode();//配置为发送模式
 rece_buf[0]=0x88;//这是我规定的主机接收到温度的回应数据
 NRF24L01_TxPacket(rece_buf);//告诉从机1我收到数据了
 }
}