☰
J1939/J1587 CAN诊断排障:终端电阻、源地址与清故障实战
2026/11/3 5:38:09 网站建设 项目流程

简介:面向商用车与工程机械电控集成工程师、OEM 整车匹配人员及维修诊断技术人员的康明斯 Quantum 系列发动机技术文档,对应 AEB 15.43 工程公告,重点解决 J1587/J1939 数据链路接入、故障码读取与诊断功能落地的问题。内容围绕 Quantum 诊断体系展开,涵盖高级诊断、在线(Onboard)与离线(Offboard)诊断的适用场景,并逐一说明 J1587 与 J1939 的报文格式、传输速率、错误检测机制,以及 QSM11、QSX15 的 J1939 安装与线束连接要求;同时指明与电子特性、OEM 组件接口、安装推荐等关联公告的查阅顺序,便于按需延伸。压缩包共 1 个 PDF 文件,约 240KB,为 64 页英文原版工程公告,篇幅紧凑、便于随查随用。已有 3563 人学习下载,适合需要对照原文核对协议细节、梳理诊断流程或做集成方案评审的读者查阅。

1. J1939 一上电就报“无通讯”:先别换 ECM,八成是终端电阻和屏蔽层在打架

重型柴油机 J1939/J1587 通讯协议与诊断、CAN 通讯诊断与集成,最容易在整机厂首次上电时翻车:钥匙一拧,仪表报“CAN 无通讯”,PC 端服务工具连不上控制器,故障灯要么全亮两秒后熄灭,要么干脆不亮。现场第一反应常是换 ECM,血泪经验是先把 120Ω 终端电阻、屏蔽层接地和 250K 波特率量一遍。这类故障适合刚接手 CAN 集成的开发者,也适合被“偶发丢帧”折腾过的熟手。下面按读不到故障码、闪码对不上、清不掉故障、现场布线翻车几个场景拆开讲,每个场景都给可照做的定位顺序。

2. 读不到故障码:J1939 与 J1587 两路串行口先分清,再谈诊断

诊断工具连不上,不等于控制器坏了。很多现场把 J1939 和 J1587 当成同一路 CAN 来处理,结果工具能亮灯、却读不到任何故障码。该系列控制器设计了两路独立串行通信口:一路是 250 kbit/s 的 J1939,另一路是 9600 baud 的 J1587,二者在钥匙开关打开时都处于激活状态,但物理层、波特率、节点数和诊断报文完全不是一回事。先把这两路分清,后面的抓包、读码、清码才有意义。

2.1 两个独立串口:250K 与 9600 的物理层差异

J1939 这边,技术包里写得很明确:J1939-11 物理层使用带 drain 线的屏蔽双绞线,差分驱动,总线速率 250 kbit/s,最大总线长度 40 米,同时最多 30 个节点连接;J1587 基于 J1708,速率 9600 baud,最多 20 个节点连接。现场最常见的误用,是把 J1587 的两根线接到 CAN 口上,或者用 250K 的 CAN 接口去收 9600 的 J1587 数据,最后看到“总线关闭”“错误帧暴涨”“一帧都收不到”,就误判为 ECM 不响应。先确认接口类型和波特率,比换任何件都快。

项目J1939J1587
速率250 kbit/s9600 baud
物理层基础J1939-11,屏蔽双绞线带 drainJ1708 基础
最大节点数3020
最大总线长度40 米按 J1708 布线限制,现场以技术包拓扑为准
诊断口J1939-13 规定的 9 针诊断口可提供 J1939同一诊断口也提供 J1587
典型用途高速控制、信息共享、诊断、多路复用信息共享、诊断、专有通信
清故障相关DM1 当前故障、DM4 历史/快照、DM11 清活动故障PID 与故障码读取,按源地址和报文定义处理

先把 CAN 口按 250K 拉起,看看控制器本身有没有进入错误状态。下面这几条命令适合在 Linux 现场机上快速确认接口是否正常,不涉及任何诊断仪私有配置。

# 现场先把 CAN 口按 J1939 的 250 kbit/s 拉起 sudo ip link set can0 down sudo ip link set can0 type can bitrate 250000 restart-ms 100 sudo ip link set can0 up # 看状态、错误计数和是否进入 bus-off ip -details -statistics link show can0

bitrate 250000对应 J1939 的高速网络;restart-ms 100表示总线关闭后 100 毫秒尝试自动恢复,方便现场观察是不是持续 bus-off;ip -details -statistics link show can0重点看 state 是否ERROR-ACTIVE,以及 bus-error、error-warning、error-passive 是否在涨。如果接口一拉起就 bus-off,先回到线束和终端电阻,不要继续读码。注意:J1587 不是 CAN,不能用这条命令去“收 J1587”,它只能帮你确认 J1939 这一路有没有被正确配置。

2.2 用最小抓包脚本确认波特率、源地址和 PGN

接口状态正常,但仍然读不到目标控制器的故障码,下一步不是猜,而是看总线上到底有没有扩展帧、源地址是多少、PGN 是不是诊断报文。现场我一般会用 python-can 写一个最小抓包脚本,只做三件事:过滤扩展帧、解出源地址、按 J1939 的 PDU1/PDU2 规则还原 PGN。这个脚本不依赖诊断仪,能快速判断“总线是死的”还是“报文有、但源地址不对”。

import can def j1939_pgn(arb_id: int) -> int: # 29 位 J1939 标识符:优先级 26-28,DP 24,PF 16-23,PS 8-15,源地址 0-7 dp = (arb_id >> 24) & 0x01 pf = (arb_id >> 16) & 0xFF ps = (arb_id >> 8) & 0xFF if pf < 240: # PDU1:PS 是目标地址,PGN 不包含 PS return (dp << 16) | (pf << 8) # PDU2:PS 是组扩展,PGN 包含 PS return (dp << 16) | (pf << 8) | ps bus = can.Bus(interface="socketcan", channel="can0", bitrate=250000) for msg in bus: if not msg.is_extended_id: continue pgn = j1939_pgn(msg.arbitration_id) src = msg.arbitration_id & 0xFF print(f"PGN={pgn:06X} SRC={src:02X} DLC={msg.dlc} DATA={msg.data.hex(' ')}")

这段代码的channel="can0"要换成现场实际接口名;bitrate=250000必须与 J1939 一致;is_extended_id过滤掉标准帧,避免把无关 CAN 帧混进来;j1939_pgn()里按 PF 是否小于 240 区分 PDU1 和 PDU2,PDU1 的 PS 是目标地址,不能算进 PGN。运行后如果一帧扩展帧都没有,先查 CAN_H/CAN_L、终端电阻和控制器供电;如果有大量报文但没有目标源地址,查节点地址冲突、诊断口错线或控制器是否真的上电。这个脚本只做现场粗筛,真正清故障前还要按技术包里的报文表和源地址表核对。

2.3 9 针诊断口线序与“能上电但读不到”的常见错线

J1939-13 规定的 9 针诊断口会同时提供 J1939、J1587 以及第二路 CAN 网络的连接能力,现场最容易出问题的地方是“工具灯亮、就是读不到”。常见错线有三类:第一,CAN_H 和 CAN_L 接反,某些收发器在短距离下还能勉强通信,但一旦线长增加或节点变多就开始丢帧;第二,把屏蔽层当成信号地,或者屏蔽层两端都接地形成地环路,表现为加油门、开大灯、启停大负载时通信时好时坏;第三,诊断口取电导致地偏移,工具指示灯亮,但差分电平已经偏离,读码超时。解决顺序很简单:断电量两个 120Ω 终端电阻并联值是否接近 60Ω,按技术包拓扑图核对 9 针诊断口定义,确认屏蔽层和 drain 线处理方式,再单独给诊断工具供电复测。不要凭线色猜,线色在不同线束厂之间并不可靠。

3. 故障灯闪码对不上:闪码节奏、灯策略和故障快照的坑

闪码读出来是 244,故障码表里却查不到对应部件;或者明明只闪了一个码,清完故障第二天又出现。这类问题多半不是故障码表印错了,而是闪码节奏、灯策略和当前/历史状态混在一起看了。该系列控制器的在线诊断会在钥匙开关打开、机器运行过程中检测故障,故障激活时写入内存并记录发动机参数快照,同时按严重程度点亮警告灯、停机灯、维护灯或水油分离灯。读闪码之前,先确认自己进的是诊断模式,而不是在看上电自检或维护提醒。

3.1 闪码进入条件:钥匙 ON、发动机不转、踏板 0-100% 三次

技术包给出的进入条件很具体:钥匙开关打开,发动机不运转。使用诊断开关进入时,开关打开后 ECM 会自动闪出第一个故障码,诊断增量/减量开关用来向前或向后切换活动故障;使用油门踏板进入时,踏板要从 0 到 100% 循环三次,进入诊断模式后继续循环踏板可以向前切换活动故障。闪码本身是三位十进制,按百位、十位、个位分组闪,组与组之间有停顿,循环重复。比如故障码 244 记录为 2 次、4 次、4 次,故障码 112 记录为 1 次、1 次、2 次。现场翻车最多的情况,是发动机已经启动、踏板没踩到 100%、或者把组间长停顿也数成了一次闪。

def decode_flash(groups): # groups 是手工记录的三组连续闪灯次数,例如 [2, 4, 4] -> 244 if len(groups) != 3: raise ValueError("闪码应按百位、十位、个位记录三组") if any(n < 0 or n > 9 for n in groups): raise ValueError("每组只能是 0-9 次闪烁") return groups[0] * 100 + groups[1] * 10 + groups[2] print(decode_flash([2, 4, 4])) # 244 print(decode_flash([1, 1, 2])) # 112

这个函数只负责把人工记录的三组闪烁次数转成十进制故障码,不替你判断当前故障还是历史故障。groups必须按百位、十位、个位顺序填,组内连续闪、组间停顿不算数字;如果记录到 10 次以上,说明停顿判断错了,重新进诊断模式再读。现场最好两个人配合,一个人看灯,一个人按“组间停顿”分隔记录,读完后让闪码循环两遍再确认,避免把自检闪烁或维护灯闪烁混进故障码。

3.2 灯策略差异:警告灯、停机灯、维护灯/发动机保护灯、两灯策略

该系列控制器最多使用五个指示灯,其中维护灯和发动机保护灯在不同机型上二选一。警告灯是琥珀色,提示需要及时关注的操作员消息,也参与故障码闪出;停机灯是红色,提示需要立即处理的关键消息,同样参与闪码;等待启动灯表示进气预热正在进行;水油分离灯提示燃油里有水,需要放水;维护灯在上电时闪,可能是换机油提醒,运行时点亮也可能是低优先级故障;发动机保护灯在保护故障时点亮,部分机型可以通过布线把保护故障映射到红色停机灯,形成两灯策略。两灯策略只改故障灯布线,不改软件或校准,但现场如果没核对布线,就会把保护故障当成普通停机故障。

灯作用容易误判的点
警告灯重要操作员消息,参与闪码看到警告灯亮就只查闪码,忽略当前故障条件
停机灯关键消息,要求立即响应,参与闪码把保护故障映射过来的红灯当成普通停机故障
维护灯/发动机保护灯不同机型二选一,维护灯可能提示换油把上电时维护灯闪当成故障码
等待启动灯进气预热进行中冷启动时误判为故障灯
水油分离灯燃油含水只清码不排水,故障反复出现

看到红灯不要直接下结论,先按机型核对灯策略:是原生停机灯,还是保护灯通过布线映射到红灯;维护灯闪是上电换油提醒,还是运行时低优先级故障;水油分离灯亮时先排水再清码。技术包里提到,如果发动机保护灯信号还去控制其他功能,比如车辆推进电路,需要在线路里加二极管,这类改线如果没做,灯亮和实际保护动作可能对不上。

3.3 闪码读数脚本/记录表:把闪烁转成 DTC

闪码读出来后,不要只记一个数字。现场真正有用的是“故障码 + 灯类型 + 当前/历史 + 快照参数”。技术包里的故障检测会在故障激活时记录发动机参数快照,这些参数是后面复现问题的黑匣子。我的做法是手边放一张固定记录表,每读到一个码就填一行,清码前先拍照或抄下来,清码后路试复现,再对比快照里的转速、油温、油压、电压和负载。

时间灯类型三组闪烁故障码当前/历史快照关键参数清码后是否复现
上电后停机灯2/4/4244当前转速、油温、油压、电压路试 10 分钟复现
怠速警告灯1/1/2112历史转速、电压清码后未复现

记录时把“当前”和“历史”分开,当前故障说明条件仍在,历史故障可能是间歇性线束或接插件问题。清码后立刻复现的,不要反复清,先查故障条件;清码后跑一段时间才复现的,重点查线束走向、接插件锁止、屏蔽层和搭铁。故障码表要按机型、校准版本和年份匹配,同一串数字在不同版本表里可能指向不同部件,拿旧表查新控制器,最后只会把自己带进沟里。

4. J1939 报文能收但清不掉故障:DM4/DM11 与源地址不匹配

抓包能看到 DM1,诊断仪也能显示当前故障,但一按清故障就超时,或者清完立刻又跳出来。这个场景在整机厂联调时很常见,根因通常不在“清故障按钮坏了”,而在源地址、报文类型和总线负载。J1939 诊断报文不是广播一声“大家把故障都清掉”,清活动故障需要目标控制器认可源地址和报文内容;DM4 承载的是历史故障和冻结帧信息,清掉当前故障不等于历史记录消失;总线负载高时,诊断报文还会延迟甚至丢帧。

4.1 清故障不是广播:源地址、目标地址和 DM4 的关系

先分清三类报文:DM1 用来报当前活动故障,DM4 用来报历史故障和冻结帧,DM11 用来清活动故障。技术包在“通过数据链路清故障的支持消息和源地址”一节里专门强调了源地址,现场如果用一个不被目标控制器认可的源地址发清故障请求,表现就是发得出去、没有响应。常见做法是先抓 DM1,记下报文的源地址和目标地址,再看诊断工具或网关用的是哪个源地址;清故障时用匹配的源地址发 DM11,清完让钥匙开关循环一次,再读 DM1 确认是否真的清掉。清完立即复现的,说明当前故障条件还在,不要把它当成清码失败。

报文PGN(十进制)用途现场注意
DM165226当前活动故障先看它判断故障是否仍在
DM465229历史故障/冻结帧清活动故障不等于清历史记录
DM1165235清活动故障源地址要匹配,清后钥匙循环再读

注意:清故障前先确认 DM1 是否仍为活动状态。当前条件没消失时,清码成功也会马上复现,反复清只会掩盖根因。

4.2 PGN 过滤:先看 DM1 当前故障,再看 DM4 历史

现场抓包不要把所有报文都打出来,250K 总线上诊断报文和高频广播混在一起,肉眼很容易看漏。下面这段脚本只保留 DM1 和 DM4,并把源地址一起打出来,方便对照技术包里的源地址表。

import can DM1 = 0xFECA # 65226,当前活动故障 DM4 = 0xFECD # 65229,历史故障/冻结帧 def j1939_pgn(arb_id: int) -> int: dp = (arb_id >> 24) & 0x01 pf = (arb_id >> 16) & 0xFF ps = (arb_id >> 8) & 0xFF if pf < 240: return (dp << 16) | (pf << 8) return (dp << 16) | (pf << 8) | ps bus = can.Bus(interface="socketcan", channel="can0", bitrate=250000) for msg in bus: if not msg.is_extended_id: continue pgn = j1939_pgn(msg.arbitration_id) if pgn in (DM1, DM4): src = msg.arbitration_id & 0xFF print(f"PGN={pgn:06X} SRC={src:02X} DATA={msg.data.hex(' ')}")

DM1和DM4用十六进制常量表示,过滤时只保留这两类诊断报文;j1939_pgn()仍然按 PDU1/PDU2 还原 PGN,避免把目标地址误算进 PGN;SRC是源地址,必须和清故障时使用的源地址对照。运行后如果只看到 DM1、没有 DM4,说明该控制器当前没有历史故障或冻结帧,不代表清码失败;如果 DM1 一直有、DM11 发出去没反应,重点查源地址和总线负载,不要先怀疑故障码表。

4.3 网络负载与多路复用:250K 总线被塞满时的表现

J1939 是 250 kbit/s 的高速网络,最大 30 个节点,技术包里专门有网络利用率章节,还区分了非多路复用和多路复用报文。现场加节点、加高频广播、加多路复用诊断消息之后,总线负载上来,表现不一定是完全断线,而是诊断报文延迟、清故障超时、DM1 偶尔丢一帧。遇到这种“时好时坏”,先抓 10 秒统计帧率和错误计数,再看是否有大量非诊断报文占着总线;如果是多路复用报文,核对技术包里的复用表和发送周期,别把高频广播当普通状态量一直发。

现象可能原因验证方式
DM1 偶尔丢一帧总线负载高或错误帧干扰看 error-warning/error-passive 是否增长
清故障超时源地址不匹配或总线忙抓 DM11 请求和响应,核对源地址
加节点后间歇离线节点数超限、支线过长、终端位置不对统计节点数,断电量 60Ω,查支线
多路复用参数跳变复用表或发送周期不匹配对照技术包网络利用率章节

5. 集成现场最容易翻车的五件事:避坑清单

这一章不按报文讲,按现场踩过的坑讲。每个坑都按“现象、原因、解决”记录,方便下次上机前逐条排除。很多问题不是控制器固件造成的,而是线束、接地、节点数、诊断口取电和故障码表版本这些看起来不起眼的地方。

5.1 终端电阻量到 60Ω 就放心:带电测量和支线过长会骗你

现象:断电量两个 120Ω 终端电阻并联值接近 60Ω,上电后还是偶发丢帧,诊断仪隔几分钟掉一次。原因:60Ω 只说明直流终端大致正常,不能说明支线长度、节点数、屏蔽层处理和终端电阻位置都正确;带电测量还会把收发器内部电路并联进来,读数看着对,实际 topology 已经不对。解决:断电测量,确认两个终端电阻分别装在总线两端,统计节点数不超过 30,总线长度不超过 40 米,支线尽量短;上电后用接口错误计数看是否持续增长,而不是只看能不能收一帧。

5.2 屏蔽层多点接地:drain 线不是随便接

现象:怠速通信正常,一加油门或开大灯就开始丢帧,故障码时有时无。原因:屏蔽层两端接地形成地环路,或者把屏蔽层当信号地、当电源地使用,drain 线处理不符合技术包拓扑,干扰直接耦合到差分对上。解决:按技术包里的典型拓扑核对屏蔽层和 drain 线,确认搭铁点干净、无漆、无虚接;不要用屏蔽层替代地线;诊断口和控制器地之间的压差要量,超过合理范围先查搭铁和供电,不要继续清码。

5.3 节点数和支线长度:30 节点不是随便挂

现象:原来网络正常,增加一个节点后整车网络间歇性离线,诊断仪偶尔能连、偶尔超时。原因:J1939 最多 30 个节点、最大 40 米,J1587 最多 20 个节点;节点数超限、支线过长、终端电阻不在两端,都会让信号反射和边沿变差。解决:画一张实际拓扑图,统计每个节点的支线长度和终端位置;超过节点数就加网关分流,不要硬挂;支线过长就改线束走向;改完后用错误计数和 DM1 连续性验证,不要只测静态电阻。

5.4 诊断口取电与地偏移:工具能亮但读不到

现象:诊断工具插上后指示灯亮,软件一直提示连接超时,换一个工具还是读不到。原因:诊断口取电导致地偏移,或者诊断口地线虚接、保险接触不良,工具电源灯亮但差分接收已经失效。解决:先单独给诊断工具供电复测,量诊断口地与控制器地之间的压差,检查保险和接插件锁止;按 J1939-13 的 9 针定义核对 J1939、J1587 和第二路 CAN 的引脚,不要凭线色猜。工具能亮不代表物理层正常,能收到一帧也不代表能稳定清码。

5.5 故障码表版本与机型不匹配:同一个码两种解释

现象:闪码读出来是 244,查表指向的部件和实际症状对不上;清码后复现,换一张表又变成另一种解释。原因:故障码表按机型、年份和校准版本区分,技术包里的故障码表只是对应范围内的版本;现场拿旧表查新控制器,或者把历史故障当当前故障,都会得出错误结论。解决:用机型铭牌和校准信息匹配故障码表,先读 DM

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询