错误类型概述
这五种错误类型,我几乎每天都在跟它们打交道。说实话,刚入行那会儿觉得只要收发正常就行,结果在EMC测试现场被折磨得够呛——原来每种错误背后都有不同的根因,处理方式也完全不同。
CAN协议规定了5种错误类型:
- 位错误 – 发送与接收电平不匹配
- 填充错误 – 连续相同位超过5个
- CRC错误 – 校验和与本地计算不符
- 格式错误 – 固定格式位取值违规
- 应答错误 – 无节点在应答间隙拉低总线
你可能觉得这五种错误名字听起来挺规矩,但在实际调试中它们往往同时出现、互相触发。我个人习惯先把它们画成一张关系图。
位错误
位错误,说白了就是“我说了0,却听到了1”。发送节点在发送一帧时,会在每个位时刻回读总线电平,如果和自己发送的不一致,立刻报错并发送主动错误标志。
我在项目中遇到过一辆电动汽车,高速行驶时偶尔报“位错误”。后来用示波器抓到总线波形,发现终端电阻焊点松动导致信号反射,在某个位采样点出现振铃,刚好被误判为相反电平。你想想看,一个焊点的问题,查了我整整两天。
查找思路: 位错误通常指向物理层问题:终端电阻、共模电压、线缆过长、CAN收发器供电不稳。先查终端电阻是否匹配,再查共模电压是否在-2V~+7V范围内。
填充错误
CAN协议为了保证时钟同步,规定同一极性连续不能超过5个位。如果发送了6个连续的显性或隐性位,接收节点就会报填充错误。这个机制其实是为了防止节点失去同步。
说起来挺简单,但我在调试一个多节点系统时,发现某个老旧的节点偶尔发送出6个连续隐性位。为什么会这样?因为它的晶振老化,分频器计数跳过了中间的位填充插入点。我建议你遇到填充错误时,优先检查故障节点的晶振精度和CAN控制器PLL配置。
- 发送端主动违规(极少见,通常是硬件bug)
- 接收端在错误帧之后可能读到一个填充错误(二次错误)
- 干扰导致位翻转,形成连续6个相同位
CRC错误
每个CAN帧尾部带一个15位CRC序列(标准帧)。接收节点用相同的多项式重算,如果结果不符,就报CRC错误。这是对数据完整性的最后把关。
我曾经遇到一个案例:一条总线上有3个节点,其中1个偶尔报CRC错误。抓到的错误帧里,数据段看起来完全正常,但CRC段有几个位错了。后来发现是CAN收发器输出引脚虚焊,导致信号上升沿变缓,采样时把1误判成了0。用示波器量上升时间,正常应在100ns以内,那个引脚到了300ns。
注意: CRC错误不一定表示数据被篡改,更多时候是信号完整性问题。不要一上来就怀疑软件算法,先查物理层。
格式错误
CAN帧中有几个固定格式位:SOF、SRR、IDE、R0、R1、DLC的高两位等。如果这些位不是协议规定的值,就会引发格式错误。比如DLC只能取0~8,如果收到9,那就是格式错误。
这类错误在正常节点中极少出现。我记得有个项目,新来的同事写CAN驱动时定义了DLC=0x0F(15),结果一发送总线就崩。原因就是他把DLC当成了数据长度字节,直接赋值了数据缓冲区的长度。格式错误的核心排查思路:看哪个节点发送的,检查它的CAN控制器配置和上层协议栈是否正确填充了帧结构。
应答错误
应答机制很简单:发送节点在ACK slot(第7个位)发送隐性位,如果总线上有任意节点正确接收,就会在该位拉低为显性。如果发送节点在ACK slot结束后没有读到显性位,就报应答错误,并重发(或进入bus-off流程)。
我在产线测试时遇到一个问题:新生产的ECU插到总线上,上位机发帧总是没应答。查了半天,发现ECU的CAN控制器处于“只听模式”(Listen Only),不会拉低ACK slot。你想想看,这个模式本来用于调试的,结果忘了改回来。还有一个常见情况:两个节点波特率不一致,接收节点无法正确采样ACK slot,也会导致无应答。
快速检查表:
| 错误类型 | 主要检测者 | 常见诱因 | 典型现象 |
|---|---|---|---|
| 位错误 | 发送节点 | 物理层干扰、终阻失配 | 发送节点立刻发主动错误帧 |
| 填充错误 | 所有接收节点 | 发送节点时钟偏差、干扰翻转 | 连续6个相同位后报错 |
| CRC错误 | 所有接收节点 | 信号边沿畸变、位采样偏差 | CRC段与本地计算不符 |
| 格式错误 | 所有接收节点 | 软件配置错误、CAN控制器bug | 固定格式位为非法值 |
| 应答错误 | 发送节点 | 无节点在线、波特率不匹配、节点处于只听模式 | ACK slot保持隐性 |
嗯,这五种错误就像总线的五种“病状”,每个都对应着不同的病因。实际调试中它们常常互为因果——比如一次干扰引发位错误,位错误导致的错误帧又让其他节点误判出填充错误。我的习惯是先用CAN分析仪过滤出原始错误类型,再逐条锁定源头。