arduino笔记33:nRF24l01模块使用 FSK 波特率 通信方式 PTX PRX

article/2025/9/13 12:03:30

最近再arduino中文社区看到了一篇介绍nrf24l01基本原理的帖子,内容感觉蛮不错的,学习一下,记录一下学习笔记。

大部分内容都是Arduino中文社区的帖子,附上自己的一点点体会。

目录

一、数据传输

FSK(Frequency Shift Keying)

波特率

可用频道

二、传输机制


 

 

 

一、数据传输

 

FSK(Frequency Shift Keying)


我们的数据其实就是一长串0和1的组合,无线传输就是想办法将0/1信号通过电磁波发送出去,专业的词汇叫信号调制,怎么做呢?
nrf2401使用的技术叫FSK(Frequency Shift Keying 直译过来叫频移键控,我认为翻译成键控频移更合适)。
说人话就是:以某个固定频率为基准(也叫载波),通过改变电磁波的频率来传递0或1,即在载波频率的基础上,发0时让频率高一点,发1时让频率低一点,接收端通过持续监测这种频率变化,从而识别出0或1,接收端的这个识别过程叫检波
从度娘那里搞来一张图:

 

上面这张图就是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信息的频率离载波频率太近,就无法保证可靠的识别,那只有加宽频带才能解决这个问题了。
以频带换时间。

 

二、传输机制


根据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)

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

 

 

 

 

 

来源:

https://www.arduino.cn/forum.php?mod=viewthread&tid=86275&extra=&authorid=175094&page=1

 


http://chatgpt.dhexx.cn/article/bnJPfNZJ.shtml

相关文章

Internal: Invoking ptxas not supported on WindowsRelying on driver to perform ptx compilation.

原环境:Windows 10, gpu 3090, TF 1.15,cuda_10.0.130_411.31_win10,cuDNN 7.6.5.32 mask-rcnn框架,运行train.py报错信息如下: image_id 333 image_id 32 image_id 58 2022-01-01 19:03:07.415032: I tensorflow/str…

Matlab里.cu函数转ptx文件常见错误

错误类型: nvcc fatal : Cannot find compiler ‘cl.exe’ in PATHwarning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 ;fatal error C1083: 无法打开包括文件: “mat.h”: No such file or di…

vs cuda c/c++ 生成ptx配置

在编译cu文件生成ptx文件 一:生成依赖项目 二:配置.cu属性,项目类型改为CUDA C/C 三:配置CUDA C/C属性 compiler output:输出的文件名; additional include directories: 包含库; nvcc compi…

the provided ptx was compiled with an unsupported toolchain

本人遇到这个问题的原因是,一个动态库在一个cuda驱动比较新的服务器上编译的,然后使用这个动态库,在cuda较老的驱动上运行 编译机器cuda版本信息 运行机器cuda版本信息

VS查看PTX代码

首先,声明本人用的是Windows 7操作系统,使用Windows 8操作系统的小伙伴们会启动不了Nsight monitor,原因在于Windows 8操作系统的Framework版本过新,解决办法可以是:安装一个版本旧一点的Matlab,安装起初会…

Nvidia Tensor Core-MMA PTX编程入门

目录 1 PTX (Parallel Thread Execution) 2 MMA (Matrix Multiply Accumulate) PTX 3 LDMATRIX PTX 4 示例 5 底层代码 6 其他 6.1 HGEMM优化 1 PTX (Parallel Thread Execution) PTX是什么,Nvidia官方描述为a low-level parallel thread execution virtual…

PTX ISA 7.4 参考手册翻译

文章目录 PTX Parallel Thread Execution ISA 7.4SynataxSource FormatCommentsStatementsinstruction identifiersInteger ConstantFloat-Point ConstantConstant expression整型常量表达式求值 State Spaces, Types, and Variables状态空间Kernel Function ParametersKernel …

CUDA PTX ISA阅读笔记(一)

不知道这是个啥的看这里:Parallel Thread Execution ISA Version 5.0. 简要来说,PTX就是.cu代码编译出来的一种东西,然后再由PTX编译生成执行代码。如果不想看网页版,cuda的安装目录下的doc文件夹里有pdf版本,看起来也…

CUDA进阶第二篇:巧用PTX

写在前面 并行线程执行(Parallel Thread eXecution,PTX)代码是编译后的GPU代码的一种中间形式,它可以再次编译为原生的GPU微码。CUDA 手册传送门:Parallel Thread Execution ISA Version 4.3 利用PTX来进行试验&…

一文了解GPU并行计算CUDA

了解GPU并行计算CUDA 一、CUDA和GPU简介二、GPU工作原理与结构2.1、基础GPU架构2.2、GPU编程模型2.3、软件和硬件的对应关系 三、GPU应用领域四、GPUCPU异构计算五、MPI与CUDA的区别 一、CUDA和GPU简介 CUDA(Compute Unified Device Architecture)&…

MPI 并行

MPI from b站视频 超算小白-灵犀学院 click (一)基本框架 头文件 mpi.h #include "mpi.h"初始化函数:MPI_Init( ) MPI_Init(int *argc, char ***argv)完成MPI程序初始化工作,通过获取main函数的参数,让…

C# 并行编程

一 并行任务库TPL 1 并行任务库(TPL,Task Parallel Library) 2 最重要的是Task类,还有Parallel类 3 Task类,是利用线程池来进行任务的执行 比如直接用ThreadPool更优化,而且编程更方便 4 Paallel类&…

并行处理及分布式系统

并行处理及分布式系统 1 为什么要并行计算 1.1 为什么需要不断提升性能 随着计算能力的增加,我们所面临的计算问题和需求也在增加随着技术的进步,我们从未想过的技术得到了解决,比如:人类基因解码、更准确的医疗成像、更快速准…

并行计算之MPI(一)

MPI学习 1. 了解并行计算 为什么要采用并行计算? (1)这是因为它可以加快速度即在更短的时间内解决相同的问题或在相同的时间内解决更多更复杂的问题特别是对一些新出现的巨大挑战问题; (2)节省投入并行计…

并行网关

1、并行网关 假设现在我们想在旁边放一份沙拉。无论如何,如果你想要沙拉,你可以像我们在图1.1中所做的那样建模。 图1.1:准备沙拉和主菜。 在这里,我们介绍了另一个符号:(文本)注释;这是一个您可以与任何流对象(在本…

并行计算:循环程序并行化的一般方法

一、数据划分和处理器指派 1. 带状划分方法 又叫做行列划分,就是将矩阵的整行或整列分成若干组,各组指派给一个处理器。 例如:设矩阵A由n行和m列,对其串行处理的程序段如下: for i1 to n dofor j1 to m doProcess(a[…

并行计算之MPI(三)

了解MPI 什么是MPI (1)MPI是一个库而不是一门语言,许多人认为MPI就是一种并行语言,这是不准确的。但是按照并行语言的分类可以把FORTRANMPI或CMPI。看作是一种在原来串行语言基础之上扩展后得到的并行语言,MPI库可以被…

并行计算的一些思考与总结

弗林分类法 根据弗林分类法,计算机结构主要分为 SIMD----单指令、多数据MIMD---多指令、多数据SISD----单指令、单数据MISD---多指令、单数据 一般的串行程序中为SISD,即在单核CPU下任何时间和地点只有一个指令处理一个数据,其所谓的多线程…

并行计算之MPI(二)

1.并行编程模型 目前两种最重要的并行编程模型是数据并行和消息传递数据并行编程模型的编程级别比较高编程相对简单但它仅适用于数据并行问题消息传递编程模型的编程级别相对较低但消息传递编程模型可以有更广泛的应用范围。 数据并行即将相同的操作同时作用于不同的数据因此…

Matlab 并行

Matlab 并行 1. 检查是否有并行附加功能2. 创建和删除并行2.1 创建默认的并行池2.2 在本地创建2.3 在集群创建2.4 删除 3. Parallel pool 包含的一些函数3.1 parfor3.2 parfeval 初学,肯定有理解不够的地方。看官方文件更靠谱。 1. 检查是否有并行附加功能 如果没有…