STM32
直播中

刘超

7年用户 1426经验值
私信 关注
[问答]

如何对NRF24L01动态数据长度进行配置呢

如何对NRF24L01动态数据长度进行配置呢?
怎样去使用NRF24L01模块呢?



回帖(1)

陈玉英

2021-12-16 15:43:55
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模块的使用也就全部写完了
举报

更多回帖

×
20
完善资料,
赚取积分