第四章 链路层协议:帧结构、多帧、通道映射、扰码与CRC校验
链路层,说白了就是JESD204B的骨架。数据怎么打包,怎么分组,怎么搞定同步,全靠这层定规矩。我刚开始接触这个标准时,光看帧和多帧的关系就绕了半天。今天咱们把它拆开,一个一个说清楚。
4.1 帧结构:基本传输单元
JESD204B里最小的数据单元叫“帧”。一个帧包含固定数量的字节,具体多少个,由参数F决定。F可以是1、2、4,甚至更大。你在配置时选一个值,协议就把ADC的采样数据切成这么长的块。
举个例子,F=1时,一个帧只有1个字节。F=4时,一个帧有4个字节。每个字节对应一个转换器样本的某个部分。如果是多链路多转换器,还会混合多个通道的数据。
每个帧的边界由帧时钟(frame clock)标定。收发双方必须严格对齐这个边界。
4.2 多帧:更高级的分组
多帧是多帧的集合?别被字面绕晕了。一个“多帧”是多个帧组成的一个逻辑分组。数量由参数K定义,K的取值范围通常是1到32。一个多帧包含K个帧。
多帧的重要性在于——同步。链路建立阶段,接收端靠多帧边界来锁定对齐。它还会在数据流中插入特定的同步字符(/A/、/Q/、/F/等),这些字符只出现在多帧的边界上。我调试时遇到过一次对接不上,查了半天才发现是K配置不匹配。
| 参数 | 含义 | 典型值 |
|---|---|---|
| F | 每帧字节数 | 1, 2, 4 |
| K | 每多帧包含帧数 | 4, 8, 16 |
| 帧时钟 | 每秒帧数 | 由链路速率 / (F×8) 决定 |
4.3 通道映射:数据怎么分配到每条线
通道映射解决一个问题:多个ADC通道的数据,如何在多条物理链路上传输?JESD204B用一套灵活的映射规则。每个转换器样本被拆成若干字节,然后按照你定义的顺序塞进不同的帧字节里。
映射规则写在寄存器里,你通过SPI或I²C配置。接收端必须用完全相同的映射才能恢复。我记得有一次把映射配反了,示波器上波形完全不对。后来打开JESD204B协议手册的附录,一行一行对,才找到毛病。所以我的建议是:画一张映射表,写进代码注释里,别偷懒。
4.4 扰码:让信号更干净
为什么需要扰码?想象一下,你一直发相同的字节(比如全是0x00),链路上一段时间没有电平跳变。那么时钟恢复电路就很难锁定,错误率会飙升。扰码就是故意打乱数据,保证足够的跳变密度。
JESD204B用了一个多项式:x⁸ + x⁴ + x³ + x² + 1。它是个自同步扰码器,接收端不需要知道初始值,只要收到数据就能恢复。算法很简单:输出 = 输入 ⊕ 扰码器状态。状态是8位,每处理一个字节更新一次。
我在项目中习惯把扰码和校验开关设计成可配的。调试初期关掉扰码,方便用逻辑分析仪看原始数据;确认跑通后再打开。千万别忘了在生产代码里打开,否则链路可能通但不过EMI测试。
4.5 CRC校验:数据完整性最后一道防线
CRC校验是多帧级别加的。在每个多帧末尾,插入一个校验码。接收端重新计算,如果对不上,就报错并请求重传。JESD204B定义了两种模式:CRC-12和CRC-8。具体用哪个由链路配置决定。
CRC-12多项式:x¹² + x¹¹ + x³ + x² + x + 1。
CRC-8多项式:x⁸ + x² + x + 1。
计算方式很简单:把整个多帧(不含校验字节)的字节串当作被除数,多项式作除数,取余数。注意起始值、输出异或值在协议中有固定规定,不能随便改。我见过有人自己实现CRC时忘了处理这些细节,导致接收端永远报CRC error。
// CRC-8 计算示例(多帧长度为K×F字节,校验字节1个)
uint8_t crc8(const uint8_t *data, int len) {
uint8_t crc = 0x00;
for (int i = 0; i < len; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x80) crc = (crc << 1) ^ 0x07; // 多项式写入
else crc = crc << 1;
}
}
return crc ^ 0x00; // 输出异或值
}
4.6 链路层协议整体流程
下面这张图把帧、多帧、扰码、CRC、通道映射之间的关系画在了一起。你一看就明白。
看到没?数据先从ADC样本进来,经过通道映射分配字节顺序。然后组帧,每F个字节一帧。接着成多帧,每K个帧一个组。之后可选扰码,再在每个多帧末尾加上CRC校验。最后串行化输出。
4.7 实际调试中的几个关键参数
- 检查F与K的乘积: 多帧总字节数 = F × K。这个值决定同步头占位。我建议先配小值(比如F=1,K=4)跑通,再逐步放大。
- 通道映射的字节对齐: 如果ADC是16位,每个样本占2字节。映射时要指定哪个字节走哪个帧位置。调试时打印出映射表,一次确认。
- 扰码的使能同步: 发送端和接收端必须同时开或同时关。我在一次协作中忘了同步这个配置,花了半天才发现。
- CRC错误的排查: 如果接收端频繁报CRC错误,先把扰码关掉,再看原始数据是否对。可能是串行链路误码,也可能是配置问题。
嗯,链路层的东西说到这儿。帧、多帧、映射、扰码、CRC,每个环节都绑在一起。你配错一个参数,整个链路就不干活。不过别怕,只要掌握了这个架构,调试的时候就知道从哪里下手。