stm32【 NRF24L01多通道、动态数据、主从一体(3)】

本文详细介绍了nRF24L01模块动态数据长度的配置方法,包括初始化配置、数据发送及接收流程。通过修改配置函数,实现了单/多通道动态数据长度的主从通讯,提供了动态数据长度下的发送与接收函数。

nRF24L01 动态数据长度

回顾
NRF 1对1通讯
NRF多通道通讯
在前面两篇文章里,实现的主从一体的单通道,多通道通讯,接下来讲解关于动态数据长度的配置,是在多通道的基础是进行修改的,而且本篇文章是作为nRF24L01模块调试的最终篇章,将实现单/多通道,动态数据的主从一体的所有功能

在前面的文章里,都是接收特定长度的数据包,数据个数通过【STATIC_PLOAD_LENGTH】设置,当接收到这么多个数据后,会在IRQ输出一个低电平,触发中断
而动态数据长度,指的是接收不同长度的数据包,接收到数据后就会在IRQ输出一个低电平,触发中断,此时得先知道本次接收的数据包内有n个有效数据,再读出n个数据
注意:无论是静态还是动态长度的数据包,有效数据不能超过32个(byte)

nRF动态数据长度配置

【void NRF_Config(void)】函数修改成下面给出的▼

void NRF_Config(void)
{
	NRF_SPI_Config();
	
	//拉低CE,注意:需要将CE拉低,使其进入待机或者掉电模式才能读/写nRF寄存器
	NRF_CE_LOW;
	
	//初始化NRF(看数据手册)
	NRF_SPI_WriteReg(W_REGISTER | SETUP_AW, 0x03);							//配置通信地址的长度,默认值时0x03,即地址长度为5字节
	NRF_SPI_WriteReg(W_REGISTER | SETUP_RETR, 0x15); 						//自动重发延迟为500+86us,重发次数5次
	NRF_SPI_WriteReg(W_REGISTER | RF_SETUP, 0x07);   						//设置发射速率为1MHZ,发射功率为最大值0dB
	NRF_SPI_WriteReg(W_REGISTER | RF_CH, 30);        						//设置通道通信频率,工作通道频率可由以下公式计算得出:Fo=(2400+RF_CH)MHz.并且射频收发器工作的频率范围从2.400-2.525GHz

#if RX_MULIT_CHANNEL
//---------------------------PRX:多通道配置----------------------------------------------------------------------------	
																				//通道0和1完整赋值,通道2-5只能赋值地址的第一个(最低byte)
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P0, RX_ADDRESS_0, ADDRESS_WIDTH); 	//配置PRX接收通道0的接收数据的地址
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P1, RX_ADDRESS_1, ADDRESS_WIDTH); 	//配置PRX接收通道1的接收数据的地址
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P2, RX_ADDRESS_2, 1); 				//配置PRX接收通道2的接收数据的地址
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P3, RX_ADDRESS_3, 1); 				//配置PRX接收通道3的接收数据的地址
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P4, RX_ADDRESS_4, 1); 				//配置PRX接收通道4的接收数据的地址
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P5, RX_ADDRESS_5, 1); 				//配置PRX接收通道5的接收数据的地址

	NRF_SPI_WriteReg(W_REGISTER | EN_AA, 0x3F);      						//接收数据后,允许所有通道自动应答
	NRF_SPI_WriteReg(W_REGISTER | EN_RXADDR, 0x3F);  						//允许所有通道接收数据

//---------------------------PRX:接收数据长度配置----------------------------------------------------------------------------	
	#if DYNAMIC_PLOAD_LENGTH //动态长度
		NRF_SPI_WriteReg(W_REGISTER | FEATURE, 0x06);   						//配合DPL功能使用
		NRF_SPI_WriteReg(W_REGISTER | DYNPD, 0x3f);    							//使能所有通道的DPL功能
	#else //固定长度,接收的数据到达STATIC_PLOAD_LENGTH长度时,才会触发RX_DS中断
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P0, STATIC_PLOAD_LENGTH);
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P1, STATIC_PLOAD_LENGTH);
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P2, STATIC_PLOAD_LENGTH);
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P3, STATIC_PLOAD_LENGTH);
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P4, STATIC_PLOAD_LENGTH);
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P5, STATIC_PLOAD_LENGTH);
	#endif
//---------------------------PTX:多通道配置------------------------------------------------------------------------	
	//发送通道地址,由于是多通道,在发送函数里选择配置


#else
//---------------------------PRX:单通道配置------------------------------------------------------------------------	
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P0, RX_ADDRESS_0, ADDRESS_WIDTH); 	//配置本机接收通道0的接收数据的地址
	NRF_SPI_WriteReg(W_REGISTER | EN_AA, 0x01);      						//接收数据后,只允许频道0自动应答
	NRF_SPI_WriteReg(W_REGISTER | EN_RXADDR, 0x01);  						//只允许频道0接收数据
	
//---------------------------PRX:数据接收长度配置----------------------------------------------------------------------------	
	#if DYNAMIC_PLOAD_LENGTH	//动态数据长度
		NRF_SPI_WriteReg(W_REGISTER | FEATURE, 0x06);   						//配合DPL功能使用
		NRF_SPI_WriteReg(W_REGISTER | DYNPD, 0x01);    							//使能通道1的DPL功能
	#else	//固定数据长度
		NRF_SPI_WriteReg(W_REGISTER | RX_PW_P0, STATIC_PLOAD_LENGTH);
	#endif
//---------------------------PTX:单通道配置------------------------------------------------------------------------	
	//发送通道地址,由于是单通道,在这里配置一次就可以了(默认通道0)
	NRF_SPI_WriteBuf(W_REGISTER | TX_ADDR, RX_ADDRESS_0, ADDRESS_WIDTH);    	//发送的数据包中被一块打包进去的接收端NRF的接收通道的地址

#endif

	NRF_SPI_WriteReg(W_REGISTER | CONFIG, 0x0C | PWR_UP | PRIM_RX);   			//默认处于接收模式

	NRF_CE_HIGH;
	delay_ms(2);

}

这是由多通道的nRF配置函数修改来的,分别在【PRX:多通道配置】和【PRX:单通道配置】里再添加一个判断【DYNAMIC_PLOAD_LENGTH】,将单/多通道的固定数据长度和动态数据长度划分开来

当【DYNAMIC_PLOAD_LENGTH = 0】,单/多通道的数据长度配置和原来的一样
当【DYNAMIC_PLOAD_LENGTH = 1】,单/多通道只需要配置两个寄存器,分别是【FEATURE寄存器】和【DYNPD寄存器】

寄存器功能
FEATURE启动动态有效数据和自动应答等功能
DYNPD启动各个通道以动态有效数据对数据包进行接收的功能

详细的请看数据手册9.1章节
基础配置就这些,只是添加了四行代码

nRF数据发送(动态数据长度)

和固定数据长度不同,动态数据长度除了要给出接收通道地址和待发送的数组以外,还需要给出本次发送多少个数据,因此创建一个新的发送函数

/********************************************************************************
  * @brief  PTX模式下发送一个可变长度的数据包
  * @param  RX_ADDRESS_X	发送到的通道地址,在单通道模式下该值无效,默认通过通道0发送
  * @param	TX_BUFF			待发送的数据缓冲区
  * @param	length			数据个数
  * @retval none
  *******************************************************************************/
void NRF_SendPacket_DPL(u8 *RX_ADDRESS_X,u8 * TX_BUFF, u32 length)
{
	NRF_TX_Mode();

	NRF_CE_LOW;																//拉低CE,进入待机模式,准备开始往NRF中的寄存器中写入数据
#if RX_MULIT_CHANNEL
//---------------------------多通道发送地址选择---------------------------------------------------------------
	//RX_ADDRESS_X:PTX选择发送到PRX的哪一个通道
	NRF_SPI_WriteBuf(W_REGISTER | TX_ADDR, RX_ADDRESS_X, ADDRESS_WIDTH);
	//PTX使用pipe0来接收PRX的Auto-ACK信号
	//所以将RX_ADDRESS_X填入pipe0,这样才能对比Auto-ACK附带的通道地址
	//在退出PTX时要将RX_ADDRESS_0赋值给RX_ADDR_P0
	NRF_SPI_WriteBuf(W_REGISTER | RX_ADDR_P0, RX_ADDRESS_X, ADDRESS_WIDTH); 
#else //---------------------------单通道发送地址------------------------------------------------------------	
		//在NRF_Config里设置一次就行
#endif

	NRF_SPI_WriteBuf(WR_TX_PLOAD, TX_BUFF, length); 						//将数据写入TX端的FIFO中,写入的个数与TX_PLOAD_WIDTH设置值相同
	NRF_CE_HIGH;															//拉高CE,准备发射TX端FIFO中的数据
																			//CE拉高后,nRF自动延迟130us后,发送数据
}

这个函数和上一篇NRF多通道通讯给出的【void NRF_SendPacket(u8 *RX_ADDRESS_X,u8 *TX_BUFF)】函数基本是一致的,只是【NRF_SPI_WriteBuf(WR_TX_PLOAD, TX_BUFF, length);】这一句代码,使用的是传递进去的参数【length】,而不是【STATIC_PLOAD_LENGTH】

在写这篇文章的时候想到,其实这两个函数是可以写成一个函数的,不过发送和接收函数都是要看具体的应用来写,就没有修改了,这里只是提供一个思路罢了

nRF数据接收(动态数据长度)

在固定长度的情况下,读出数据的个数是知道的,
直接调用指令【RD_RX_PLOAD】就能读出数据▼

NRF_SPI_ReadBuf(RD_RX_PLOAD,RX_FIFO_Buff,STATIC_PLOAD_LENGTH);

而动态数据长度下,要用另一条指令【R_RX_PL_WID】先读出本次数据包内的有效数据个数,再调用指令【RD_RX_PLOAD】从RX_FIFO内读出指定个数的数据,因此接收函数修改成这样▼

/********************************************************************************
  * @brief  PRX模式下从RX_FIFO中接收一个数据包
			同时读出通道值
  * @param  none
  * @retval none
  *******************************************************************************/
void NRF_ReceivePacket(void)
{
	u8 i;
	u32 length;
	
	NRF_CE_LOW;
	
#if DYNAMIC_PLOAD_LENGTH
	length = NRF_SPI_ReadReg(R_RX_PL_WID);
	NRF_SPI_ReadBuf(RD_RX_PLOAD,RX_FIFO_Buff,length);				//从RX端的FIFO中读取数据,并存入指定的区域,注意:读取完FIFO中的数据后,NRF会自动清除其中的数据
#else
	length = STATIC_PLOAD_LENGTH;
	NRF_SPI_ReadBuf(RD_RX_PLOAD,RX_FIFO_Buff,STATIC_PLOAD_LENGTH);	//从RX端的FIFO中读取数据,并存入指定的区域,注意:读取完FIFO中的数据后,NRF会自动清除其中的数据
#endif

	RX_pipe = (status & 0x0E) >> 1;									//读取通道值
	
	printf("pipe%d  length:%d\r\n",RX_pipe,length);					//打印信息
	for(i = 0; i < length; i++){
		printf("%x ",RX_FIFO_Buff[i]);
	}
	
	NRF_CE_HIGH;													//重新拉高CE,进入接收模式,准备接收下一个数据
}

当【DYNAMIC_PLOAD_LENGTH = 0】时和之前的一样
当【DYNAMIC_PLOAD_LENGTH = 1】时,调用指令【R_RX_PL_WID】得到长度后,再读取数据

nRF24L01动态数据长度总结

本篇文章再NRF多通道通讯基础上修改了两个函数,并且新增加一个数据发送函数

void NRF_Config(void);			//nRF初始化
void NRF_ReceivePacket(void);
void NRF_SendPacket_DPL(u8 *RX_ADDRESS_X,u8 * TX_BUFF, u32 length);	//发送动态长度有效数据包

实现动态数据长度的功能,在主函数使用动态数据长度功能时将数据个数也一并传参就行了

	NRF_SendPacket_DPL(RX_ADDRESS_2,pack,sizeof(pack));

到此,对于nRF24L01模块的使用也就全部写完了

评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值