3、LoRa数据包结构详解:前导码、同步字、报头、净荷、CRC校验
各位同学,咱们今天来聊聊LoRa数据包的结构。说实话,很多做LoRa开发的朋友,上来就调库、发数据,但数据包在空中的样子,可能从来没仔细看过。我个人觉得,搞通信的人,一定要把数据包的每一段都吃透,不然出了问题你都不知道从哪查起。
LoRa的数据包结构,说白了就是五段:前导码、同步字、报头、净荷、CRC校验。咱们一段一段拆开讲。
3.1 前导码(Preamble)—— 唤醒接收机的敲门砖
前导码是数据包的第一段。它的作用是什么?很简单,就是告诉接收机:“嘿,注意了,我要发数据了!”
接收机平时处于低功耗的监听模式,它需要检测到前导码才能知道有数据来了。前导码是一串固定的、已知的码片序列。接收机通过检测这个序列,来同步时钟和频率偏移。
前导码的长度可以配置,默认是12个符号长度。但我在项目中遇到过一个问题:如果前导码太短,接收机可能来不及同步,导致丢包;如果太长,又会增加功耗和占用信道时间。
前导码的格式其实很简单,就是连续的“1”和“0”交替的码片。接收机通过检测这个模式,就能锁定信号的起始位置。
3.2 同步字(Sync Word)—— 区分不同网络的身份证
前导码之后,紧跟着的就是同步字。同步字的作用是区分不同的LoRa网络。说白了,就是告诉接收机:“这个数据包是发给你的网络的,不是隔壁老王那个网络的。”
LoRa的同步字默认是0x12和0x34。但你可以修改它。我记得有一次做项目,两个LoRa网络在同一个区域工作,结果数据互相串扰。后来我把其中一个网络的同步字改成了0xAB和0xCD,问题就解决了。
同步字在数据包中的位置,紧接在前导码之后。它的长度是固定的,2个字节。接收机检测到同步字后,就知道这个数据包是发给自己的,然后继续解析后面的内容。
3.3 报头(Header)—— 数据包的说明书
报头是数据包的第三段。它包含了数据包的元信息,比如净荷长度、编码率、是否使用CRC等。说白了,报头就是数据包的说明书,告诉接收机怎么解析后面的数据。
LoRa有两种报头模式:显式报头和隐式报头。
- 显式报头:默认模式。报头会包含净荷长度、编码率、CRC标志等信息。接收机通过解析报头,就知道后面该收多少数据。
- 隐式报头:报头被省略了。发送端和接收端需要事先约定好净荷长度、编码率等参数。这种模式适合固定数据包长度的场景。
我个人习惯在大多数场景下使用显式报头,因为灵活。但如果你做的是传感器数据上报,每次数据长度都一样,用隐式报头可以省掉报头的开销,提高传输效率。
报头的结构是这样的:
显式报头格式:
- 净荷长度(1字节):表示后面净荷的字节数
- 编码率(1字节):表示前向纠错的编码率
- CRC标志(1位):表示是否使用CRC校验
- 保留位(7位):预留的位,通常为0
3.4 净荷(Payload)—— 真正要传的数据
净荷就是数据包的核心内容,也就是你真正想传的数据。比如传感器的温度值、开关的状态、控制指令等。
净荷的长度是有限制的。LoRa的净荷最大长度取决于扩频因子和编码率。一般来说,扩频因子越大,净荷长度越小。举个例子,SF7时净荷最大可以到255字节,但SF12时可能只有几十个字节。
我在项目中遇到过一个问题:有一次我想传一个比较大的数据包,结果发现发送失败了。后来一查,原来是净荷长度超过了当前扩频因子下的最大值。嗯,这里要注意,设计协议时一定要考虑净荷长度的限制。
净荷的格式完全由你自己定义。你可以用JSON、二进制、或者自定义的协议。我个人建议用二进制格式,因为效率高、占用空间小。比如温度值用2字节的整数表示,湿度用1字节的整数表示,这样解析起来也快。
3.5 CRC校验—— 数据完整性的守护神
CRC是数据包的最后一段。它的作用是检测数据在传输过程中是否发生了错误。说白了,就是检查数据有没有被干扰、有没有丢位。
LoRa支持两种CRC模式:净荷CRC和报头CRC。
- 净荷CRC:对净荷部分进行CRC校验。如果CRC校验失败,接收机会丢弃这个数据包。
- 报头CRC:对报头部分进行CRC校验。如果报头CRC校验失败,接收机也会丢弃数据包。
CRC的算法是标准的CRC-16,多项式是0x8005。你不需要自己实现,LoRa芯片内部已经集成了CRC计算模块。
CRC校验失败后,接收机会怎么做?它会丢弃这个数据包,然后继续监听下一个数据包。发送端如果开启了确认机制,会重传数据包。如果没有确认机制,数据就丢了。
3.6 数据包结构总结
好了,咱们把LoRa数据包的五个部分都讲完了。来,我画个表格总结一下:
| 字段 | 作用 | 长度 | 可配置 |
|---|---|---|---|
| 前导码 | 唤醒接收机,同步时钟 | 可配置(默认12符号) | 是 |
| 同步字 | 区分不同网络 | 2字节 | 是 |
| 报头 | 描述净荷的元信息 | 显式/隐式 | 是 |
| 净荷 | 真正要传输的数据 | 可变(受SF限制) | 是 |
| CRC | 检测数据完整性 | 2字节 | 是 |
你想想看,这五个部分缺一不可。前导码负责唤醒,同步字负责区分网络,报头负责描述数据,净荷负责承载内容,CRC负责保证正确性。任何一个环节出问题,数据包都可能传不过去。
我记得刚开始做LoRa开发时,总觉得这些细节不重要,能用就行。后来遇到各种奇怪的问题,才明白每一个字段都有它的设计道理。嗯,这里要提醒大家,做通信开发,一定要把数据包结构吃透,不然出了问题你都不知道从哪查起。
下一章咱们会讲如何自定义LoRa协议,包括如何设计净荷格式、如何实现确认重传机制等。到时候咱们再深入聊。