news 2026/9/25 1:46:05

ISO 11898与SAE J1939协议分层解析:CAN总线通信核心区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ISO 11898与SAE J1939协议分层解析:CAN总线通信核心区别

1. 从一次总线调试翻车说起:为什么这两个协议总被搞混

刚入行那会儿,我接手过一个车载节点的通信调试任务。硬件同事把CAN收发器焊好,线束接上,终端电阻也量了,120欧姆没问题。上电之后用分析仪抓包,总线上确实有报文在跑,ID、DLC、数据段都看得见。但问题是,我按手头那份"CAN协议说明"去解析数据,怎么都对不上——发动机转速的字节位置跟文档里写的完全不一样,车速信号更是找不到。

折腾了大半天,请教了一位老师傅,他看了一眼我手里的文档就笑了:"你看的是ISO 11898,但这条总线上跑的是J1939。物理层一样,上层完全两码事。"

这句话点醒了我。ISO 11898和SAE J1939经常被新手混为一谈,根本原因在于它们确实共享同一套物理层和部分数据链路层基础,但在协议栈里所处的位置、解决的问题、定义的规则完全不在一个层面上。打个比方,ISO 11898像是规定了"公路怎么修、车道多宽、限速多少",而J1939则是在这条公路上进一步规定了"货车拉什么货、货物怎么贴标签、司机之间怎么对话"。路是同一条路,但跑在上面的规矩截然不同。

这篇内容就是想把这件事彻底讲清楚。不管你是刚接触车载网络的嵌入式新手,还是从其他总线(比如Modbus、SPI、IIC)转过来做CAN通信的工程师,只要花几分钟把下面这几个层面的区别理顺,以后拿到任何一份CAN相关文档,你都能快速判断它讲的是哪一层的东西,不至于像我当年那样对着错误的参考文档死磕。

核心关键词先摆出来:CAN总线、ISO 11898、SAE J1939、协议分层、ECU通信。这几个词贯穿全文,搞懂它们之间的关系,基本就抓住了车载CAN通信的主干。

2. 协议栈视角:ISO 11898和J1939根本不在一个楼层

2.1 用"盖楼"类比理解协议分层

要讲清楚这两个协议的区别,最有效的切入角度是协议栈分层。我习惯用盖楼来类比:

  • 地基和承重墙:物理层,负责电信号怎么传、线缆什么规格、电平怎么定义。ISO 11898主要就在这一层以及数据链路层的一部分。
  • 楼层和房间隔断:数据链路层,负责帧怎么组、仲裁怎么做、错误怎么检测。ISO 11898-1定义了CAN的帧格式和仲裁机制。
  • 房间里的家具和规矩:应用层,负责数据代表什么含义、怎么打包、怎么寻址。SAE J1939主要在这一层,同时它自己也定义了一套网络层和传输层规则。

所以你看,ISO 11898是"楼"本身的标准,J1939是"楼里怎么办公"的标准。一栋楼可以只盖好框架不装修(只用ISO 11898),也可以按J1939的规矩精装修(跑J1939协议)。这就是为什么同一条CAN总线上,物理层测量结果一样,但上层解析规则可以完全不同。

2.2 ISO 11898到底规定了什么

ISO 11898这个标准其实是一个系列,常见的有几个部分:

标准编号覆盖内容通俗理解
ISO 11898-1数据链路层与物理信令CAN帧格式、仲裁、错误处理
ISO 11898-2高速物理介质连接高速CAN收发器电气特性
ISO 11898-3低速容错物理层低速CAN,容错能力更强

新手最常接触的是ISO 11898-2,也就是高速CAN的物理层标准。它规定了:

  • 差分信号传输,CAN_H和CAN_L两根线
  • 显性位和隐性位的电平定义
  • 终端电阻120欧姆(两端各一个)
  • 最高速率1Mbps(经典CAN)
  • 总线拓扑为线性总线,节点挂在主干上

注意:很多人以为ISO 11898就是"CAN协议"的全部,其实它只管到数据链路层。你抓到一个CAN帧,能看懂它是标准帧还是扩展帧、ID是多少、数据几个字节,这是ISO 11898-1的功劳。但数据段里每个字节什么意思,ISO 11898不管。

2.3 J1939在ISO 11898之上又加了什么

SAE J1939是建立在CAN基础之上的应用层协议,主要面向商用车、重型车辆、工程机械等领域。它复用了ISO 11898定义的物理层和数据链路层,然后往上叠了好几层自己的规则:

  • 网络层:定义了29位扩展ID的分配方式,把ID拆成优先级、PGN、源地址等字段
  • 传输层:定义了多包传输机制(TP.CM和TP.DT),解决CAN单帧最多8字节的限制
  • 应用层:定义了各种参数组(PGN)和可疑参数(SPN),规定了每个参数怎么解析

换句话说,J1939把CAN的29位ID从"一个标识符"变成了"一套寻址系统"。这是理解J1939最关键的一步。在ISO 11898层面,ID就是一个用于仲裁和过滤的编号;在J1939层面,这29位被拆解得明明白白,每一位都有含义。

2.4 一张表看清两者的层级关系

对比维度ISO 11898SAE J1939
协议栈位置物理层+数据链路层应用层(含网络层、传输层)
核心职责电信号传输、帧格式、仲裁数据含义、寻址、多包传输
ID使用方式标识符,用于仲裁和过滤29位拆分为优先级/PGN/源地址
数据段含义不定义,8字节裸数据按PGN定义每个字节含义
典型速率最高1Mbps通常250kbps或500kbps
终端电阻120欧姆沿用ISO 11898,同样120欧姆

这张表建议新手存下来。以后拿到任何CAN相关材料,先问一句:它讲的是左边这列还是右边这列?答案立刻就清楚了。

3. 29位ID的拆解:J1939最核心的那把钥匙

3.1 为什么J1939要用29位扩展帧

经典CAN有11位标准帧和29位扩展帧两种。11位ID最多2048个标识符,对于简单系统够用,但对于一辆重型卡车动辄几十上百个ECU、每个ECU要发多种参数的场景,11位根本不够分。

J1939选择了29位扩展帧,并且把这29位做了极其精细的划分。这是J1939区别于"裸CAN"最本质的特征。如果你只学ISO 11898,你看到的是一个29位数字;如果你学了J1939,你看到的是优先级、参数组编号、源地址三个有意义的字段。

3.2 29位到底怎么分

J1939的29位ID结构如下:

位段名称含义
28-26(3位)Priority优先级,0最高,7最低
25(1位)Reserved保留位,通常为0
24(1位)Data Page数据页,用于扩展PGN范围
23-16(8位)PDU FormatPDU格式,决定PDU1还是PDU2
15-8(8位)PDU SpecificPDU特定字段,含义随PF变化
7-0(8位)Source Address源地址,标识发送节点

这里有个关键分水岭:PDU Format(PF)的值决定了PDU Specific(PS)字段的含义。

  • 当PF < 240时,是PDU1格式,PS字段表示目标地址(Destination Address),也就是点对点通信
  • 当PF >= 240时,是PDU2格式,PS字段表示组扩展(Group Extension),也就是广播通信

这个规则我第一次看的时候也觉得绕,后来用一句话记住了:PF小于240是"我跟你说话",PF大于等于240是"我向大家广播"。

3.3 PGN是怎么算出来的

PGN(Parameter Group Number)是J1939里表示"一组参数"的编号。它的计算方式跟PDU格式有关:

  • PDU1格式(PF < 240):PGN = Data Page + PF + 00(PS固定为0)
  • PDU2格式(PF >= 240):PGN = Data Page + PF + PS

举个例子,发动机转速的PGN是61444(0xF004)。拆开看:

  • PF = 0xF0 = 240,属于PDU2
  • PS = 0x04
  • Data Page = 0
  • PGN = 0 + 0xF0 + 0x04 = 0xF004 = 61444

再比如请求PGN(Request)是59904(0xEA00):

  • PF = 0xEA = 234,小于240,属于PDU1
  • PS = 目标地址
  • PGN = 0 + 0xEA + 0x00 = 0xEA00 = 59904

提示:算PGN的时候,PDU1格式下PS要当作0来处理,这是新手最容易算错的地方。我第一次手算PGN就栽在这里,把目标地址也加进去了,结果怎么都对不上。

3.4 源地址和地址声明

J1939里每个ECU都有一个源地址(Source Address),范围0到253。其中:

  • 0到127:常用固定地址,比如发动机ECU通常是0,制动ECU通常是11
  • 128到247:动态分配地址
  • 248到253:特殊用途
  • 254:空地址(Null Address)
  • 255:全局地址(Global Address),广播时用

地址不是随便设的,J1939有一套地址声明(Address Claim)机制。ECU上电后会发一个地址声明报文(PGN 60928),如果发现地址冲突,会通过优先级仲裁决定谁保留、谁换地址。这套机制保证了即插即用的网络管理能力,也是J1939比裸CAN高级的地方。

3.5 一个实际抓包例子

假设你在总线上抓到一帧:

ID: 0x18F00400 Data: FF FF 7D 00 FF FF FF FF

按J1939拆解:

  • 0x18F00400 = 二进制 0001 1000 1111 0000 0000 0100 0000 0000
  • 优先级 = 110 = 6
  • 保留位 = 0
  • 数据页 = 0
  • PF = 0xF0 = 240
  • PS = 0x04
  • 源地址 = 0x00 = 0(发动机ECU)

PGN = 0xF004 = 61444,查J1939标准可知这是"电子发动机控制器1"(EEC1)。数据段前两个字节FF FF是发动机扭矩相关,第三、四字节7D 00按小端解析是0x007D = 125,对应发动机转速。J1939里转速的分辨率是0.125 rpm/bit,所以实际转速 = 125 × 0.125 = 15.625 rpm?不对,这里要再乘一个系数,实际转速计算是 (0x007D) × 0.125 = 15.625,但标准里EEC1的转速字节是第4、5字节,且分辨率是0.125 rpm/bit,所以125 × 0.125 = 15.625 rpm显然不对,说明我取的字节位置需要再核对。

这个例子说明一个重点:光会拆ID还不够,还得会查PGN对应的SPN定义,知道每个字节的位置、分辨率、偏移量。这就是J1939应用层的核心工作。

4. 物理层和终端电阻:两者共享但常被误解的部分

4.1 终端电阻到底该接几个、接在哪

CAN总线的终端电阻是新手最容易出问题的地方。ISO 11898-2规定,高速CAN总线两端各需要一个120欧姆的终端电阻,总共两个,并联后总线静态电阻约60欧姆。

我见过太多现场问题出在这里:

  • 有的节点板子上自带了120欧姆,结果一条总线上接了五六个,并联后电阻低到20多欧姆,通信直接瘫
  • 有的整条总线一个终端电阻都没有,短距离低速勉强能跑,一上速度就丢帧
  • 有的只在主机端接了一个,以为"有一个就行"

注意:终端电阻的作用是消除信号反射,匹配总线特性阻抗。CAN总线特性阻抗约120欧姆,所以两端各接一个120欧姆,让信号到达末端时被吸收而不是反射回来。接多了相当于阻抗不匹配,接少了反射严重,两种情况都会导致通信异常。

正确的做法是:整条总线只有最远的两个物理端点各接一个120欧姆,中间节点一律不接。如果你用的是成品线束,通常线束两端已经集成好了;如果是自己搭的测试台,一定要确认清楚每个节点的电阻配置。

4.2 波特率和线长的关系

ISO 11898-2对波特率和总线长度的关系有明确建议:

波特率最大总线长度
1 Mbps40米
500 kbps100米
250 kbps250米
125 kbps500米
50 kbps1000米

这个表背后的逻辑是:波特率越高,位时间越短,信号在总线上的传播延迟占比就越大,允许的总线长度就越短。信号在铜线里的传播速度大约是光速的2/3,也就是每米约5纳秒。1Mbps时一个位时间是1微秒,信号跑一个来回的时间必须远小于位时间,否则采样点会错位。

J1939常用的250kbps和500kbps,对应总线长度250米和100米,覆盖了大部分商用车和工程机械的场景。这也是为什么J1939没有选1Mbps——车太长,1Mbps跑不了那么远。

4.3 采样点设置:容易被忽略的细节

CAN的位时间分成几个段:同步段、传播段、相位缓冲段1、相位缓冲段2。采样点就在相位缓冲段1和2之间。ISO 11898建议采样点在位时间的75%到87.5%之间。

这个参数在配置CAN控制器的时候要设置。如果总线上所有节点的采样点不一致,通信距离一长就容易出错。我遇到过一批节点,有的用75%,有的用87.5%,短距离测试没问题,装车后跑起来就间歇性丢帧,查了好久才发现是采样点不统一。

提示:J1939对采样点有推荐值,通常建议在87.5%左右。配置的时候尽量让所有节点保持一致,尤其是不同厂商的ECU混用的时候,这一项要提前确认。

4.4 共模电感和隔离:工业场景的加分项

在实验室里跑CAN,不接共模电感、不做隔离,通常也能通。但到了工业现场或者车载环境,电磁干扰严重,地电位差大,这时候就需要:

  • 共模电感:抑制共模干扰,提高抗扰度
  • 隔离收发器:把CAN总线侧和MCU侧电气隔离,防止地环路和浪涌损坏

这些不是ISO 11898强制要求的,但属于工程实践中的常规做法。J1939的应用场景(商用车、工程机械)环境恶劣,所以实际产品里几乎都会加隔离。

5. 多包传输:J1939解决8字节限制的独门方案

5.1 为什么需要多包传输

CAN单帧最多8字节数据,这是ISO 11898-1定死的。但J1939应用层很多参数组远超8字节,比如故障码列表、软件版本信息、标定数据,动辄几十上百字节。怎么办?

J1939的传输层定义了多包传输机制,用两个专门的PGN来协调:

  • TP.CM(Transport Protocol Connection Management):PGN 60416,负责协商传输
  • TP.DT(Transport Protocol Data Transfer):PGN 60160,负责实际数据传输

5.2 多包传输的完整流程

以发送一个长报文为例,流程是这样的:

  1. 发送方发TP.CM.BAM或TP.CM.RTS:BAM是广播方式,RTS是点对点方式。报文里包含总字节数、总包数、目标PGN
  2. 接收方回应TP.CM.CTS(点对点方式):告诉发送方可以开始发,以及每次发几包
  3. 发送方发TP.DT:每包7字节有效数据,第1字节是包序号
  4. 接收方收齐后组包:按序号拼接,还原完整数据

BAM方式不需要接收方回应,直接连发,适合广播;RTS/CTS方式有流控,适合点对点可靠传输。

5.3 多包传输的实操坑

我在实际项目里踩过几个多包传输的坑:

  • 包序号从1开始,不是0:TP.DT的第一个字节是序号,从1递增。我一开始按0开始写,接收方组包全乱
  • 最后一包不足7字节要填充:J1939规定用0xFF填充,接收方按总字节数截断
  • BAM传输间隔有要求:包与包之间最小间隔50ms到200ms,发太快接收方处理不过来
  • 超时处理:点对点传输如果CTS没来,发送方要超时重试,不能死等

注意:多包传输是J1939应用层的一部分,ISO 11898完全不涉及。如果你只用ISO 11898,遇到超过8字节的数据就得自己想办法拆包组包,而J1939已经把这套机制标准化了。

5.4 和CAN FD的区别

这里顺带提一句CAN FD。CAN FD是ISO 11898-1的后续演进,数据段最多64字节,速率也可以更高。但J1939目前主流还是基于经典CAN,虽然有J1939-22(基于CAN FD的新版),但存量市场里经典CAN的J1939还是绝对主力。

所以新手不要一上来就想着用CAN FD绕过8字节限制,先搞清楚J1939的多包传输机制,这是理解现有车载网络的基础。

6. 实际项目中怎么快速判断该用哪套规则

6.1 看文档标题和来源

拿到一份CAN相关文档,先看标题:

  • 标题里有"ISO 11898"、"物理层"、"数据链路层"、"收发器"、"终端电阻"——这是底层标准
  • 标题里有"J1939"、"PGN"、"SPN"、"商用车"、"重型车辆"——这是应用层协议

6.2 看ID是11位还是29位

抓包的时候看ID:

  • 11位标准帧:可能是ISO 11898裸CAN,也可能是其他应用层协议(如CANopen)
  • 29位扩展帧:大概率是J1939,但也要确认,因为CANopen也用29位

进一步确认:把29位ID按J1939规则拆,如果PF、PS、SA字段拆出来合理(PF值常见、SA在0-253范围),基本就是J1939。

6.3 看数据段是否有规律

J1939的数据段通常有明确的字节定义,比如:

  • 前两字节常是扭矩或转速
  • 有分辨率(如0.125 rpm/bit)和偏移量
  • 多字节参数通常小端排列

裸CAN的数据段往往没有统一规律,取决于具体项目自定义。

6.4 一个实用的判断流程

判断步骤观察点结论
第一步文档是否提到PGN/SPN是→J1939
第二步ID是11位还是29位29位→倾向J1939
第三步29位ID拆解是否合理PF/PS/SA合理→J1939
第四步数据段是否有标准分辨率有→J1939
第五步是否有多包传输有TP.CM/TP.DT→J1939

这套流程走下来,基本不会判断错。

6.5 常见误区澄清

最后澄清几个新手常犯的误区:

  • 误区一:ISO 11898就是CAN协议的全部。实际上它只管物理层和数据链路层,应用层是空的
  • 误区二:J1939是另一种总线。不是,J1939跑在CAN总线上,物理层完全一样
  • 误区三:学了J1939就不用学ISO 11898。不行,物理层出问题的时候,J1939知识帮不了你,还得回到ISO 11898查终端电阻、查电平、查采样点
  • 误区四:J1939只用于商用车。虽然它起源于商用车,但现在工程机械、农业机械、船舶、发电机组都在用,覆盖面很广

7. 给新手的上手路径建议

如果你刚接触这块,我建议按这个顺序上手:

  1. 先搞懂ISO 11898-2的物理层:终端电阻、电平、波特率、线长,这些是基础中的基础,出问题最先查这里
  2. 再学ISO 11898-1的帧格式:标准帧、扩展帧、仲裁、错误帧,能看懂抓包数据
  3. 然后学J1939的29位ID拆解:优先级、PGN、SA,这是J1939的钥匙
  4. 接着学常用PGN和SPN:先掌握发动机、车速、制动这几个高频的
  5. 最后学多包传输和地址声明:这是进阶内容,实际项目遇到再深入

工具方面,一台CAN分析仪(支持J1939解析的更好)、一个示波器(看波形和电平)、一个万用表(量终端电阻)基本就够了。软件上,很多分析仪自带J1939数据库,能直接显示PGN名称和参数值,省去手动查表的麻烦。

我在实际带新人的时候发现,最容易卡住的地方不是协议本身多难,而是没有建立起"分层"的思维习惯。一旦你养成拿到问题先问"这是哪一层的事"的习惯,ISO 11898和J1939的区别就再也不会搞混了。物理层的问题查ISO 11898,数据含义的问题查J1939,各归各管,排查效率会高很多。

最后分享一个我自己的小技巧:在项目里建一个自己的PGN速查表,把常用PGN、对应SPN、字节位置、分辨率、偏移量都整理进去,用的时候直接查,比翻标准文档快得多。这个表随着项目积累会越来越值钱,是实打实的经验资产。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 1:45:55

STM32开发环境搭建全攻略:CubeMX与Keil5安装配置避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:45:42

眼动模块进阶开发:如何扩展新Blockly积木块与自定义图片ID

眼动模块进阶开发&#xff1a;如何扩展新Blockly积木块与自定义图片ID 【免费下载链接】eye-tracking-module 源师兄扩展项目: 眼动模块 | 由源师兄组织创建 项目地址: https://gitcode.com/yuanshixiong/eye-tracking-module 源师兄眼动模块是一个通过串口控制圆形屏幕…

作者头像 李华
网站建设 2026/9/25 1:45:17

IDM、Fabless、Foundry:芯片三种商业模式的核心分野与选型逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:44:54

Neo4j 5.26.0 Windows安装配置与数据导入实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 1:44:11

TX12刷EdgeTX 2.7.1与ExpressLRS高频头配置全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华