3. 数据链路层:帧结构设计、前导码与同步字、CRC校验原理与实现、数据包重传机制
好,咱们进入数据链路层。这一层说白了,就是给原始比特流「穿上衣服」,让它们能有序、可靠地在空中飞。我刚开始做无人机通信时,总觉得物理层搞定就万事大吉,结果发现数据乱飞、丢包、错位……嗯,后来才明白,数据链路层才是通信的「脊梁骨」。
3.1 帧结构设计——给数据搭个骨架
数据链路层的核心产出就是「帧」。你可以把帧想象成一个快递包裹,里面装着你的数据,外面贴着地址、重量、校验码等信息。没有这个结构,接收端根本不知道哪一段是有效数据。
我个人习惯把帧结构分成几个固定区域:
- 前导码:用于唤醒接收端,同步时钟
- 同步字:标记帧的起始位置
- 帧头:包含长度、类型、序列号等控制信息
- 有效载荷:真正的数据内容
- CRC校验:用于检测传输错误
举个例子,我曾在项目中设计过这样一个帧结构:
| 前导码 (4字节) | 同步字 (2字节) | 帧头 (6字节) | 有效载荷 (N字节) | CRC (2字节) |
你想想看,如果前导码和同步字设计得不好,接收端可能一直处于「猜谜」状态,不知道什么时候该开始收数据。所以,这两个字段是帧结构的「门神」。
3.2 前导码与同步字——让收发双方对上暗号
前导码的作用,说白了就是让接收端的时钟和发送端对齐。无线通信中,收发双方的晶振频率不可能完全一致,时间长了就会累积误差。前导码通常是一串交替的0和1,比如 0xAAAAAAAA,接收端通过检测这个模式来调整自己的采样时钟。
同步字则是一个特定的比特模式,用来标记帧的起始。我建议同步字选择自相关性好的序列,比如 0x7E 或 0xD5。为什么?因为这样的序列在随机数据中出现的概率极低,不容易误判。
0xFF 作为同步字,结果发现当有效载荷中出现连续 0xFF 时,接收端会误判帧起始。后来改成了 0x7E7E,问题就解决了。所以,同步字的选择一定要考虑「伪同步」问题。
接收端的工作流程是这样的:
- 持续监听信道,检测前导码模式
- 一旦检测到前导码,开始调整时钟同步
- 等待同步字出现,确认帧起始
- 开始接收后续的帧头和有效载荷
3.3 CRC校验原理与实现——给数据加把锁
无线信道是个「不靠谱」的传输介质,电磁干扰、多径效应都会导致比特翻转。CRC(循环冗余校验)就是用来检测这些错误的。
CRC的原理其实不复杂:把数据看作一个巨大的二进制数,用约定的多项式去除它,余数就是CRC值。接收端用同样的多项式去除收到的数据,如果余数为0,说明数据大概率没出错。
我常用的CRC-16-CCITT多项式是 0x1021(生成多项式为 x^16 + x^12 + x^5 + 1)。为什么选它?因为它在检测常见错误模式上表现很好,而且实现起来不费资源。
下面是一个C语言实现的CRC-16计算函数:
uint16_t crc16_ccitt(uint8_t *data, uint16_t len) {
uint16_t crc = 0xFFFF; // 初始值
for (uint16_t i = 0; i < len; i++) {
crc ^= (uint16_t)data[i] << 8;
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc <<= 1;
}
}
}
return crc;
}
在实际项目中,我一般用查表法来加速CRC计算。预计算256个表项,每次查表代替内层循环,速度能提升好几倍。对于无人机这种实时性要求高的场景,查表法是首选。
3.4 数据包重传机制——丢了就再发一次
CRC能检测错误,但不能纠正错误。一旦发现数据包出错,最简单的办法就是——重传。
重传机制的核心是「确认-超时」模型:
- 发送方发送数据包后,启动一个定时器
- 接收方收到正确数据包后,回复一个ACK确认帧
- 如果发送方在超时时间内没收到ACK,就重传该数据包
这里有个关键问题:超时时间设多长?设短了,容易误判丢包,导致不必要的重传;设长了,信道利用率低。我一般根据实际测试来调整,比如先设为10ms,然后在实际飞行中观察重传率,再微调。
还有一种情况:接收方收到了数据包,但ACK在传输中丢失了。这时候发送方会重传,接收方就会收到重复的数据包。所以,每个数据包都需要一个唯一的序列号,接收方通过序列号来去重。
避坑指南: 我曾经在一个项目中,把序列号设成了8位,结果在高速飞行时序列号很快循环回绕,导致接收方把新数据误判为重复数据。后来改成了16位序列号,配合「滑动窗口」机制,才彻底解决这个问题。
对于无人机这种控制类应用,我建议使用「选择性重传」而不是「回退N步」。因为无人机控制数据通常很小,但实时性要求高,回退N步会导致大量不必要的重传,影响控制延迟。
好了,数据链路层的核心内容就这些。帧结构是骨架,前导码和同步字是门神,CRC是锁,重传机制是保险。把这四样东西设计好,你的无线通信链路就稳了一大半。