NRF24L01+实现一对一数据双向传输

  • 目录
    • 说明
    • 带负载数据ACK的双向通信
    • 配置NRF24L01+的收发程序
    • 收发双方数据的处理
    • 测试代码和结果

目录

说明

最近在diy四轴飞行器的时候,需要实现四轴和遥控器之间的双向通信。手头上用的模块是NRF24L01+和SI24R1,这两个芯片的引脚功能相同,不仅硬件上可以直接进行替换使用,程序往往还可以互用(因为还是有点差别),两个芯片的差别很小,其中一个是SI24R1的功率最大达到7dB,而NRF24L01+最大是0dB,这个在配置参数的时候要注意。
NRF24L01+和SI24R1都可以配置为发送或接收模式,为了减少打字的麻烦,下文全都以NRF24L01+来写。实现四轴和遥控器的双向通信,可以让NRF24L01+不断在收/发模式之间直接进行切换,小马哥的四轴用的就是这种方式,但我用HAL库实现这种方式的时候,会出现这种问题:两者可以进行双向的数据传输,但一会儿之后就不能传输了,我也不清楚是怎么回事。
后来查询芯片数据手册,仔细研究NRF24L01+的工作方式之后,发现NRF24L01+工作在ACK模式时,发送端发送数据给接收端时,接收端收到并检验数据无误后,会回复一个ACK信号给发送端,收到ACK的发送端就认为数据发送完成,并产生TX_DS中断,这就是一个应答机制。而接收端回复的ACK信号可以是选择带负载数据的,利用这一点,就可以把接收端要回传的数据发送回发送端,以此来实现双向数据传输。

带负载数据ACK的双向通信


要使用带负载数据的ACK信号(ACKPAYLOAD)需要配置FEATURE寄存器中的EN_ACK_PAY位,同时收发双方要开启动态负载长度(通过配置DYNPD和FEATURE寄存器来实现)。

配置NRF24L01+的收发程序

程序改自正点原子的实验例程。
接收方

 NRF24L01_CE=0; NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);   //使能通道0的接收地址    NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);           //设置RF通信频率        NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度         NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);    //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);       //使能通道0的自动应答  NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x06);     //使能动态负载(收发数据)长度NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x01);       //使能通道0动态负载长度NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);     //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式NRF24L01_CE=1;

发送方

 NRF24L01_CE=0;     NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址 NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACKNRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //设置RF通道为40NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x07); //使能动态负载(收发数据)长度NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x01);   //使能通道0动态负载长度NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);   //使能通道0的自动应答    NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);  //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断NRF24L01_CE=1;//CE为高,10us后启动发送

以上配置经过测试是可以使用的,在NRF24L01+之间,SI24R1之间,NRF24L01和SI24R1之间都可以进行双向通信。

收发双方数据的处理

首先是写两个发送数据的函数(其实这两个函数是把数据写入到发送缓冲区,而不是实现数据的发送)
一个是发送端主动发送数据给接收端:

void nrf_txPacket(u8 *txbuf,u8 len)
{NRF24L01_CE=0;NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,len);//写数据到TX BUFNRF24L01_CE=1;
}

另一个是接收端回复带负载数据的ACK信号(把要回传的数据写入到发送缓冲区,等待接收端自动发送应答信号)

void nrf_txPacket_AP(u8 *txbuf,u8 len)
{NRF24L01_CE=0;NRF24L01_Write_Buf(W_ACK_PAYLOAD(0),txbuf,len);//写数据到TX BUFNRF24L01_CE=1;
}

然后是处理数据的函数,我是在中断回调函数里处理的

     u8 sta = NRF24L01_Read_Reg(NRF_READ_REG + STATUS);if(sta & TX_OK){NRF24L01_CE = 0;NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS,TX_OK); //清除发送完成标志·NRF24L01_Write_Reg(FLUSH_TX,0xff); //清除TX_FIFO//在这里对发送完的数据进行数据处理NRF_TX_DATA[0]++;NRF24L01_CE = 1;}if(sta & RX_OK){NRF24L01_CE=0;u8 len = NRF24L01_Read_Reg(R_RX_PL_WID);if(len>0 && len<33)//数据长度有效{NRF24L01_Read_Buf(RD_RX_PLOAD,NRF_RX_DATA,len);}nrf_txPacket_AP(NRF_TX_DATA,1);//发送ACK Payload,数据长度为1NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS,RX_OK);//清除发送完成标志NRF24L01_Write_Reg(FLUSH_RX,0xff); //清除RX_FIFONRF24L01_CE=1;}if(sta & MAX_TX){NRF24L01_CE = 0;NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,MAX_TX);//清除达到最大重发标志NRF24L01_Write_Reg(FLUSH_TX,0xff); //清除TX_FIFONRF24L01_CE = 1;}

测试代码和结果

接收端的代码:显示接收端接收到的和发送出去的数据

 while(1){LCD_ShowxNum(30+14*8,170,NRF_RX_DATA[0],3,16,0);LCD_ShowxNum(30+14*8,190,NRF_TX_DATA[0],3,16,0);delay_ms(1);    t++;if(t==1000)//大约1s钟改变一次状态{t=0;LED0=!LED0;} }

发送端的代码:显示发送端发送的数据和接收到的数据

 while(1){LCD_ShowxNum(30+14*8,170,NRF_RX_DATA[0],3,16,0);LCD_ShowxNum(30+14*8,190,NRF_TX_DATA[0]++,3,16,0);delay_ms(1);    t++;if(t==1000)//大约1s钟改变一次状态{t=0;LED0=!LED0;nrf_txPacket(NRF_TX_DATA,1);}}

测试效果


最后,本人没什么写博客的经验,表达不够清晰,写的也比较水,为的是记录一下调试的经历,如果表述中有什么错误的地方欢迎各位大佬批评指正。想知道更详细的内容需要查阅一下数据手册,了解一下NRF24L01+/SI24R1的工作流程。

NRF24L01+实现一对一数据双向传输相关推荐

  1. 分包组包 北斗通信_一种利用北斗短报文实现第三方数据双向传输的方法与流程...

    本发明涉及通信技术领域,特别涉及一种利用北斗短报文实现第三方数据双向传输的方法. 背景技术: 中国北斗卫星导航系统是中国自行研制的全球卫星导航系统,北斗RDSS是北斗系统区别于其他导航系统的特点之一, ...

  2. 基于NRF24L01的CAN数据透传

    闲谈: 闲来无聊,恰好公司又经常用CAN数据的传输,自己觉得要是用无线传送多好,然后,就是一个奇想,就想做一个无线数据的透传,恰好身边又有NRF24L01,那就行动吧! 下面是NRF24L01 SPI ...

  3. 【STM32+cubemx】0026 HAL库开发:NRF24L01无线2.4G通信模块的应用

    NRF24L01是NORDIC公司生产的一款无线通信通信芯片,可以工作在免费开放的2.4GHz频段:通信速率可以达到最高2Mbps:MUC可以使用SPI接口与它交互. 本节我们就来使用stm32驱动N ...

  4. 基于arduino与raspberry的远程数据采集系统

    前言 该课题是毕业时做的一个远程数据采集课题,今天无意翻看到这份报告,不禁勾起满满的怀念.重新看了一遍报告,感觉做的确实是挺low的,但想起当时自己查了无数的资料,才完成这个设计,尤其是人在学校,然后 ...

  5. NRF24L01模块多发一收通信(STM32)

    NRF24L01模块多发一收通信(STM32) 目录 NRF24L01模块多发一收通信(STM32) 前言 一.解决思路 二.实验过程 1.设备ID号定义 2.数据打包发送 3.数据接收拆解 总结 前 ...

  6. NRF24L01模块配置

    发射数据时:   (1)首先将nRF24L01配置为发射模式   (2)接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低 ...

  7. 外设驱动库开发笔记26:nRF24L01无线通讯驱动

    现在无线在我们的生活中无处不在.而我们开发的物联网产品也大量使用无线通讯.在这一篇文章中,我们将讨论nRF24L01无线通讯模块驱动程序的开发与实现. 1.功能概述 nRF24L01是一款工作在2.4 ...

  8. 【STM32】NRF24L01模块的收发调试

    NRF24L01 发送端.c文件 发送端.h文件 接收端.c文件 接收端.h文件 接收端main函数 总结: 这里我是用了两块板子来做通信实验,这里我就直接贴发送端和接收端的.c.h文件,一个是用标准 ...

  9. HAL库驱动NRF24L01实现数据传输

    文章目录 1.NRF24L01介绍 2.驱动程序设计 1.根据原理图进行封装 2.cubemx配置 3.收发测试 4.源代码 本次使用正点原子精英开发板和野火MINI开发板进行采用NRF24L01的数 ...

最新文章

  1. 谷歌发布深度学习新算法,适用于真实机器人的技能学习
  2. 波士顿动力机器狗要去切尔诺贝利上班了
  3. InfoPath表单实战
  4. 电脑声音太小如何增强_感觉手机音量太小了?教你这样设置,声音立马大上许多...
  5. 大型网站系统与Java中间件实践pdf
  6. Git开发流程和工作流
  7. html5自动打印图片,html2canvas生成清晰的图片实现打印代码示例
  8. Current在Java里面_在C#中相当于Java System.currentTimeMillis()
  9. Bulma - 基于 Flexbox 的现代化的 CSS 框架
  10. 汇编语言上机考试三星题——判断一个不超过65535的整数是否为质数
  11. 管理感悟:测试的目的是什么
  12. GitLab上配置SSH Key
  13. python构建决策引擎_决策引擎与机器学习模型的集成 | 信数这么干(一)
  14. 基于冲突的搜索算法(CBS)个人笔记
  15. linux dumpe2fs命令
  16. K-mean 算法代码演示
  17. 第14周—项目1(3)二叉排序树
  18. 海信研发前端工程师面试经验总结
  19. 极坐标t1t2几何意义_复数与几何(一) 基本几何性质及应用
  20. 禁止查看写好的宏_??智能作业灯T5体验:不在孩子身边,也能辅导小朋友写作业...

热门文章

  1. thinkphp5 实现短信注册验证功能
  2. 谷歌的代码覆盖率最佳实践
  3. 唯众高职物联网应用技术专业解决方案
  4. solidworks批量图号分离_教你如何将SolidWorks2016图号名称分离到零件属性中
  5. Threejs实现键盘控制人物行走跳动/Capsule碰撞体(胶囊体)/碰撞检测(Octree八叉树)/游戏第三人称/镜头跟随人物移动
  6. 记录一下自己vscode的代码合并功能的使用
  7. CC00339.CloudKubernetes——|KuberNetes运维.V56|——|Prometheus.v01|自动发现.v01|创建secret|
  8. BMS中SOC的计算(一)
  9. 【自动驾驶模拟器AirSim快速入门 | 04】推理预测及模拟器运行
  10. Elasticsearch 8.X “图搜图”实战