第2章:MAVLink协议深度解析
2.1 MAVLink协议发展史
MAVLink,全称Micro Air Vehicle Link。说白了,它就是无人机界的“普通话”。
我第一次接触MAVLink是在2010年。那时候还在用v0.9版本,说实话挺简陋的。后来2013年,v1.0正式发布,这才算真正成熟起来。我记得当时接手一个项目,客户要求兼容老版本,那叫一个头疼。
现在主流是v1.0和v2.0两个版本。v2.0主要解决了几个痛点:
- 消息ID范围扩大:从256个扩展到16777216个
- 支持签名验证:防止数据被篡改
- 兼容v1.0:向下兼容,老设备也能用
我个人习惯,新项目直接上v2.0。除非你还在维护十年前的老古董。
2.2 消息格式深度拆解
MAVLink的消息格式,我把它分成三块:Header、Payload、CRC。咱们一个一个说。
2.2.1 Header(帧头)
v1.0的Header是6字节,v2.0是10字节。我直接给个对比表:
| 字段 | v1.0 | v2.0 | 说明 |
|---|---|---|---|
| 起始标志 | 0xFE | 0xFD | 区分版本 |
| Payload长度 | 1字节 | 2字节 | v2.0支持更大数据 |
| 序列号 | 无 | 1字节 | 防丢包用的 |
| 系统ID | 1字节 | 1字节 | 区分不同无人机 |
| 组件ID | 1字节 | 1字节 | 区分飞控、GPS等 |
| 消息ID | 1字节 | 3字节 | v2.0支持更多消息 |
嗯,这里要注意。v2.0的起始标志是0xFD,不是0xFE。我在项目中遇到过有人搞混,结果解析出来的数据全是乱码。
2.2.2 Payload(数据体)
Payload就是实际要传的数据。长度从0到255字节不等。具体结构取决于消息ID。
举个例子,心跳包(HEARTBEAT)的Payload只有9字节:
typedef struct {
uint8_t type; // 无人机类型
uint8_t autopilot; // 飞控类型
uint8_t base_mode; // 基础模式
uint32_t custom_mode; // 自定义模式
uint8_t system_status; // 系统状态
} mavlink_heartbeat_t;
你想想看,9个字节就能知道无人机的基本状态,效率很高吧?
2.2.3 CRC(校验码)
CRC是保证数据完整性的关键。MAVLink用的是CRC-16-CCITT,多项式是0x1021。
我曾经踩过一个坑:CRC计算时,Payload长度字段也要参与校验。一开始我没注意,结果数据总是校验失败。排查了整整两天才发现。
2.3 心跳包机制
心跳包,英文叫HEARTBEAT。它是MAVLink里最重要的消息,没有之一。
为什么重要?因为它是“活着”的标志。无人机每隔1秒发一个心跳包,告诉地面站:“我还活着,一切正常。”
心跳包的消息ID是0。没错,就是0。这是MAVLink里优先级最高的消息。
心跳包的内容包括:
- type:无人机类型(四旋翼、固定翼等)
- autopilot:飞控类型(PX4、ArduPilot等)
- base_mode:基础模式(手动、自动等)
- custom_mode:自定义模式(比如任务模式)
- system_status:系统状态(正常、警告、紧急等)
我个人习惯,在调试时先看心跳包。如果心跳包正常,说明通信链路没问题。如果心跳包丢了,那问题就大了。
2.4 消息ID分配规则
消息ID,就是MAVLink里每条消息的“身份证”。
v1.0只有256个ID,从0到255。v2.0扩展到16777216个,从0到16777215。
分配规则是这样的:
| ID范围 | 用途 | 示例 |
|---|---|---|
| 0 - 49 | 核心消息 | HEARTBEAT(0), SYS_STATUS(1) |
| 50 - 99 | 任务消息 | MISSION_ITEM(39) |
| 100 - 149 | 参数消息 | PARAM_REQUEST(21) |
| 150 - 199 | 传感器消息 | GPS_RAW(24) |
| 200 - 255 | 厂商自定义 | 自己定义 |
嗯,这里要注意。厂商自定义消息的ID范围是200-255。我建议不要随便用,因为可能会和未来的官方消息冲突。
我曾经在项目里自定义了一个消息ID 200,结果后来MAVLink官方更新,把200分配给了新消息。那叫一个尴尬。后来我学乖了,自定义消息都用ID 250以上。
2.5 实战经验总结
说了这么多,最后分享几个实战经验:
- 优先处理心跳包:在接收数据时,先检查是不是心跳包。如果是,优先处理。
- 注意CRC校验:不要偷懒跳过CRC。我见过太多因为CRC没做导致数据错乱的案例。
- 版本兼容:如果系统里有v1.0和v2.0的设备,记得做版本检测。
- 消息ID规划:自定义消息ID时,留好扩展空间。别等到不够用了再改。
好了,这一章就到这里。下一章我们聊聊数传模块的硬件选型,那又是另一个故事了。