nRF24L01 动态数据长度
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寄存器】
[tr]寄存器功能[/tr]
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:%drn",RX_pipe,length); //打印信息
for(i = 0; i < length; i++){
printf("%x ",RX_FIFO_Buff
);
}
NRF_CE_HIGH; //重新拉高CE,进入接收模式,准备接收下一个数据
}
当【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模块的使用也就全部写完了
nRF24L01 动态数据长度
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寄存器】
[tr]寄存器功能[/tr]
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:%drn",RX_pipe,length); //打印信息
for(i = 0; i < length; i++){
printf("%x ",RX_FIFO_Buff
);
}
NRF_CE_HIGH; //重新拉高CE,进入接收模式,准备接收下一个数据
}
当【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模块的使用也就全部写完了
举报