3. MAVLink 数据包结构:从起始标志到校验和

各位同学,今天我们来聊聊 MAVLink 协议最核心的东西——数据包结构。

说白了,MAVLink 就是一套无人机之间、无人机与地面站之间沟通的“语言”。你得知道这句话从哪里开始、到哪里结束、是谁说的、说了什么、对不对。这些信息,就藏在数据包的每一个字节里。

我刚开始接触 MAVLink 时,总觉得协议栈很神秘。后来拆开一看,嗯,其实就 8 个字段,结构非常清晰。咱们一个一个来看。

3.1 数据包整体布局

先看一张总图,让你对 MAVLink 数据包有个整体印象。

MAVLink 1.0 数据包结构 起始标志 0xFE 有效载荷 长度 序列号 SEQ 系统ID SYS 组件ID COMP 消息ID MSG 有效载荷 Payload 校验和 CKA/B 字段说明: • 起始标志(1字节):固定值 0xFE,标识一个 MAVLink 帧的开始 • 有效载荷长度(1字节):Payload 部分的字节数,范围 0-255 • 序列号(1字节):每发送一帧自动加 1,用于检测丢包 • 系统ID(1字节):标识发送方所属的无人机系统 • 组件ID(1字节):标识系统内的具体组件(飞控、GPS、相机等) • 消息ID(1字节):标识消息类型,决定 Payload 的解析方式 • 有效载荷(0-255字节):实际传输的数据内容 • 校验和(2字节):CRC16 校验,用于检测数据完整性

你看,整个包就这么简单。8 个字段,每个字段都有明确的职责。咱们逐个拆解。

3.2 起始标志:帧的“身份证”

起始标志是数据包的第一个字节,固定为 0xFE(MAVLink 1.0)。

为什么是 0xFE?其实没有特别深奥的原因,就是协议设计者选了一个不太常见的值,降低误判概率。你想想看,如果起始标志是 0x00 或 0xFF,串口上到处都是这种值,接收端很容易“假同步”。

小提示:MAVLink 2.0 的起始标志是 0xFD,别搞混了。我见过有人把 1.0 和 2.0 的包混在一起解析,结果数据全乱套了。

3.3 有效载荷长度:告诉你要读多少字节

第二个字节表示有效载荷(Payload)的长度,单位是字节。范围从 0 到 255。

这个字段很关键。接收端读到起始标志后,紧接着读这个长度值,就知道后面要收多少字节才算完。没有它,接收端根本不知道什么时候该停止接收。

举个例子:如果长度字段是 10,那么接收端就知道,后面还有 10 个字节的 Payload,再加上 2 个字节的校验和,总共还要收 12 个字节。

3.4 序列号:防丢包、防乱序

序列号(SEQ)是一个 1 字节的计数器,范围 0-255。每发送一帧,序列号自动加 1,到 255 后回绕到 0。

这个字段有什么用?我举个实际场景:

  • 地面站连续收到序列号 10、11、13,发现 12 丢了,就知道中间有丢包。
  • 如果收到 15、14、16,说明顺序乱了,可以重新排序。
注意:序列号只有 1 字节,最大 255。如果通信频率很高,短时间内可能回绕多次。接收端需要处理回绕逻辑,不能简单用“新的大于旧的”来判断。

3.5 系统ID 与 组件ID:谁在说话?

这两个字段放在一起讲,因为它们共同标识“谁发了这条消息”。

字段 字节数 范围 说明
系统ID(SYS) 1 1-255 标识一个无人机系统(如:1号无人机、2号地面站)
组件ID(COMP) 1 0-255 标识系统内的具体组件(如:飞控=1、GPS=2、相机=100)

举个例子:系统ID=1,组件ID=1,表示“1号无人机的飞控”。系统ID=2,组件ID=100,表示“2号无人机的相机”。

我在做多机编队项目时,就靠这两个字段区分不同飞机。每架飞机分配一个唯一的系统ID,地面站收到消息后,根据系统ID就知道是哪架飞机发来的。

3.6 消息ID:这条消息是什么?

消息ID(MSG ID)只有 1 字节,但它决定了整个数据包的含义。

比如:

  • 消息ID=0:HEARTBEAT(心跳包)
  • 消息ID=30:ATTITUDE(姿态信息)
  • 消息ID=33:GLOBAL_POSITION_INT(全球定位)

接收端读到消息ID后,就知道该用哪种数据结构来解析后面的 Payload。如果消息ID不认识,直接丢弃即可。

核心要点:消息ID是 MAVLink 协议的“灵魂”。协议定义了数百种消息ID,每种对应一组特定的数据格式。你只要记住消息ID,就能知道这条消息在说什么。

3.7 有效载荷:真正的数据

有效载荷(Payload)是数据包的主体,长度由第二个字段指定,范围 0-255 字节。

Payload 的内容完全由消息ID决定。比如:

  • 心跳包(ID=0)的 Payload 只有几个字节,包含系统状态、模式等信息。
  • 姿态信息(ID=30)的 Payload 包含横滚角、俯仰角、偏航角等浮点数。

解析 Payload 时,必须严格按照协议定义的数据结构来。多一个字节、少一个字节,数据就全错了。

3.8 校验和:数据有没有被篡改?

最后 2 个字节是 CRC16 校验和。它覆盖了数据包中从“有效载荷长度”到“有效载荷”的所有字节。

接收端收到数据后,会重新计算一遍 CRC,然后与收到的校验和对比。如果一致,说明数据在传输过程中没有被篡改;如果不一致,直接丢弃。

我曾经在调试一个无人机时,发现地面站经常收不到正确的姿态数据。排查了半天,最后发现是串口线接触不良,导致数据偶尔被干扰。加上 CRC 校验后,问题立刻暴露出来——丢包率高达 30%。

避坑指南:CRC 校验不是可选项,是强制项。不要为了省 2 个字节而跳过校验。我曾经见过有人为了“提高效率”把校验和去掉,结果数据错了都不知道,飞机差点炸了。

3.9 完整数据包示例

咱们看一个实际的 MAVLink 数据包,十六进制表示:

FE 09 1A 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00