发射数据时:
(1)首先将nRF24L01配置为发射模式
(2)①接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;
②若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从TXFIFO中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TXFIFO中数据保留以便再次重发;MAX_RT或TX_DS置高时,使IRQ变低,产生中断,通知MCU。最后发射成功时,若CE为低则nRF24L01进入空闲模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入空闲模式2。
1 /********************************************************************** 2 配置NRF为TX模式,并发送一个数据包 3 输入参数tfbuf:即将要发送出去的数据区首地址 4 ***********************************************************************/ 5 void NRF_SendPacket(u8* tfbuf) 6 { 7 CE_LOW; //拉低CE,进入待机模式,准备开始往NRF中的寄存器中写入数据 10 SPI_Write_Buf(WR_TX_PLOAD, tfbuf, TX_PLOAD_WIDTH); //将数据写入TX端的FIFO中,写入的个数与TX_PLOAD_WIDTH设置值相同 12 SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0e); //将NRF配置成发射模式 13 SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e); //写0111 xxxx 给STATUS,清除所有中断标志,防止一进入发射模式就触发中断 14 15 CE_HIGH; //拉高CE,准备发射TX端FIFO中的数据 16 17 delay_ms(1); //CE拉高后,需要延迟至少130us 18 }
接收数据时:
(1)首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来
(2)当接收方检测到有效的地址和CRC时,就将数据包存储在RXFIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。若此时自动应答开启,接收方则同时进入发射状态回传应答信号。最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。
1 /********************************************************************** 2 从NRF的RX的FIFO中读取一组数据包 3 输入参数rx_buf:FIFO中读取到的数据的保存区域首地址 4 ***********************************************************************/ 5 void NRF_ReceivePacket(u8* rx_buf) 6 { 7 CE_LOW; 8 9 SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH); //从RX端的FIFO中读取数据,并存入指定的区域,注意:读取完FIFO中的数据后,NRF会自动清除其中的数据 10 SPI_Write_Byte(WRITE_REG_CMD+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志 11 12 CE_HIGH; //重新拉高CE,让其重新处于接收模式,准备接收下一个数据 13 }
①接收地址与发送地址为什么要设定成一样的?
a.了解接收端与发送端的职责:
发送端(手柄)的职责:发送数据给接收端,接收某接收端的应答信号。
接收端(飞机)的职责:接收发送端发送的数据,发送应答信号给发送端。
b.对接收&发送地址的阐述:
1.
因此程序中要将发送地址和接收地址配成一样的,这样发射端可以正常收到接收端发送的应答信号,确保通信成功。
1 u8 TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //--本地地址 2 u8 RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //此地址用来配置本机NRF的RX0通道的地址,同时为了能正常收到应答信号,此地址一般都和上面的地址配置相同
写寄存器进行TX_ADDR,TX_ADDR地址配置:
1 SPI_Write_Buf(WRITE_REG_CMD + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); 2 SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);
②如何抛开接收端(飞机),来进行调试(遥控器)发送是否成功?
NRF24L01是收发双方都需要编程的器件,这就对调试方法产生了一定的要求,如果两块一起调,那么通讯不成功,根本不知道是发的问题还是收的问题;
发送方:发送-等应答-(自动重发)-触发中断 可是这样的流程就已经把接收方给牵涉进来了,就是说一定要接收方正确收到数据并且回送应答信号之后发送方才能触发中断,结束一次完整的发送。可是这跟我们的初衷不相符,我们想单独调试发送,完全抛开接收,这样就要去配置一些参数来取消自动应答,取消自动重发,让发送方达到发出数据就算成功的目的。
于是通过以下三语句将发送端的流程就变成了发送-触发中断。这样就抛开了接收方,可以专心去调试发送端
1 //测试NRF作为发射端的时候是否能发出数据的测试代码,程序正常运行时,可以注释掉 2 SPI_Write_Byte(WRITE_REG_CMD + SETUP_RETR, 0x00); 3 SPI_Write_Byte(WRITE_REG_CMD + EN_AA, 0x00); 4 SPI_Write_Byte(WRITE_REG_CMD + EN_RXADDR, 0x00);
参考博客:
发送地址和接收地址问题参考https://blog.csdn.net/qq_26602023/article/details/51016724
调试单端参考https://blog.csdn.net/q553716434/article/details/9996985