本文将深度解析一款烂大街的无线芯片,NRF24L01(及国产完全兼容的SI24R1)。实在是现在网上很多写NRF24L01的文章抓不到重点,一些冷门用法没人写,就写了这个文章。推荐选用SI24R1,原因是功能完全相同,但SI24R1内置PA,最大输出是7dbm,而挪威原版的NRF24L01+最大输出只有0dbm。因为2.4G是ISM频段,功率即正义!

以下以SI24R1为例进行说明

读写控制

spi配置

遵循以下配置即可:

  1. CPOL 1 & CPHA 1或者CPOL 0 & CPHA 0,手册推荐使用后者,但是前者也是能用的
  2. SPI CLK 配置10MHZ以下即可
  3. SPI位宽配置为8bit
  4. MSB在前

读寄存器

  1. 手册明确说明,CS拉低后的第一个字节被认为是命令字,这样也就没办法做常CS了,也就是必须把CS接到MCU,并保证在传输命令字之前CS有一个下降沿,这样才能读写有效!
  2. 所有的命令字如下
    按照说明进行配置就可以了

基本传输

不使用其ARQ机制(在NRF24L01+被称为Enhanced ShockBurst™)的话,一次最基础的传输需要配置的寄存器数量是非常少的。

RX配置:

EN_AA(0x01) → 0x00 配置不使用自动ACK

EN_RXADDR(0x02) → 0x01 配置使能接收地址0

SETUP_SW(0x03) → 0x03 配置使用5字节地址,这个地址最好长一点,虽然短了会省一些空中带宽,但是也会增加碰撞的概率,为了稳定性,最好还是用最长的

RF_SETUP(0x06) → 0x07 配置使用1MBPS的空速,最大输出功率

RX_PW_P0(0x11) → 0x0A 配置使用固定接收长度10

CONFIG(0x00) → 0x03 配置使能,配置为接收模式

RF_CH(0x05) → 0x0A 配置射频信道为10,即2410MHZ,这个地方要注意,当使用2MBPS的空速时,相邻信道间最小要间隔2MHZ的频率,对于1MBPS和256kbps来说,信道间隔为1MHZ即可

RX_ADDR_P0 → 任意五字节地址,配置接收地址0

TX_ADDR → 任意五字节地址,最好和RX_ADDR_P0一样

TX配置:

将CONFIG的最低位设置为0,其他与RX一样。

需要注意的地方是,在配置CONFIG的时候,CE必须为低,因为模块不允许在工作模式下配置收发模式。

对于TX_ADDR和RX_ADDR的理解是这样的,RX_ADDR为要接收谁发送的消息,每个模块在发送的时候把自己的TX_ADDR写进去,这样所有的模块都去监测空中消息,当空中消息的ADDR与自己的某个使能的RX_ADDR匹配时就会进行接收。

参数配置

完整的配置时序如下:

发送处理

数据发送的时序,目前由于配置的是固定接收长度,因此需要写入正好10字节才能进行正常传输,,又由于我们没有屏蔽任何中断,因此当发送成功后会触发一次中断,一般在发送之前先调用FLUSH_TX(0xE1)命令清除一下FIFO,避免堆积导致的阻塞。

中断中需要读取STATUS寄存器,并将其写回,写回的动作将会清除中断

接收处理

接收端在接收到数据后会触发一个中断,同样的读取STATUS寄存器确定是否是接收中断,并在此之后清除STATUS。然后通过命令R_RX_PL_WID(0x60)指令读取当前接收到的数据包的长度,当然当长度约定为固定值时,该行为可以忽略。

之后按照长度将数据读取出来即可,一般在读取结束之后使用FLUSH_RX(0XE2)清除一下FIFO,避免堆积可能导致的阻塞

添加CRC

crc是硬件行为,当侦测到crc错误的时候,按照基本传输配置的话,接收端将不会产生数据接收中断。配置方式就是将CONFIG寄存器当中对应的位置上就可以了,其他配置与基本传输相同。

RX配置:

CONFIG(0x00) → 0x0F 配置使能,配置为接收模式,启用CRC16

TX配置:

CONFIG(0x00) → 0x0E 配置使能,配置为发送模式,启用CRC16

使用动态长度

如果都是用静态长度的话,其实传输不够灵活,所以NRF24L01提供了动态负载长度的功能,使用动态负载长度之后,只管对TX FIFO写入数据,只要别超过32字节就可以,因为FIFO深度就是32。写入结束后,直接拉起CE启动传输,数据就会被打包传输。此时在接收端只需要检查接收长度,并按照接收长度读取出数据即可。上面做普通传输的地方已经写了怎么在中夺冠中获取接收到的长度。使用动态负载长度后,对于RX_PW_Px寄存器就可以不去设置了。此时需要在TX和RX中多配置两个寄存器,分别如下:

TX&RX

DYNPD(0x1C) → 0x01 使能通道1的动态负载长度

FEATURE(0x1D) → 0x04 使能动态负载长度特性

使用ARQ(Enhanced ShockBurst™)

这个特性不知道为什么被很多人吐槽为影响稳定性,实际测试正确的使用ARQ还是对丢包问题有一定改善的。

这个特性原理很简单,就是NRF24L01内置了引擎,当发送完一个数据包后自动转入接收模式等待ACK,接收端接收到数据包之后,自动切换到发送模式发送一个ACK,之后切换回接收模式。发送端接收到ACK后切换回发送模式。一旦发送端没有接收到ACK,在延迟设定的时间后会发起一次重发,直到成功收到ACK或者到达最大重发次数。下面这个图就是一个传输过程的示意图:

里面关于中断的说明,当接收机第一次接收到数据包之后会触发一次RX中断,由于ACK丢失,主机不会产生TX完成中断而是会进行重发,接收机收到重发的包之后,因为之前已经接收过该数据包,则数据包被丢弃,但是会自动ACK,主机收到正常的ACK之后才会产生TX完成中断。

使用ARQ比较简单,只需要使能该特性,并配置最大重传次数和重传延迟时间就可以了,需要注意的是使用ARQ时必须使能CRC且需要设置RX_ADDR_P0与TX_ADDR相同,必须设置地址相同的原因是,接收机回ACK的时候会将数据包的地址写进去,这个地址就是之前发送方发送时填进去的TX_ADDR,如果发送方想收到这个ACK就必须配置成可以接收这个地址的配置,也就是RX_ADDR_P0需要与TX_ADDR相同。相对于基本传输,修改EN_AA的配置并多配置一个寄存器即可

RX & TX

EN_AA(0x01) → 0x01 配置通道0使用自动ACK

SETUP_RETR(0x04) → 0x35 配置最大重传5次,重传延迟1ms,需要注意这个地方,手册有说明不同空速下有一个最短的重传时间配置

多发单收

由上面介绍地址匹配时说到,单个NRF24L01接收地址可以配置6个,也就是说一个NRF24L01可以接收来自于6个模块的消息,只要没有发生碰撞即可。使用多地址也很简单,使能对应的通道,并配置接收地址即可,需要注意的是,手册有对地址设置限制的介绍:

当接收到数据后,在中断中对STATUS寄存器进行判断即可获取是哪个通道发送过来的数据。

带载ACK

使用ARQ时会自动传输一个ACK,既然已经有ACK了,那没有理由阻拦我们在ACK中带点东西回去,NRF24L01同样提供了带载ACK的选项。

需要注意,使用带载ACK的话必须使能动态负载长度,其主要需要修改的寄存器为FEATURE

TX & RX

FEATURE(0x1D) → 0x06 使能动态负载长度特性并使能带载ACK

使用时,接收机需要先把想要在接收到数据之后填进ACK的数据写入FIFO,写入地址为W_ACK_PAYLOAD(10101ppp b)其对应二进制码中的ppp为接收通道,也就是可以针对接收通道进行定制返回的信息,注意这个地方写入的地址不是W_TX_PAYLOAD。

其FIFO深度为32,共三页,建议一般使用其中一页即可。

负载写入后,当接收机接收到对应通道的数据后,就会将负载加到ACK包中返回。

对于发送放来说,ACK包返回触发的是TX完成中断,但是对于带载的数据包来说,同时还会触发RX中断,发送方按照正常的接收操作来进行就可以,数据还是通过R_RX_PAYLOAD进行读取。

按照手册的说法,数据应该在发送方发送之前写入,实际测试在数据接收中断中写入数据到W_ACK_PAYLOAD是可以随当次ACK返回的,但是会存在把模块卡死的概率,并不推荐这样使用,最好还是按照手册说明,尽量不要这么做。

半双工方式工作

通过手动切换模式可以达成半双工传输的模式。即模块上电后默认配置为接收模式,要发送是切换到发送模式,发送完成立刻切换回接收模式。在此过程中一定要注意状态转移图,在模块的不同状态切换之间是需要时间的,主要要符合时序要求才能稳定工作。

总结

总的来说NRF24L01还是一款相对来说比较有可玩性的无线模块,只是功率实在小了一点,在ISM频段,被干扰的概率过高,可以考虑上个PA什么的,这样可用性会提高很多。顺带该模块的状态转移速度还算比较快,可以考虑基于此模块做一下跳频算法,这样可以有效的提高抗干扰的能力,等有什么时候有兴趣了可以再写一下使用NRF24L01设计一套慢跳频的机制来提升其抗干扰能力的文章。

深度解析NRF24L01相关推荐

  1. 单文件浏览器_图文并茂深度解析浏览器渲染原理,包看懂超值得收藏

    在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广 ...

  2. 舒工深度解析不规则场地座位二维码生成规则

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

  3. 今晚8点开播 | 深度解析知识图谱发展关键阶段技术脉络

    作为知识图谱领域形成过程的亲历者之一,AI科技大本营此次邀请到文因互联 CEO 鲍捷,他将对知识图谱的历史渊源进行梳理,对该领域几次发展的主要技术突破做深度解析,并分析其工业落地的几个关键点.欢迎大家 ...

  4. 多目标跟踪算法FairMOT深度解析

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨周威@知乎 来源丨https://zhuanlan.zhihu.com/p/259356109 ...

  5. 深度解析工业软件:研究框架(140页)

    来源:跨越鸿沟 本文多图,建议阅读6分钟. 本文为你深度解析工业软件:研究框架 工业软件的核心,不仅是"软件",更是"工业". 有什么样的工业流程,就有什么样的 ...

  6. 科普|深度解析5G与未来天线技术

    来源:电子万花筒 过去二十年,我们见证了移动通信从1G到4G LTE的转变.在这期间,通信的关键技术在发生变化,处理的信息量成倍增长.而天线,是实现这一跨越式提升不可或缺的组件. 按照业界的定义,天线 ...

  7. 深度解析:mPaaS 3.0全新组件

    摘要:以"数字金融新原力(The New Force of Digital Finance)"为主题,蚂蚁金服ATEC城市峰会于2019年1月4日上海如期举办.分论坛上,蚂蚁金服产 ...

  8. 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一第1章 C语言与内存1.1 引言...

    本节书摘来自异步社区<嵌入式Linux与物联网软件开发--C语言内核深度解析>一书中的第1章,第1.1节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区"华章计算机&quo ...

  9. 2008年12月13日上海USB驱动开发深度解析讲座PPT

    讲座PPT:宋宝华2008年12月13日上海USB驱动开发深度解析讲座PPT [url]http://www.linuxdriver.cn/200812/20081213172619_836.rar[ ...

最新文章

  1. 汽车车灯灯具系统(下)
  2. 程序员面试系列——插入排序
  3. HTTP状态码一览表(HTTP Status Code)
  4. sql server系统表详细说明(转)
  5. mysql 行转列分级输出_MySQL如何实现行转列分级输出?_MySQL
  6. 深入react技术栈(9):表单
  7. IBM SOA[ESB,BPM,Portal等]基础架构图解
  8. Turtle库(海龟)
  9. SET化消息中间件架构实现
  10. 在SQL Server中添加供应用程序使用的帐号
  11. 《自动化技术中的进给电气传动》1.1节和1.2节读书笔记
  12. mac chrome 重启电脑 插件消失
  13. VUE 批量导出、导入Excel
  14. 从Unity商店下载的插件存放的位置
  15. 【EDUcoder实训作业题解】结构体
  16. “1只老母鸡”估值180亿!老乡鸡发展20年,都做对了什么?
  17. Linux valgrind java_linux下利用valgrind工具进行内存泄露检测和性能分析
  18. ROS2利用cartographer算法进行激光建图
  19. 计算机基础题精选(一)
  20. 2022社区交友系统源码+支持在线聊天/直播+有搭建教程

热门文章

  1. 产品管理包括什么和什么_什么是产品管理?
  2. 三态门及数据缓冲器 双向口的用法
  3. 无极电影的php,php无极
  4. GateWay网关访问服务出现503的问题解决
  5. 常见的一些 HTTP状态码 404 502 503
  6. 新一届CMO获奖名单公布:人大附中、上海中学霸榜,深圳中学选手夺魁
  7. 项目中站立会议和故事墙的那些事儿—敏捷开发
  8. Android ART dex2oat 加载加速浅析
  9. 微软官方操作系统(需空U盘)
  10. rewrite break