深度解析NRF24L01
本文将深度解析一款烂大街的无线芯片,NRF24L01(及国产完全兼容的SI24R1)。实在是现在网上很多写NRF24L01的文章抓不到重点,一些冷门用法没人写,就写了这个文章。推荐选用SI24R1,原因是功能完全相同,但SI24R1内置PA,最大输出是7dbm,而挪威原版的NRF24L01+最大输出只有0dbm。因为2.4G是ISM频段,功率即正义!
以下以SI24R1为例进行说明
读写控制
spi配置
遵循以下配置即可:
- CPOL 1 & CPHA 1或者CPOL 0 & CPHA 0,手册推荐使用后者,但是前者也是能用的
- SPI CLK 配置10MHZ以下即可
- SPI位宽配置为8bit
- MSB在前
读寄存器
- 手册明确说明,CS拉低后的第一个字节被认为是命令字,这样也就没办法做常CS了,也就是必须把CS接到MCU,并保证在传输命令字之前CS有一个下降沿,这样才能读写有效!
- 所有的命令字如下
按照说明进行配置就可以了
基本传输
不使用其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相关推荐
- 单文件浏览器_图文并茂深度解析浏览器渲染原理,包看懂超值得收藏
在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广 ...
- 舒工深度解析不规则场地座位二维码生成规则
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...
- 今晚8点开播 | 深度解析知识图谱发展关键阶段技术脉络
作为知识图谱领域形成过程的亲历者之一,AI科技大本营此次邀请到文因互联 CEO 鲍捷,他将对知识图谱的历史渊源进行梳理,对该领域几次发展的主要技术突破做深度解析,并分析其工业落地的几个关键点.欢迎大家 ...
- 多目标跟踪算法FairMOT深度解析
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨周威@知乎 来源丨https://zhuanlan.zhihu.com/p/259356109 ...
- 深度解析工业软件:研究框架(140页)
来源:跨越鸿沟 本文多图,建议阅读6分钟. 本文为你深度解析工业软件:研究框架 工业软件的核心,不仅是"软件",更是"工业". 有什么样的工业流程,就有什么样的 ...
- 科普|深度解析5G与未来天线技术
来源:电子万花筒 过去二十年,我们见证了移动通信从1G到4G LTE的转变.在这期间,通信的关键技术在发生变化,处理的信息量成倍增长.而天线,是实现这一跨越式提升不可或缺的组件. 按照业界的定义,天线 ...
- 深度解析:mPaaS 3.0全新组件
摘要:以"数字金融新原力(The New Force of Digital Finance)"为主题,蚂蚁金服ATEC城市峰会于2019年1月4日上海如期举办.分论坛上,蚂蚁金服产 ...
- 《嵌入式Linux与物联网软件开发——C语言内核深度解析》一第1章 C语言与内存1.1 引言...
本节书摘来自异步社区<嵌入式Linux与物联网软件开发--C语言内核深度解析>一书中的第1章,第1.1节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区"华章计算机&quo ...
- 2008年12月13日上海USB驱动开发深度解析讲座PPT
讲座PPT:宋宝华2008年12月13日上海USB驱动开发深度解析讲座PPT [url]http://www.linuxdriver.cn/200812/20081213172619_836.rar[ ...
最新文章
- 汽车车灯灯具系统(下)
- 程序员面试系列——插入排序
- HTTP状态码一览表(HTTP Status Code)
- sql server系统表详细说明(转)
- mysql 行转列分级输出_MySQL如何实现行转列分级输出?_MySQL
- 深入react技术栈(9):表单
- IBM SOA[ESB,BPM,Portal等]基础架构图解
- Turtle库(海龟)
- SET化消息中间件架构实现
- 在SQL Server中添加供应用程序使用的帐号
- 《自动化技术中的进给电气传动》1.1节和1.2节读书笔记
- mac chrome 重启电脑 插件消失
- VUE 批量导出、导入Excel
- 从Unity商店下载的插件存放的位置
- 【EDUcoder实训作业题解】结构体
- “1只老母鸡”估值180亿!老乡鸡发展20年,都做对了什么?
- Linux valgrind java_linux下利用valgrind工具进行内存泄露检测和性能分析
- ROS2利用cartographer算法进行激光建图
- 计算机基础题精选(一)
- 2022社区交友系统源码+支持在线聊天/直播+有搭建教程