2. CAN协议基础
做CAN协议一致性测试,绕不开三个最基础的东西:帧长什么样、位怎么填充、CRC怎么算。这三件事看似独立,其实环环相扣。我最早接触CAN时,以为只要把帧格式背下来就行——后来被一个隐性错误狠狠上了一课,才发现位填充和CRC才是真正的“隐形杀手”。咱们按顺序拆开说。
2.1 帧格式——五种帧与一场“握手”
CAN总线上跑着五种帧:数据帧、远程帧、错误帧、过载帧、帧空间。测试中打交道最多的是数据帧和远程帧。
| 帧类型 | 用途 | 仲裁方式 |
|---|---|---|
| 数据帧 | 发送节点把数据喂给总线 | ID越小优先级越高 |
| 远程帧 | 请求某个ID的数据 | 同样ID下,远程帧优先级低于数据帧 |
| 错误帧 | 任何节点发现总线错误时主动发出 | 固定高优先级 |
| 过载帧 | 接收节点还没准备好接收下一帧 | 插在帧间隔中 |
| 帧空间 | 帧与帧之间的间隔,包括间歇场和总线空闲 | — |
数据帧的结构我习惯分成七个段:SOF(起始帧)、仲裁域、控制域、数据域、CRC域、ACK域、EOF。标准帧11位ID,扩展帧29位ID。这里有个坑——一致性测试会专门检查CRC域是否包含了位填充后的数据,而不是原始位流。
2.2 位填充——为什么需要它?又为什么头疼?
位填充的规则很简单:发送器检测到连续5个相同的位(00000或11111),就在第5位之后自动插入一个反向位。接收器看到5个相同位,就自动把第6位扔掉。
- 规则:连续5个相同位 → 插入一个相反位
- 作用:维持位同步,防止DC偏移
- 例外:CRC界定符、ACK槽、ACK界定符、EOF不参与填充
我见过一个真实案例:某款MCU的CAN控制器实现有bug,位填充逻辑只在数据域的比特流里生效,却忘记了CRC域里的填充。结果总线上一出现奇偶性不好的CRC序列就丢帧。一致性测试里专门有一条:强制构造连续5个相同位的数据,观察CRC域是否也被正确填充。
2.3 CRC校验——算法逻辑与测试陷阱
CAN的CRC是个15位的生成多项式:x¹⁵ + x¹⁴ + x¹⁰ + x⁸ + x⁷ + x⁴ + x³ + 1。计算范围从SOF到数据域结束,不包括位填充位。我刚开始做测试时总觉得CRC既然有硬件算,就不用管细节。直到有一次误码率测试不过,才发现CRC的校验范围没搞清楚——数据域之后的CRC序列本身是不参与CRC计算的。
计算步骤:
- 初始化CRC寄存器为全0
- 对SOF到数据域结束的每个位(不含填充位),逐位移入寄存器
- 最后得到15位CRC序列,填入CRC域
- 接收器用同样的多项式计算,若结果等于0,说明无误
多项式对应的二进制表示为:1 1000 0100 1100 1001(0x4599)。注意,这个15位数据在总线上传输时是高字节在前,还是低字节在前?我见过不少工程师搞反了——CAN协议规定:CRC序列的发送顺序是MSB first。
| 特性 | 数值 |
|---|---|
| 生成多项式 | 0x4599(15位) |
| CRC序列长度 | 15位 |
| 校验范围 | SOF + 仲裁域 + 控制域 + 数据域(不含填充位) |
| 发送顺序 | MSB first |
| 余数检测 | 接收方CRC寄存器最终应为0 |
一致性测试里有一个经典案例:构造一个包含突发错误的帧,观察DUT能否正确报出CRC错误。测试仪器会在CRC域之前或之后的某个位置注入一个位翻转,然后检查DUT的ERR引脚或状态寄存器。我用这个方法查出过两个不同供应商的CAN控制器都有同样的bug:它们把ACK slot也纳入了CRC计算范围。
2.4 本章知识结构——三件事怎么串起来?
下面这张图展示了帧格式、位填充与CRC的交互关系。注意CRC计算发生在位填充之前,而最终在总线上传输的是填充后的位流。这就是很多测试出问题的根源。
2.5 一致性测试中的常见陷阱与实操建议
做一致性测试时,很多工程师只关心“帧能不能被解析”,忽略了位填充和CRC的边界情况。我总结几个高频出错点:
- 位填充后CRC计算错误: 测试仪器模拟发送时,如果没在CRC域之后关闭位填充,会导致EOF提前或延后。ISO 11898-1明确说:CRC界定符之后位填充停止,但有些老款控制器在ACK段仍会尝试填充——直接报错。
- CRC边界条件: 当数据域长度=0时(远程帧),CRC计算范围如何?标准答案:只有SOF + ID + RTR + 控制域。我曾经遇到一个DUT在RTR=1时把数据域占位也纳入了CRC,导致误码。
- 远程帧与数据帧的区分: 远程帧无数据域,但CRC仍然计算。有些廉价CAN接口芯片在远程帧上漏掉了CRC,导致接收端永远回复错误帧。
- 填充位对同步抖动的影响: 我在做EMC测试时发现,连续填充位越多,位定时恢复电路的误差越大。一致性测试会构造“65个连续显性位”(最坏情况),看DUT能否保持同步不掉帧。