4. CRC校验过程:接收端校验、余数为零判定、校验错误标志
收发两端用的是同一套生成多项式,这个咱们上一章已经聊过了。那接收端拿到数据之后,到底怎么判断它有没有被"污染"?说白了,就是再做一遍除法,看余数。
我个人习惯把CRC接收端校验叫作"验算"。就像你算完一道数学题,回头再检查一遍。只不过这里是硬件替你检查,而且检查得又快又准。
接收端校验的基本流程
接收端做的事,其实就三步:
- 收完整帧——把数据字段和FCS字段一起收下来,注意FCS就是发送端附加的余数
- 做模2除法——用双方约定好的生成多项式G(x),对整个码字做除法
- 看余数——余数为0,判定传输正确;余数不为0,判定传输出错
你想想看,发送端故意在数据后面加了一段余数,目的就是让整个码字能被G(x)整除。如果传输过程中没有比特翻转,接收端除出来的余数一定是0。这就是CRC最核心的校验逻辑。
关键认知:接收端不需要知道原始数据是什么,只需要做一道除法,通过余数就能判断数据是否完整。这种"无状态校验"是CRC在工程中广泛应用的重要原因。
下面这张图把整个流程串起来了,我建议你先看一遍,再读后面的原理:
余数为零的判定原理
为什么余数为0就代表传输正确?这事儿得从发送端说起。
发送端在数据后面附加的FCS,本质上是一个精心算出来的"补码"。它的作用就是让整个数据帧能被G(x)整除。用数学公式来表达就是:
发送码字 = 数据 × x^r + 余数
= 商 × G(x)
接收端拿到的码字,如果传输过程中没出错,就等于发送码字。那你用它除以G(x),余数自然是0。
但如果传输中发生了比特翻转,接收到的码字就变成了"发送码字 + 错误向量"。这时候再除以G(x):
接收码字 ÷ G(x) = (发送码字 + 错误向量) ÷ G(x)
= 商 + (错误向量 ÷ G(x))
只要错误向量不能被G(x)整除,余数就不为0。CRC的检错能力,本质上就是看"哪些错误向量能被G(x)整除"——这些就是漏检的情况。好的生成多项式,能把这个漏检率压到极低。
我的经验:有一次在调试串口通信时,发现CRC校验偶尔会报错,但重传之后又好了。查了半天,发现是电源纹波太大,导致接收端采样时钟抖动。所以CRC报错不一定都是"比特翻转",有时候是信号完整性问题。建议你先排除物理层干扰,再怀疑CRC算法本身。
校验错误标志的处理机制
接收端发现余数不为0之后,接下来该干什么?
在硬件层面,CRC校验器会直接输出一个错误标志信号。不同的芯片实现方式略有差异,但逻辑是一样的:
| 判定结果 | 硬件行为 | 软件行为 | 后续处理 |
|---|---|---|---|
| 余数为0 | 清除CRC错误标志 | 读取数据,继续处理 | 正常通信,无需干预 |
| 余数不为0 | 置位CRC错误标志 | 丢弃数据帧,请求重传 | 触发错误处理流程 |
这里有几个工程细节,我想提醒你注意:
- 错误标志是锁存的:一旦CRC校验失败,标志位会被硬件锁存,直到软件主动清除。我见过不少新手忘了清标志,导致后续所有帧都被误判为错误。
- 连续错误计数:我个人习惯在驱动层加一个连续错误计数器。单次CRC错误可能是干扰,但连续5次甚至10次错误,说明链路可能已经断开了。
- 不要直接丢弃:在某些安全关键系统中,CRC错误的帧会被保留下来用于故障分析,而不是直接丢弃。你可以把它存到一个"坏帧缓冲区"里,方便排查根因。
我曾经踩过一个坑:一个项目里用了某款MCU的硬件CRC模块,手册上写着"自动清除标志"。实际测试发现,它只在连续两帧都正确的情况下才清除标志。如果正确帧后面紧跟着错误帧,标志会一直保持置位。后来我不得不在每个帧中断里手动读一次CRC状态寄存器。所以,永远不要100%相信硬件手册上的表述,实测才是硬道理。
实战中的注意事项
接收端校验看起来简单,但在实际项目中容易出问题的往往是细节。我总结了几个高频"坑点":
- 生成多项式不匹配:收发两端的G(x)必须完全一致,包括多项式表达方式(正常多项式 vs 反转多项式)。我在一个项目中吃过这个亏,双方用的是同一个多项式编号,但一家用了正常实现,另一家用了反转实现,结果CRC死活对不上。
- 初始值不同:有些CRC算法会给移位寄存器设一个非零初始值(比如CRC-32用0xFFFFFFFF)。如果收发端初始值不一致,余数校验永远通不过。
- 字节序问题:多字节数据在传输时,高位在前还是低位在前?这个会影响FCS的计算结果。我曾经为这个问题调了整整两天。
- FCS的附加方式:有些协议把FCS直接附加在数据末尾,有些会做位反转后再附加。接收端必须用同样的方式解析。
一句话总结:接收端CRC校验 = 模2除法 + 余数判定 + 标志处理。三个环节环环相扣,任何一个环节出问题,都会导致误判。
好了,关于接收端校验的核心内容就这些。核心就三件事:怎么做除法、怎么判余数、怎么处理标志。你把这套逻辑理清楚了,CRC的接收端对你来说就没秘密了。