4. CAN FD 错误检测机制:位错误、填充错误、CRC 错误、格式错误、ACK 错误
在实际抓波形之前,咱们得先把 CAN FD 的错误检测机制理清楚。我之前带过不少新人,上来就对着逻辑分析仪乱戳,结果波形出来了,一看全是红色标记,根本不知道错在哪。其实说白了,CAN FD 的错误检测就五类,每一类都有明确的触发条件。搞懂了这些,你再看错误帧,心里就有底了。
4.1 位错误(Bit Error)
位错误是最基础的,也最常见。规则很简单:发送节点往总线送一个显性位(逻辑 0),结果回读时却读到了隐性位(逻辑 1),或者反过来——我想送隐性,读到显性,那立刻报错。
这里有个关键点:仲裁期间不会触发位错误。为什么?因为仲裁本身就是多个节点同时发显性位抢总线,这时候读到的电平不一致是正常的。只有在仲裁结束后,才能用位错误来判断总线竞争是否正常结束。
4.2 填充错误(Stuff Error)
CAN 协议规定:连续发送 5 个相同电平后,必须插入一个相反的电平。这叫“位填充”。如果接收方发现连续 6 个相同电平,那就判定为填充错误。CAN FD 的数据场采用了更灵活的填充规则,但原理是一样的——防止时钟同步丢失。
位填充的另一个作用是保持时钟同步。每个上升沿或下降沿都能让接收节点重新同步采样点。我记得第一次做 CAN FD 通信时,数据段速率到了 5 Mbps,填充规则一旦被破坏,整个网络就像多米诺骨牌一样连续报错。
4.3 CRC 错误
CRC 错误是数据完整性检查的最后一道防线。发送节点会根据报文内容计算出一个 17 位或 21 位的 CRC 校验和(CAN FD 的 CRC 比经典 CAN 长),接收节点用同样的算法重新算一遍,如果结果不匹配,就报 CRC 错误。
我在项目里遇到过一种情况:总线终端匹配不良导致信号反射,反射波叠加到正确的电平上,使得某些位被误判。CRC 能检查出这种“看起来像合法数据但实际上已经变形”的情况。所以当你看到连续多个 CRC 错误时,别急着怀疑芯片,先检查一下物理层。
| 错误类型 | 检测方 | 触发条件 |
|---|---|---|
| 位错误 | 发送方 | 发送电平与回读电平不一致(仲裁期间除外) |
| 填充错误 | 接收方 | 连续 6 个相同电平 |
| CRC 错误 | 接收方 | 本地 CRC 计算结果与接收到的 CRC 段不匹配 |
| 格式错误 | 接收方 | 固定隐性电平的场段被读成显性 |
| ACK 错误 | 发送方 | 在 ACK 槽内未读到显性位(无节点确认) |
4.4 格式错误(Form Error)
CAN FD 的帧格式里有一些**固定电平**的段——比如 CRC 分隔符、ACK 分隔符、EOF(帧结束)。这些段必须保持隐性。如果接收方在这些段上读到了显性位,那就触发格式错误。嗯,这个东西很刁钻。
我记得有一次,客户的 CAN FD 节点在高温环境下频繁报格式错误。后来发现是 RXD 引脚上的噪声毛刺被误判成显性位。解决办法很简单:在 RXD 上串一个 1 kΩ 电阻,或者调整 CAN 控制器的数字滤波参数。格式错误的定位往往比位错误更难,因为它的触发点很窄(就几个 bit 时间),逻辑分析仪一定要把时基调小才能看清。
4.5 ACK 错误(Acknowledgment Error)
发送节点在 ACK 槽期间(紧跟着 CRC 分隔符之后)会释放总线,如果此时没有其他节点主动拉低总线(即发送显性位来确认),发送节点就会读到隐性,于是报 ACK 错误。这说明你的报文发出来了,但没有节点收到并正确通过 CRC 校验。
1. 检查总线终端电阻(缺一个就没法把显性位拉到底)
2. 检查接收节点的 CAN 控制器是否处于 BusOff 状态
3. 检查接收节点的验收滤波是否把该报文过滤掉了
4. 如果以上都正常,用差分探头量一下 CAN_H 和 CAN_L 之间的压差,看看显性位是否真的能达到 1.5 V 以上。
ACK 错误还有个特殊场景:CAN FD 的采样点兼容性问题。不同厂家的 CAN FD 控制器采样点位置可能不同(比如有的设在 75%,有的设在 80%),如果采样点误差太大,接收方可能在 ACK 槽上采样失败。我个人习惯在设计阶段就统一所有节点的采样点,避免这种隐形坑。
4.6 五种错误的地图式归纳
下面这张 SVG 图把这五种错误检测机制的关系画出来了。你拿到逻辑分析仪波形后,先看错误帧的类型,再对照这张图找到可能的根因,排查效率能提升不少。
4.7 错误状态机与恢复
说了这么多错误检测,最后补一句状态机。CAN 控制器内部有三个状态:错误活动(Error Active)、错误被动(Error Passive)、总线关断(Bus Off)。每个节点内部有发送错误计数器和接收错误计数器,累计到一定阈值就会切换状态。错误活动状态下的节点在检测到错误后会发送主动错误标志(6 个显性位);错误被动状态下的节点只能发送被动错误标志(6 个隐性位);一旦进入 Bus Off,节点完全退出总线,不再参与任何通信。