1. 测试框架:两层看总线
CAN 通信故障分两类:物理层问题(电平、波形、阻抗、干扰)和协议层问题(波特率失配、ID 冲突、错误状态)。排查时先分清现象属于哪一层,能少走一半弯路:
| 层次 | 看什么 | 用什么 | 典型现象 |
|---|---|---|---|
| 物理层 | CANH/CANL 电压、差分幅值、边沿、采样点、终端阻抗 | 示波器(差分探头或双通道相减)、万用表 | 波形畸变、电压超范围、时好时坏、长线误码 |
| 协议层 | 帧结构、CRC、位填充、错误帧类型、错误计数、负载率 | CAN 分析仪、SocketCAN(candump/ip)、逻辑分析仪 | 错误帧风暴、Bus-off、偶发丢帧、周期性重发 |
先万用表量阻抗、示波器看波形,再做协议层抓帧——因为协议层的"错误帧风暴"往往只是物理层问题的表象。
2. 物理层电平规范:ISO 11898-2
高速 CAN(ISO 11898-2)用 CANH 与 CANL 之间的差分电压表示位:
| 状态 | 逻辑 | CANH | CANL | 差分 Vdiff=CANH−CANL |
|---|---|---|---|---|
| 显性(Dominant) | 0 | ≈3.5V | ≈1.5V | ≈2V(1.5~3.0V) |
| 隐性(Recessive) | 1 | ≈2.5V | ≈2.5V | ≈0V(−0.5~+0.05V) |
接收器判定阈值:Vdiff > 0.9V 判显性,< 0.5V 判隐性(0.5~0.9V 为不确定区)。共模电压应控制在 −2V~+7V。要点:
- 示波器必须测差分:两路探头分别接 CANH/CANL,用通道 A−B 看差分波形;直接单端看 CANH 会把共模干扰误判成信号问题。
- 隐性电平应稳定在 2.5V 附近:明显偏低(如 1.8V)说明收发器供电或终端偏置异常。
- 显性差分低于 1.5V:要么终端电阻过小拉低了驱动能力,要么线缆过长/阻抗不匹配。
- 低速 CAN(ISO 11898-3)是另一套电平(隐性差分 −1.5V、显性 3V),别拿高速规范去套。
3. 示波器测量项目:电平、位时间与采样点
用示波器在 CANH/CANL 差分通道上逐项核对(建议每项都截图存档):
| 测量项 | 合格判据 | 异常解读 |
|---|---|---|
| 隐性电压 | ≈2.5V(2.0~3.0V) | 偏置/供电异常 |
| 显性差分幅值 | 1.5~3.0V,典型 2V | <1.5V:终端过小/线太长;>3V:终端缺失/阻抗失配 |
| 位时间 Tbit | 1/波特率(500k → 2µs) | 偏差>容差 → 采样错位、错误帧 |
| 采样点位置 | 位内 60~90%,全网一致 | 不同节点采样点差异大 → 同步失效 |
| 边沿振铃/过冲 | 过冲小、无持续振铃 | 终端缺失/阻抗不连续 → 反射 |
| 终端阻抗(断电量) | CANH−CANL 静态 ≈60Ω | ≈120Ω:缺一端终端;≈0Ω:短路;∞:断路 |
终端电阻的实测判断:断电后在总线任一点量 CANH−CANL 间电阻。两端各 120Ω 并联 = 60Ω;只量到 120Ω 说明少一端终端(或该节点没上电生效);0Ω 是短路(注意别把收发器内部电阻误判),∞ 是断线。
一是必须断电测量,上电时收发器有源阻抗会干扰读数;二是量到的 60Ω 是"两端并联"结果,不能据此判断"每个节点都接了"——逐节点断电复测,或直接看节点终端开关状态。
4. 协议层测试:帧、错误与负载率
4.1 五类错误与错误帧
CAN 的可靠性来自"发送自检 + 全节点监督"。协议层测试的核心是识别错误帧类型——它直接告诉你问题在哪:
| 错误类型 | 检测原理 | 常见诱因 |
|---|---|---|
| 位错误 | 发送节点发出去的位与总线回读不一致(仲裁段/ACK 段除外) | 电平异常、短路、两节点同时收发器冲突 |
| 填充错误 | SOF~CRC 段出现连续 6 个相同位(违反 5 位插 1 反位规则) | 控制器同步丢失、干扰造成长串同电平 |
| CRC 错误 | 接收节点重算的 CRC 与帧内 CRC 不符 | 干扰、线缆质量、位错误未被当场发现 |
| 形式错误 | 固定格式字段(定界符/EOF/ACK 定界符)出现非法电平 | 时序错乱、干扰 |
| ACK 错误 | ACK 槽采样到隐性(没有节点应答) | 总线上只有发送节点、接收节点未同步 |
任何节点检测到错误,立即发错误帧:主动错误标志(6 个显性位)+ 错误定界符(8 个隐性位)。错误帧会让当前帧作废并被重发,这是"抓不到正常帧、满屏错误帧"的机制根源。
4.2 错误状态机与 Bus-off
每个节点维护收发错误计数器 TEC/REC,按计数分三态:
| 状态 | 错误计数 | 行为 |
|---|---|---|
| 主动错误(Error Active) | TEC<128 且 REC<128 | 正常收发,出错发主动错误帧(6 显性位) |
| 被动错误(Error Passive) | 128≤TEC≤255 | 只能发被动错误帧(6 隐性位),发送前等待 |
| Bus-off | TEC>255 | 节点脱离总线,不参与任何收发 |
Bus-off 恢复:节点需连续检测到 128 次"11 个隐性位"(总线空闲)后自动回到主动错误状态。排查 bus-off:先看错误类型——TEC 快速上涨通常是位错误(自身发不出去),稳定上涨多是 ACK/CRC(总线问题)。Linux 下用 ip -s -d link show can0 可看内核统计的 error 计数与 bus-off 次数。
4.3 负载率计算
单帧位数 ≈ 47 + 8×DLC(标准帧)/ 67 + 8×DLC(扩展帧),单位:位
负载率 = Σ(帧位数) / 波特率 / 统计窗口时长 × 100%
注:公式不含位填充(实际约 +10~25%)与帧间隔外的总线空闲;重发帧会重复计入
工程参考:负载率 <30% 属于轻载,>50% 就要关注仲裁延迟与抖动,>80% 在实时场合基本不可用。测负载率有两个口径——协议层(分析仪按帧统计,本文 C 代码实现)和物理层(示波器统计总线空闲比例,更真实,含错误帧占用)。
5. 故障排查流程:从现象到结论
拿到一个 CAN 故障,按"量 → 看 → 拆"三步走:
- 量阻抗:断电量 CANH−CANL ≈60Ω?不是则修终端/短路/断路。
- 看波形:上电后差分波形是否符合 11898-2?显性 2V/隐性 0V、位时间对、边沿干净?
- 拆节点:分析仪抓帧,逐节点断开,看错误帧是否消失——定位肇事节点。
| 现象 | 最可能原因 | 验证手段 |
|---|---|---|
| 完全无波形/无通信 | 断线、未供电、收发器损坏 | 万用表通断、示波器看 VCC |
| 波形幅值偏小 | 终端缺失/过多、线缆过长 | 量 60Ω、看边沿振铃 |
| 单节点发报错(ACK) | 总线上只有自己、对方没同步 | 确认对端节点数、波特率一致 |
| 满屏错误帧/CRC | 波特率不匹配、干扰、线缆质量 | 分析仪看错误类型、示波器看毛刺 |
| 时好时坏 | 接触不良、共模干扰、终端松动 | 晃动线缆复现、测共模电压 |
| 节点 Bus-off 掉线 | 该节点自身发送路径故障 | 看 TEC 上涨速率与错误类型 |
6. 交互式演示:故障诊断示波器
选择一种总线场景,示波器视图画出 CANH/CANL 波形(500kbps 下 SOF + 数据位的示意波形),下方给出电平判定与诊断建议。波形为示意,用于把"现象 → 结论"对应起来。
观察要点:多数故障最终都表现为错误帧风暴或节点掉线,但根源在物理层——示波器看到的是"因",分析仪看到的是"果"。先治因,错误帧自然消失。
7. 总线测试 C 代码(SocketCAN)
下面的程序在 Linux 上用 SocketCAN 原始套接字统计一个窗口内的数据帧数、错误帧数、负载率与重复帧,并对错误帧比例过高的场景给出 bus-off 风险提示(Linux 下可再用 ip -s -d link show can0 核对内核统计)。
8. 测试报告要点
现场测试建议按以下清单留档,故障复现时直接对比"基线 vs 故障":
- 环境:日期、接线拓扑(节点数/线长/分支)、终端电阻实测值(Ω)、供电电压
- 物理层:隐性电平(V)、显性差分幅值(V)、位时间实测(µs)、采样点位置(%)、边沿过冲/振铃(V 或截图)
- 协议层:波特率、负载率(%)、错误帧类型与计数、每 ID 帧数、bus-off 次数与恢复时间
- 结论:定位到哪一层、哪个节点/哪段线缆,修复措施与复测结果
物理层截图配合协议层抓帧是完整证据链:本站 SocketCAN 篇 的 candump/cansend 可直接当分析仪用,从站实现篇 的负载率分析与此处公式一致,双波特率篇 的采样点计算可对照示波器实测。
9. 小结
CAN 总线测试的核心是分层定位:先用万用表量出 60Ω、再用示波器确认电平与波形、最后用分析仪看错误帧与负载率。记住三句口诀:阻抗不对先修终端,波形不对先查线缆与干扰,错误帧风暴先看物理层再怀疑协议。多数"时好时坏"最后都能在示波器上找到答案。