查看: 6524|回复: 79

[经验] 开贴讲讲NRF24L01P,让你彻底搞懂它的工作原理,持续更...

[复制链接]

该用户从未签到

发表于 2019-5-7 17:16 | 显示全部楼层 |阅读模式
本帖最后由 alicedodo 于 2019-5-23 09:50 编辑

*****************************************                                            
更贴码字很多,很容易触发论坛人工审核机制(我今天的更贴无一例外啊),导致最新内容一直刷新不出来。
今天赶上有些时间,所以多更了两次,人工审核太慢了,跟不上更贴的节奏了。
无奈在码云上专门开了一个项目,当帖子写。
TIM截图20190508190118.png
大家想尽早看最新内容的话,可以点开我个人主页找到项目地址,上图中的这个项目,查看wiki文档。
哥们儿说话算话,既然说了不弃坑,那论坛这边会一直更新,如果提问题尽量在论坛这边提.


*****************************************

【1】为什么使用2.4GHz频段https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=466799

【2】聊一聊nrf2401的功率
https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=466801

【3】nrf2401数据传输原理第1讲:FSK原理
https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=466802

【4】nrf2401数据传输原理第2讲:半双工通信
https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=467621

【5】nrf2401数据传输原理第3讲:地址和数据通道
https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=469710

【6】nrf2401数据传输原理第4讲(小结):数据包帧格式
https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&pid=471576

【7】待添加
送福利: https://gitee.com/alicedodo/xaobao_cheap_bus_servo_hack_record

*****************************************



开场白:
在讨论区里已经不止一次看到有同学求助有关使用nrf24l01+通信的问题,也看到不少高手发过相关库的使用教程或demo。
但事实证明效果不怎么好,还是时不时有人发帖问这个问题,甚至直接照抄高手的代码也通不了。
即使抄代码搞通了,但按自己的需求稍微修改代码之后又不通了,有的同学甚至都怀疑自己的硬件有问题。

这个无线模块真的这么难用么?并不是。
一切问题的根本原因在于你没真正的搞懂这个模块,没彻底明白它的工作原理。遇到问题的,有仔细阅读过官方的datasheet么?

开这个帖子的目的,就是想彻底终结有关nrf24l01+各种【入门问题】,我会用通俗易懂的方式将这个芯片的工作原理表达出来。
只要你有基本的电磁学常识,对arduino已经入门,认真看帖,我保证你也能彻底搞懂这个【难用】的无线模块。

帖子应该会比较长,我业余时间有限,所以会循序渐进,分期更新,保证不弃坑。
https://gitee.com/alicedodo/arduino-nrf2401-bootloader
这是我在码云上开源的arduino无线下载bootloader,使用nrf24l01+作为无线模块,希望它可以让大家对这个帖子的质量保持期待。


开场白结束,下面加几个声明:
1. 帖子里不会就某个具体的nrf24的库进行讲解或展示demo,至少在模块工作原理彻底写完之前不会,因为这不重要,如果你搞明白了原理,还怕不会使用封装接口库么?
2. 大家在帖子里不要问"两个模块一对一传输某某格式的数据,代码该怎么写"之类的问题,如果你对工作原理不理解,我说了你也只是一知半解,当然我更没时间给每个类似问题写代码了。
3. 抛开具体代码,讨论基本工作原理的问题可以随便问,知道的我会回答,不知道的我会明确告知,不会乱说。
4. 新来的同学有问题先翻翻帖子,看看之前有没有已经被解答的类似问题,尽量不要伸手就要。解决问题时保持一定的独立性,这是提高自己的好习惯。












码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

1人打赏

该用户从未签到

 楼主| 发表于 2019-5-20 13:53 | 显示全部楼层
a727409529 发表于 2019-5-20 11:41
楼主,非常感谢您的讲解,受益匪浅,最近在用这个东西。我想问几个问题
1.这个编码标准是什么呢?
2.可否讲 ...

1. "这个编码标准是什么呢?"
这句话我没理解是什么意思,"编码"是说的什么编码?

2. 我计划在写完了双向通信原理之后会开始写SPI时序的部分,这里只是简单回答一下吧
   既然你关心的是寄存器的配置,那就只说一下写寄存器的过程:
写寄存器既是通过SPI给nrf2401发送一条命令(格式:命令字节+N个数据字节)
   (1)CSN拉低 (两个作用,即是使能nrf2401的SPI接口,也是让nrf2401知道接下来要开始接收一条命令)
   (2)MOSI输出命令字节,高bit先出,写寄存器命令字节是一个拼接出来的值: 0x20+目标寄存器地址(5bit)
   (3)MOSI依次输出数据字节(即你想给对应寄存器配置的值),多字节时低字节先出,字节内部高bit先出
   (4)CSN拉高,即表示关闭nrf2401的SPI接口,也让nrf2401知道命令结束
注意,写寄存器只能在nrf2401处于PowerDown/Standby-I/Standby-II 这3种工作状态下才有效
如果你还想了解更多又等不及帖子更新的话,可以去找一份官方NRF24L01+的datasheet,看第8章(不长,就五六页吧)

3. 实际操作例程的话,我计划在写完工作原理之后会挑一个库分期写几个demo
   比如第一节只讲如何正确写寄存器,然后再读出来验证我们写入的结果
  第二节在进一步讲如何写入payload,然后触发一下MAX-RT中断
  等等
码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

2人打赏

该用户从未签到

 楼主| 发表于 2019-5-8 15:00 | 显示全部楼层
lonelyman 发表于 2019-5-8 14:06
持续关注ing,支持楼主

谢谢关注!
第一次在论坛开贴,不懂规矩,更贴有些费劲。
经常码了一段字,也不知道是哪个词有问题,提交时就会提示触发论坛审核,需要转入人工审核。
问过版主,人工审核一天之内会放行,有些慢(中午更的一段这会儿还没刷出来呢)
影响更贴兴致啊
码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

该用户从未签到

 楼主| 发表于 2019-5-7 17:16 | 显示全部楼层
本帖最后由 alicedodo 于 2019-5-8 13:10 编辑

接着上文继续说说功率。
十万块对王思聪来说是毛毛雨,但对我等DS来说就是巨款了。同理,nrf2401号称是超低功率,发射信号时最大电流也就十几毫安,貌似是很小,但那要看使用条件。
如果你的arduino通过充电器接在了电网上,有海一样的能源供应,那无线模块这点儿消耗绝对是小意思,但是如果你只有两节南孚电池,那这十几毫安的消耗就很可观了,几天就给你搞没电了。而同时呢,我们并不是时时刻刻都有数据要传送,为了省电,多数情况下可以让模块关机嘛,等有数据要发的时候再开机就好了。英雄所见略同,nrf2401的设计者和我们想到一块儿去了,他们给nrf2401设计了一个掉电模式(专业词 PowerDown mode),这个模式下nrf2401消耗多少电流呢? 900nA,整整比火力全开的状态低4个数量级,勤俭节约的典范啊。


可是理想很丰满,现实很骨感,nrf2401在掉电模式为什么这么省电?因为它把包括射频电路在内的绝大部分子模块都关闭了,只有SPI接口的相关电路还能工作(这个不难理解,SPI部分要是关闭了,我们就没办法操作它了)。如果我们要让它从掉电模式进入火力全开模式,nrf2401有很多工作要做,依次开启各个关闭的模块,等待进入稳定状态,这个过程比较耽误时间,大约几个毫秒,当我们对数据传输有较高实时性要求时,这个过程明显太慢了。
于是贴心的设计者又帮我们想到了好办法:在掉电模式和火力全开之间再增加【热待机模式】(Standby)(其实有两种待机模式 Standby-I和 Standby-II,此等细节我们后面再详细讨论),这个模式下只有射频模块的电路是关闭了,其他部分保持激活状态,一旦我们要发送数据,nrf2401只需要很短的准备时间就可以火力全开。但这样做也不是没代价的,由于更多的模块处于激活状态,热待机模式的耗电量和掉电模式相比显著增加,大约在30-300uA这个范围,但是也算很省电了。


除此之外,本着好人做到底的原则,nrf2401设计者在火力全开模式下也为我们增加了功耗控制的手段。在这个模式下射频部分的功耗占整个芯片功耗的绝对大头,自然要拿它开刀了,射频部分的功耗被划分为4档次,由低到高代号分别为0/1/2/3,一般射频功率用dBm这个单位来表示,0/1/2/3分别对应-18/-12/-6/0dBm(是不是有点儿眼熟?大家在使用模块是配置发射功率其实就是这么回事儿),自然功率越好耗电越少啦,对应的,其他方面同等条件下,功率越小传输距离越小,大家在实际应用的时候可以根据自己的情况自行选择使用什么功率配置。


提醒一句,nrf2401模块不管是对外发送数据(TX mode)还是接收数据(RX mode)都是要大幅耗电的,但上一段提到的射频功率控制只能控制对外发送数据,接收数据的功率是没办法控制的,这个一定要记住。
码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

该用户从未签到

 楼主| 发表于 2019-5-7 17:16 | 显示全部楼层
本帖最后由 alicedodo 于 2019-5-7 19:49 编辑

同样是无线模块,从技术实现上说,蓝牙模块要比nrf2401复杂的多得多,但为什么蓝牙模块用起来这么简单?
原因很简单,蓝牙协议是国际标准,数不清的公司为其添砖加瓦,趟平任何技术难题,将复杂的协议包了一层又一层,最后提供了一个非常傻瓜化的使用接口,简单到当串口用就可以了。
而nrf2401只是Nordic这个公司自己的产品,不是通用标准,虽然简单许多,但我们普通使用者需要直接面对模块,最多只有Mirf这样的简单封装库可以使用,而且这些库也只是让我们操作模块的时候少撸几行代码,里面并没有封装什么通用型的通信协议,所以本质上还是在直接操作nrf2401模块,如果你对这个模块不熟悉,自然也就对封装库提供的接口一知半解,似是而非。


好了,闲言少叙,开始正题:
道生一 一生二 三生万物
nrf2401是一个无线模块,通过电磁波传输数据。
不要认为这是一句废话。这是这个帖子后续所有内容的起点,或者说所有的讨论都是对这句话的丰富和细化。慢慢往后看你会明白的。


既然是无线传输,那肯定要占用电磁波频段了。对模块稍微有了解的都知道,这个模块使用的是2.4GHz附近的频率,可是为什么偏偏要用这个波段?
答案是: 这是一个技术问题,更是一个法律问题.
距离相近的两个电台不能使用同一波段,因为会相互干扰,结果就是谁也没法正常通信,所以你占了这个波段我就不能用了,因此电磁波频段是稀缺资源。这种好东西肯定要归国家所有啊,于是全世界所有国家无一例外都纷纷立法,非政府批准,不得随意占用无线电频段。
但总归该留点儿汤吧,于是2.4G附近的频段就成了民间自由使用的极少数频段资源之一了,这也是为什么WiFi/ZigBee/蓝牙/nrf2401都使用这个频段的重要原因。
由此可以推导出第一个问题:
为什么nrf2401有时候会莫名其妙的出现很高的丢包率、时好时坏?
答案是很可能是受WiFi的干扰,2.4G WiFi的频段和nrf2401有很大一块频带是重叠的,如果你家有wifi信号,那很容易会受干扰而导致丢包严重,将nrf2401的频段设置为高于2490MHz可以显著降低丢包率。


接着再引出第二个问题:为什么这个无线模块有效通信距离这么近?
TB上最便宜、最常见的nrf2401模块,上面只有一个nrf2401芯片而且天线还是附着在PCB上的铜线的那种。
空旷无遮挡的地方大约也就100米左右,即使是那种加了功率放大芯片的模块,有效距离也就一两千米。为啥会这么短、而且穿墙能力这么弱?
有两方面原因:(1)2.4G高频电磁波的物理特性导致(2)发射功率太小,这是主要原因
先说(1),电磁波频率越高越容易被物体遮挡,复杂地形位置传输距离越短
再说(2),任何向周围空间均匀传播的能量形式,能量密度都会随着距离的增加而显著的衰减,典型的如声波,好比两个人隔空讲话,对方嗓门不变时,你离得越远听得越不清楚,远到一定程度就什么也听不见了。电磁波也不例外,频率不变的前提下,想要增大传输距离,只能增大发射功率。而nrf2401的功率发射信号时,最大电流也不过11毫安左右,换算成功率也就十几毫瓦,自然传不远,即使那种加了功率增强芯片的模块,发射电流也就一百几十毫安。

码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

1人打赏

该用户从未签到

 楼主| 发表于 2019-5-7 17:16 | 显示全部楼层
本帖最后由 alicedodo 于 2019-5-8 19:35 编辑



功率的事儿聊完了,转过头来说说频率,nrf2401是怎样使用电磁波来传输数据的呢?


我们的数据其实就是一长串0和1的组合,无线传输就是想办法将0/1信号通过电磁波发送出去,专业的词汇叫信号调制,怎么做呢?
nrf2401使用的技术叫FSK(Frequency Shift Keying 直译过来叫频移键控,我认为翻译成键控频移更合适)。
说人话就是:以某个固定频率为基准(也叫载波),通过改变电磁波的频率来传递0或1,即在载波频率的基础上,发0时让频率高一点,发1时让频率低一点,接收端通过持续监测这种频率变化,从而识别出0或1,接收端的这个识别过程叫检波。
从度娘那里搞来一张图:
FSK调制原理简图.png
上面这张图就是FSK的基本原理简图,不过大家不要被这张图的某个细节所误导,即传递1的时候并不是一个正弦波就完事儿了,同样0也不是两三个正弦波就完事了,要准确地传递一个bit,对应的频率信号必须要稳定地持续一段时间,这样接收端才能准确的判断出这是一个有效的bit。


我们假设这个时间是T,(1/T)是啥呢?波特率!是不是很眼熟啊.


其实对于nrf2401来说,上文中的波特率准确的名字应该叫空中波特率(air-data-rate),就FSK的原理上来说,波特率可以是任意值,但nrf2401做了大幅简化,只允许使用3种固定的波特率,分别是 250Kbps/1Mbps/2Mbps,nrf2401允许我们在使用时给它指定一个波特率,3选1。需要注意的是,当nrf2401正处于接收数据或发送数据的工作状态时,不要修改波特率,你修改了,就破坏了当前这份数据的接收/发送规律,必然导致通信失败。


科普完了FSK的原理,有些问题自然而然就明了了:
(1)记得刚才说的"载波频率"吧,nrf2401把它叫做啥呢?"RF Channel frequency"!在nrf2401这里,载波频率是可调的,通过修改nrf2401内部相关寄存器的配置进行调节,既然是由寄存器来决定载波频率,那频率取值肯定是不连续了,以2400MHz为起始值,每隔1MHz取一个频率点,最大一直到2525MHz(设定频率的时候记得避开WiFi干扰),一共126个取值,nrf2401把这些值叫做 RF Channel。 和波特率一样的问题,收发数据的时候不要修改。


(2)由FSK的原理可知,两个模块一收一发,想要正常通信,双方必须使用同样的载波频率,也就是两边RF Channel的值必须相同


(3)由FSK的原理可知,当nrf2401在某载波频率上发送数据时,会占用一个窄窄的、以载波频率为为中心左右延伸的频带。承载bit信息的频率离载波频率越远,接收端越容易识别出这个bit,但坏处是会占用更宽的频带(这个道理应该不难理解吧?)。前面说了,RF Channel的频率间隔是1MHz,如果频带宽度超过了1MHz,那么相邻的两个RF Channel在频带上就会重叠,会相互干扰,这俩Channel就一起废了。


当nrf2401的波特率是250Kbps或1Mbps时,可以做到频带宽度小于1MHz,这样就能保证126个RF Channel互不影响,也就是说,我们共有126个Channel可用,很完美。
但是当波特率是2Mbps的时候,情况出现了变化,频带宽度小于1MHz搞不定,只能做到让频带宽度小于2MHz,也就是说我们只有一半的Channel可以用了。


这是啥原理呢?
还记得前面说的那个时间T么?2Mbps时这个T只有500纳秒,即接收端在接收数据时只有500纳秒的时间来识别每个bit,如果承载bit信息的频率离载波频率太近,就无法保证可靠的识别,那只有加宽频带才能解决这个问题了。
以频带换时间。
码字不易,如果觉得学到了真家伙,请我喝碗咸豆花
  • TA的每日心情
    奋斗
    2018-3-11 22:42
  • 签到天数: 12 天

    [LV.3]偶尔看看II

    发表于 2019-5-8 14:06 | 显示全部楼层
    持续关注ing,支持楼主

    该用户从未签到

    发表于 2019-5-10 08:44 | 显示全部楼层
    很棒,最近接触到了这个模块,不懂原理真的是一头雾水。谢谢!

    该用户从未签到

     楼主| 发表于 2019-5-10 13:25 | 显示全部楼层
    本帖最后由 alicedodo 于 2019-5-10 14:21 编辑

    【4.nrf2401数据传输原理第二讲】
    之前的讨论中,我们已经了解了nrf2401传输bit信息的原理,这一节再延伸一下。
    根据FSK的实现原理可以很明显的看出,这是串行传输模式。和串口传输几乎是一样的,唯一不同的是串口有TX RX两根线,通信两端可以同时接收/发送,互不影响。而反观nrf2401,它内部只有一个射频模块,任意时刻,射频模块只能在【关机/发射信号/接收信号】这3种工作状态中3选1,也就是nrf2401要么只能对外发送数据,要么只能接收数据。


    来点儿专业词汇:
    两个通信节点,数据只能从本端传输到对端而不能反着来,这叫单工通信;
    本端可以发数据给对端,对端也可以发数据给本端,这叫双工通信;
    本端随时可以发数据给对端,对端也可以随时发数据给本端,互不影响,这叫全双工通信;
    虽然两端可以互传数据,但我发的时候你只能收不能发,同样你发的时候我也只能收不能发,这叫半双工通信。
    综上可知,串口属于全双工通信,nrf2401属于半双工通信。


    当我们使用nrf2401进行双向通信的时候,根据项目的不同应该会遇到各种各样的通信场景,我们讨论一下最复杂的情况:
    两个无线节点互相通信,某一时刻,两边都有大量的数据想要尽快传送给对方。半双工的特性决定了肯定无法同时互相传输,应该怎么制定传输方案呢?
    最简单的方法,我先发你收着,等我这边的数据发完了你再给我发。
    这个方法原理上可行,但不合适:
    1. 实时性差。 波特率不变时,数据量越大,传输耗时越长,我这边发给你的数据越多,开始收取你那边数据的时间就越靠后。
    2. 不可靠。相比有线传输,无线传输从原理上就天然的不可靠,很容易受周围空间中其他电磁波的干扰。
    巴拉巴拉传了一长串,万一中间某个地方干扰了一下,哪怕只导致一个bit解析出错,那对方收到的整份数据就是错误的。


    现在换一种方法:
    (1)我们双方约定好,公平使用传输通道,我让让你,你可以先发数据。但有个条件,不管你有多少数据要发给我,发数据的时候,每次发的字节数量不能超过某个固定长度,我们这里假设是32字节。发少了可以,发多了不行。
    (2)你那边发完了这32字节数据之后,要立即转入接收状态。
    此外,我对你还有个要求,一旦你进入了接收状态,不要一直死等,如果过了一段时间你没收到我发给你的数据,请切换到发送状态,把刚才发我的那段数据再发一遍。
    (3)我收到你的数据之后,如果检查没错误,我会立即转入发送状态,把我这边的数据发给你,同样我也会遵守单次发送最大长度32字节的约定。
    (4)如果我收到数据后检查发现有错误,那不好意思,就算我有数据要发给你,但因为你给我的数据是错误的,所以我不搭理你,等着你再给我发一遍。
    (5)还有一种特殊情况:经检查你发的数据没问题,但我没什么数据要发给你,这时候,为了不让你在接收状态死等下去,我会简单发你一个"恩,收到了"之类的无意义回复。
    (6)给你发完回复之后,我不关心你有没有收到,我会接着退出发送状态,进入接收状态继续等待。
    (7)你在接收状态收到了我发给你的数据,知道了"我已收到你的数据",然后你就可以再次转入发送状态,将第二段数据发给我,继续重复前面的过程。
    (8)如果你在接收状态下一直没收到我的回复,导致等待超时了,那说明刚才的交流某个环节出了问题。也许是我根本没收到你的数据,也许你的数据被我检查出错误来了,也许是我发你的回复你没收到。所以,你需要重新发送一次刚才发过的数据。
    (9)某些极端情况下,你可能一遍遍的重发同样的数据,我一直没搭理你。然后,你怒了,能咋办?回家告状去呗!


    以上的描述就是nrf2401实现可靠双向通信的基本过程。
    可以看出,上文中的"你"主动性更大,每次通信的时候,都是由"你"发起的,"我"只是被动的接收,
    然后"我"通过"回复(ACK)"的方式变相的把"我"这边的数据回传给"你".
    通信过程的异常控制也是有"你"这一端来掌控的,包括 超时控制 / 重发控制 / 重发失败足够次数之后终止通信并报错。

    nrf2401把行为如"你"的这一端叫做"主发送端"(Primary Transmitter,简称PTX),
    把行为如"我"的这一端叫做"主接收端"(Primary Receiver,简称PRX),
    以后讨论时我们只使用 PTX / PRX 这两个简写,大家记一下。


    还有一点需要特别强调:
    PTX虽然叫PTX,但PTX可以进入"发送模式"发送数据,也可以进入"接收模式"接收数据;
    PRX同样既可以进入"发送模式"发送数据, 也可以进入"接收模式"接收数据;
    PTX/PRX指的是控制逻辑;"发送/接收模式"指的是射频部分的工作状态,切记两者不要混淆。

    我们计算一下,单次发送32字节数据,需要多长时间:
    2Mbps  波特率: 32*8/2000000 = 128  微秒
    1Mbps  波特率: 32*8/1000000 = 256  微秒
    250Kbps波特率:  32*8/250000  = 1024 微秒 1毫秒多一点点
    可以看出这个时间是很短的,在此基础上,把时间轴拉长,从宏观上看,可以近似看做两端是在同时、双向通信。
    这种方案本质上是将时间划分为多个很小的片段,随着时间片的向前推进,通信双方交替使用唯一的信号通道向对端发送数据。
    专业的词汇叫: 时分复用(Time Division Multiplexing,TDM)

    【关于上面那一长段你我交互的过程,大家仔细看看,确保弄清各个环节,对于后面理解更细致的通信过程有很大帮助。】



    码字不易,如果觉得学到了真家伙,请我喝碗咸豆花

    该用户从未签到

     楼主| 发表于 2019-5-16 14:41 | 显示全部楼层
    【5.nrf2401数据传输原理第三讲】
    【这两天比较忙,今天终于抽出了一点时间,抓紧更一段】
    由无线通信的基本原理可知,当nrf2401发送数据给对端模块的时候要发射电磁波,这本质上是一个像四周空间广播的过程。
    既然是广播,只要是有效距离范围内的任意一个处于接收状态的nrf2401模块,都能收到这个信号,那我咋知道我收到的这波数据是不是给我的?


    于是"地址"这个概念就出现了:
    PTX是主发送端,通信过程由PTX主动发起,发送数据的时候,PTX将表示某个地址的数据附带在要发送的这段数据上,而同时,所有的主接收端即PRX,都在其内部预先存好了一个唯一的地址。这个地址的长度是3到5字节,具体长度是可以通过我们的程序来配置的,3/4/5字节3选1。


    PTX发送数据的时候会先将目标地址数据发出去,然后再发送实际的数据;
    当PRX识别出有效信号时,会首先从这一长串0101中找出表示地址的那段数据,然后将这个地址和自己设定的地址进行比较,如果相符,则认为数据是发给自己的,继续接收数据,如果不相符,则数据不是发给自己的,直接丢掉,继续等待下一波数据。


    目标PRX收到数据只是第一步,如果PRX有数据要回传给PTX,那么它会按照同样的方式,将自己的地址(注意是PRX端的地址,不要搞错)附带在数据前面一并发送出去。由于PTX本来就知道这个地址,所以PTX端遵照同样的接收规则接收回应数据,至此就是一个完整的通信过程。即使PRX没有实际数据要发送给PTX,按照约定规则,它也会回复一份不带有效数据的回应给PTX端,这份回应同样附带地址。


    不管是作为PTX还是PRX,我们的程序可以通过nrf2401的SPI接口,按照nrf2401规定的方式,随意修改这个"地址"。但关于地址有几个非常重要的细节要说明:


    nrf2401作为PRX的时候,内部【最多】可以同时存在6个接收地址,可以通过配置【分别启用】或【分别禁用】一个或多个接收地址。如果启用了多个地址,那么PRX接收数据信号的时候,数据中的目标地址会同时和这些地址依次比较,只要有一个地址匹配上了,那么PRX就认为这份数据是给自己的。哪个地址匹配上了,PRX回复时就把这个地址附带到回应数据上。


    nrf2401把这6个接收地址相关的东西叫做数据通道(data pipe),也就是大家在使用库的时候必定要接触的pipe,编号是pipe0~pipe5,故而这个地址也叫pipe address.


    前面说过,pipe地址长度可以随意配置成3/4/5字节,但这6个pipe只能共用一种长度配置,不能分别使用不同的地址长度;
    pipe0 地址最长可5字节,地址值随意配置,当取3/4字节地址长度时,5字节中使用最低的那3/4字节,高处字节忽略;
    pipe1 特点同pipe0;
    pipe2~pipe5 地址最长可5字节,但地址值仅有最低字节可以随意配置,剩余的高位字节只能共用/跟随pipe1中配置的值。


    PRX虽然有多个数据通道,但需要注意的是,nrf2401只有一个射频模块,任意时候只能接收一份数据。
    如果你在多对一通信时使用【多PTX<-->单PRX的多pipe】方案,需要注意错开各自发送时间。
    如果同一时刻两个PTX同时向一个PRX发送数据,即使地址不同,两个信号也会相互干扰,导致PRX谁的信号也解不出来。


    再来说说PTX端,前面说过,PTX接收回应数据时也要检测地址,PTX使用数据通道pipe0来接收数据(定死的,不能改),所以我们必须【启用】pipe0通道,并为其【配置好地址和地址宽度】,再强调一下,这个地址严格讲不是PTX的地址,而是目标PRX的地址!实际上PTX是没有自己的地址的。


    别忘了PTX刚开始发送数据的时候也需要一个地址,按照常理说,pipe0的地址都配置好了,PTX发送数据时就应该知道要发到哪个地址上,但并不是这样:
    不知处于什么设计方面的考虑,nrf2401发送数据前必须要给它单独配置一个发送地址(TX_ADDR),也就是说,想要让PTX正确的发送和接收数据,必须将目标地址配置给PTX配置两次(即将一个地址分别写到两个不同的地方),一次是给pipe0的,一次是给TX_ADDR的,这两个地方的值必须一样。


    配置地址宽度对PTX来说也是通用的,即对pipe0和TX_ADDR同时有效。


    先写这些,字数不多但是里面的细节很多,且都是对写程序非常重要的细节,大家仔细看看。

    码字不易,如果觉得学到了真家伙,请我喝碗咸豆花
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    SpiderRobot 蜘蛛
    SpiderRobot 蜘蛛
    关于SpiderRobot 项目实行方案 之前有人推荐我做这个项目,于是乎就有了这个 h
    Arduino MEGA 与UNO 通过nRF24L模块通讯
    Arduino MEGA 与UNO 通过n
    之前在深水宝很“实惠”的店铺买了一些原件,随手砍了esp8266以及nRF24L*3 因为缺
    求助!GM65二维码扫描模块怎么用?
    求助!GM65二维码扫描模块
    求助!GM65二维码扫描模块怎么用? 卖家给的资料真的看不懂该怎么弄。。( ̄▽ ̄)~*
    KPM大比拼
    KPM大比拼
    前言:没别的就是比手快! 方案描述: 做这个的初衷其实是受到一些网红玩具的启发—
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表