打印
[应用相关]

STM32驱动NRF24L01一对多的通信

[复制链接]
1843|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
包含两个方面:
(1)能进行一对多通信(同个频道下一般最多是一对六)
(2)发送的数据包宽度是可变的
沙发
dingbo95|  楼主 | 2018-8-31 14:34 | 只看该作者
配置NRF24L01进行一对多通信,前提是一对一通信机制必须要清楚。
我个人的理解是这样的

PTX端需要配置的地址TX_ADDR和RX_ADDR
PRX端需要配置的地址RX_ADDR
至于以上地址在这个机制中是怎么用的,为什么会相同,下面会解释。

使用特权

评论回复
板凳
dingbo95|  楼主 | 2018-8-31 14:36 | 只看该作者
ShockBurst™下数据包格式:


使用特权

评论回复
地板
dingbo95|  楼主 | 2018-8-31 14:36 | 只看该作者
PTX端发送数据前,会先对数据进行打包。在这个数据包红色框中的就是PTX发射端的地址TX ADDR。当PRX接收到一包有效的数据时,它会解析这个数据包中的Address地址是否跟它自身RX_ADDR相同,如果是相同的,那它就认为这是个发给我的包,如果不相同呢,那肯定是发给别人的包,就会被丢弃。好的,发送和接收都搞明白了,还有应答信号(前提是使能了自动应答)。前面说了PRX会对比Address地址是否跟自身RX_ADDR相同,一旦对比成功,PRX会自动转换到发送模式并以这个地址作为发送地址发送应答信号。那么PTX是怎么接收这个应答信号的呢(前提是使能了自动应答),PTX在发送了一包数据后会自动转换为接收模式,等待接收PRX发过来的应答信号。那PTX是怎么知道需要接收哪个从机发送过来的应答信号呢,PTX端的RX_ADDR就起作用了,PTX也会检测应答包中的地址是不是跟自身的RX_ADDR地址相同,相同就表示这是个正确的应答包,TX_DS中断被触发,MCU通过识别中断号就能知道发送成功。
明白了一对一通信的机制,也就明白了为什么PTX端的TX_ADDR,RX_ADDR,和PRX端的RX_ADDR是相同的。其实这三个地址说白了就是一个地址,就是PRX某个PIPEx的地址,这就是一对多通信的基础

使用特权

评论回复
5
dingbo95|  楼主 | 2018-8-31 14:36 | 只看该作者
一般来说一对多说的是,一个接收N个发送
MultiCeiver(多方通信):
MultiCeiver 是接收模式下的一个功能,包含了一组共六个并行的数据通道,每个通道都拥有独一无二的地址。一个RF通道对应一个逻辑数据通道。在NRF24L01+中,每个数据通道都有其自身的物理地址。

使用特权

评论回复
6
dingbo95|  楼主 | 2018-8-31 14:41 | 只看该作者
NRF24L01+配置成PRX(接收者)后,在同一通信频道中,可以接收6个不同数据通道的数据。6个NRF24L01+被配置为PTX(发送者),他们能与同一个PRX通信。PRX能同时搜寻所有的数据通道。但是同一时刻只有一个数据通道能接收数据包。所有的数据通道都能工作在Enhanced ShockBurst™下。
以下配置所有的数据通道都一样:

CRC使能/失能(CRC在Enhanced ShockBurst™下一般都是被使能的)
CRC编码
RX地址宽度
通信频道
传输速率
LNA增益

使用特权

评论回复
7
dingbo95|  楼主 | 2018-8-31 15:14 | 只看该作者
数据通道的使能在EN_RXADDR寄存器。默认情况下只有数据通道0和1被使能。每个数据通道的地址在RX_ADDR_Px寄存器中设置。
NOTE:确保每个数据通道的地址都是不同的。否则GG

每个通道有5个字节的可配置地址。数据通道0有独一无二的5个字节的地址。数据管道1~5共享4地址字节。但是6个通道的最低字节必须是不同的。

使用特权

评论回复
8
dingbo95|  楼主 | 2018-8-31 15:15 | 只看该作者
图13的例子所示:


使用特权

评论回复
9
dingbo95|  楼主 | 2018-8-31 15:25 | 只看该作者
PRX使用MultiCeiver™ 和 Enhanced ShockBurst™与多个PTX通信。为了确保从PRX发送的应答包能被正确的PTX接收,PRX会获取当前接收到的数据包中的通道地址,然后以这个地址作为发送地址发送应答数据包。图14中的例子解释了PRX和PTX的地址配置详情。在PRX中RX_ADDR_Pn是管道地址,必须是独一无二的。在PTX中TX_ADDR是指定通道的通道地址,必须跟RX_ADDR_P0(没错就是RX_ADDR_P0不是RX_ADDR_Pn)中设置的地址相同。也就是说假如有6个PTX跟1个PRX建立通信,这6个PTX的TX ADDR1~TX ADDR6就必须要一一对应PRX端通道0~通道5的地址,而每个PTX端的接收通道0(RX_ADDR_P0)必须跟其对应的TX ADDR相同。

使用特权

评论回复
10
dingbo95|  楼主 | 2018-8-31 15:27 | 只看该作者
一对多图示

使用特权

评论回复
11
dingbo95|  楼主 | 2018-8-31 15:31 | 只看该作者
只有当一个数据通道接收一个正确的数据包时,其他的通道才能开始接收数据。
二 配置可变宽度的数据包
Enhanced ShockBurst™有两种可供选择的payload长度:
(1)static length,通过设置接收端的RX_PW_Px寄存实现,接收端TX FIFO中的数据长度必须跟接收端设置的想等。
(2)Dynamic payload length(DPL):DPL允许PTX端发送可变长度payload给接收端,而接收端不需要使用RX_PW_Px寄存器,MCU使用R_RX_PL_WID命令能读出payload的长度。

使用特权

评论回复
12
dingbo95|  楼主 | 2018-8-31 15:31 | 只看该作者
使用DPL模式,必须使能FREATURE寄存器的EN_DPL位,在接收模式下,DYNPD寄存器的DPL_Px必须要设置。
NOTE:MCU最好能每次都检查一下接收到的payload的长度是不否大于32字节,如果大于32字节可能是接收到看错误的信息,需要丢弃。丢弃一帧数据包使用Flush_RX命令。
注意:PTX和PRX同时需要设置FREATURE寄存器的EN_DPL位和DYNPD寄存器的DPL_Px位。
举个一对六的配置

使用特权

评论回复
13
dingbo95|  楼主 | 2018-8-31 15:49 | 只看该作者
接收节点
const u8 PIPE0_RX_ADDRESS[RX_ADR_WIDTH]={0x78,0x78,0x78,0x78,0x78};//接收通道0地址
const u8 PIPE1_RX_ADDRESS[RX_ADR_WIDTH]={0xF1,0xB3,0xB4,0xB5,0xB6};//接收通道0地址
const u8 PIPE2_RX_ADDRESS[1]={0xCD};//接收通道0地址,PIPE2~5共用PIPE1的4字节地址,低字节地址在前,下同
const u8 PIPE3_RX_ADDRESS[1]={0xA3};//接收通道0地址
const u8 PIPE4_RX_ADDRESS[1]={0x0F};//接收通道0地址
const u8 PIPE5_RX_ADDRESS[1]={0x05};//接收通道0地址
void NRF24L01_RX_Mode(void)
{
    NRF24L01_CE_L();      
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)PIPE0_RX_ADDRESS,RX_ADR_WIDTH);//写通道0地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)PIPE1_RX_ADDRESS,RX_ADR_WIDTH);//写通道1地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)PIPE2_RX_ADDRESS,1);//写通道2地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(u8*)PIPE3_RX_ADDRESS,1);//写通道3地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P4,(u8*)PIPE4_RX_ADDRESS,1);//写通道4地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P5,(u8*)PIPE5_RX_ADDRESS,1);//写通道5地址
    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3F);    //使能所有通道自动应答   
    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3F);//使能所有接收地址  
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0x40);        //设置发送频道24.064Ghz
//  NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//通道0数据宽度,DPL不需要设置接收数据宽度所以注释掉,下同
//  NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P1,RX_PLOAD_WIDTH);//通道1数据宽度
    NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x04|0x02);    //配合DPL功能使用
    NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x3f);    //使能所有通道DPL功能
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x07);
    NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//主接收
    NRF24L01_CE_H(); //启动接收
}      


使用特权

评论回复
14
dingbo95|  楼主 | 2018-8-31 15:52 | 只看该作者
发送节点0的代码,1~5只要更换本地地址和接收地址就行啦,6个不同的地址下面都列出来了

u8 const PIPE0_TX_ADDRESS[TX_ADR_WIDTH]= {0x78,0x78,0x78,0x78,0x78};    //PTX0本地地址
u8 const PIPE0_RX_ADDRESS[RX_ADR_WIDTH]= {0x78,0x78,0x78,0x78,0x78};    //PIPE0接收地址

u8 const PIPE1_TX_ADDRESS[TX_ADR_WIDTH]= {0xF1,0xB3,0xB4,0xB5,0xB6,};   //PTX1本地地址
u8 const PIPE1_RX_ADDRESS[RX_ADR_WIDTH]= {0xF1,0xB3,0xB4,0xB5,0xB6,};   //PIPE1接收地址

u8 const PIPE2_TX_ADDRESS[TX_ADR_WIDTH]= {0xCD,0xB3,0xB4,0xB5,0xB6};        //PTX2本地地址
u8 const PIPE2_RX_ADDRESS[RX_ADR_WIDTH]= {0xCD,0xB3,0xB4,0xB5,0xB6};        //PIPE2接收地址

u8 const PIPE3_TX_ADDRESS[TX_ADR_WIDTH]= {0xA3,0xB3,0xB4,0xB5,0xB6};        //PTX3本地地址
u8 const PIPE3_RX_ADDRESS[RX_ADR_WIDTH]= {0xA3,0xB3,0xB4,0xB5,0xB6};        //PIPE3接收地址

u8 const PIPE4_TX_ADDRESS[TX_ADR_WIDTH]= {0x0F,0xB3,0xB4,0xB5,0xB6};        //PTX4本地地址
u8 const PIPE4_RX_ADDRESS[RX_ADR_WIDTH]= {0x0F,0xB3,0xB4,0xB5,0xB6};        //PIPE4接收地址

u8 const PIPE5_TX_ADDRESS[TX_ADR_WIDTH]= {0x05,0xB3,0xB4,0xB5,0xB6};        //PTX5本地地址
u8 const PIPE5_RX_ADDRESS[RX_ADR_WIDTH]= {0x05,0xB3,0xB4,0xB5,0xB6};        //PIPE5接收地址

void NRF24L01_TX_Mode(void)
{                                                        
    NRF24L01_CE_L();   
    NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)PIPE0_TX_ADDRESS,TX_ADR_WIDTH);//写发送端的地址
    NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)PIPE0_RX_ADDRESS,RX_ADR_WIDTH);//写接收端PIPE0的地址  

    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能PIPE0自动应答
    NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能PIPE0接收地址
    NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,0x40);
    NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x04|0x02);    //配合DPL功能使用
    NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x3f);    //使能所有通道DPL功能
    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x07);
    NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
    NRF24L01_CE_H();
}

使用特权

评论回复
15
keaibukelian| | 2018-9-1 15:18 | 只看该作者
能带多少个点?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

1197

帖子

5

粉丝