谁都能看懂的J1939协议解读

        近期学习了一下J1939的协议, 本以为凭借着对CAN通讯扎实的知识基础学习这个应是轻松拿捏,但是没想到零零散散也用了2-3天的时间才把原理和协议大致看懂. 因为手头上还没有现成的工具和环境,因此非常遗憾这里没有包括实践的过程,后面有时间我再补充一些实际的数据流把.

        老实说这个过程有点超出我的预期, 虽然对于这个知识在互联网上并不缺乏公开的分享,但是实际的学习过程还是有点困扰.因为大部分的资料,文章都是围绕着协议本身进行解释,没有站在应用者的视角展示一个完整的场景.导致我看完了很多文章之后始终有两个问题不能理解, 1. 这个协议怎么使用?发出来的数据流是什么?通过融合多种教材以及其他辅助手段,我逐渐在理论层面理解了上面的问题,接下来我就把这些经过加工的内容分享给大家.

Feature

  • J1939标准协议建立在CAN(控制器区域网络,ISO11898)上
  • 物理层(J1939/11)
  • 应用层(J1939/71和J1939/73)
  • 报文格式及使用方法(J1939/21)
  • J1939协议传送速度稳定在250kbps
  • 屏蔽双绞线,总线阻抗为120Ω。
  • J1939使用CAN 2.0B协议中定义的29位标识符
  • J1939 中有两种通信方式,分别是点对点和广播通信
  • 1939共定义了五种报文类型,分别为命令、请求、广播/响应、确认和组功能。

FrameStructure

📌P(Priority),优先级字段,用于在仲裁过程中控制报文优先级。

📌EDP(Extended Data Page),为扩展数据页位,在J1939中固定取值为0。

📌DP(Data Page),数据页位,可用来扩展参数组的数量。

📌PF(PDU Format),为PDU格式字段,通过不同的取值来确定参数组编号(Parameter Group Number, PGN)是按照PDU1格式还是PDU2格式。

📌PS(PDU Specific),特定协议数据单元字段,

  1. 当PF的值为0-239时PS表示目标地址(PDU1格式),
  1. 当PF的值为240-255时PS字段表示组扩展(PDU2格式),且报文只能广播。

📌SA(Source Address),源地址字段,整个网络中SA的值必须是唯一的。

📌 Data Field,数据场,对于Classic CAN来说是8个字节,而CANFD则最多有64个字节数据。如果需要传输更多的数据,则需要借助J1939的传输协议。

PGN

PGN(Parameter Group Number)是 J1939 应用层用来标识一组参数或报文类型的编号。它决定了节点该如何解析载荷,反映了报文的功能和结构。这部分是J1939中比较重要的概念.

下面提供一些这结构的示意图,作为参考(借用Vector手册中的图片).


 

J1939 扩展帧 ID(29 位)从高到低依次为

  • Priority(3 位)
  • Reserve R(1 位)
  • Data Page DP(1 位)
  • PDU Format PF(8 位)
  • PDU1 点对点 <240 即0xF0
  • PDU2 广播 >=240 即0xF0
  • PDU Specific PS(8 位)
  • Source Address SA(8 位)
  • ID 字段里的 SA(Source Address)永远是“发送该帧的节点地址”

PGN 由 DP、PF 和 PS(或 0x00)三部分组成,共 18 位

在 J1939 的 PGN 计算规则里,只有当 PDU Format(PF)≥ 240(PDU2/广播)时,才把 PS 字段当作 Group Extension (GE) 加入 PGN。

因为在 CM 控制报文里 PF = 0xEC (236 < 240),属于 PDU1 格式:

  • PS 被当作目标地址,不作 PGN 一部分
  • PGN 的 GE(即 PS 低字节)强制置 0

SPN

  • J1939-DA以表格形式列出了所有指定的SPN,SPN是由SAE 指定的数字。
  • PGN的描述中指定了SPN在PGN内的起始位置
  • J1939标准将SPN描述定义为 SLOT (Scaling, Limit, Offset and Transfer Function, 比例、界限、偏移和转换函数)
  • 多帧没有SPN字段的概念,之后再完成多帧发送后才能从全部的Payload种提取出那些事SPN

  • 如果SPN的所有位均为1,则SPN的状态为SNA
  • 11 – SNA (Signal Not Available, 信号不可用)。

SPN PDU1 报文中的体现

  • CAN ID(PDU1)里没有 SPN 字段PDU1 的 29 位扩展 ID 只包含
  • Priority/R/DP/PF(报文类型)
  • PS(目标节点地址)
  • SA(源节点地址)

这些位均与节点寻址和 PGN(高两字节)有关,不涉及任何 SPN

SPN 概念在 PayLoad

SPN (Suspect Parameter Number)是在完成会话层(TP.CM/TP.DT)重组或者单帧载荷到达后,才根据PGN 定义去映射:

  • 确定该 PGN(如 0xF004 “发动机转速”)对应哪些 SPN
  • 在数据字段里定位各 SPN 的起始字节/位
  • 按照 SPN 的比例因子 & 偏移量换算工程值

举例:发动机转速 SPN190 位于 PDU2 广播回复的 Byte1–Byte2

Plain Text
Data = [40 1F FF FF FF FF FF FF]
     ↳
原始值 0x1F40 = 8000
     ↳ 转速 = 8000 × 0.125 rpm/bit = 1000 rpm 

  • ID 格式(PDU1/PDU2)从不携带 SPN 信息,SPN 只在解析了完整Payload后,按 J1939/71 表格映射, SPN 是根据某个 PGN 的定义去解析它的 Paylaod, 换句话说:PGN 告诉你——“去这段Payload里,用 J1939/71 的那张表找 SPN”.

单帧

假设 有一帧报文是节点 0x17 向节点 0xCA 发起点对点 Request,索要 PGN 0x00F004(发动机转速) – 上层接收器看到此帧后,会回复一条 PDU2 广播或 PDU1 点对点的发动机转速报文, 下面我以这个完整的数据流来解释下PDU1和PDU2的两种情况.

Rqst:08│18 EA CA 17│04 F0 00 FF FF FF FF FF

PDU1 点对点通讯

  • PDU Format 1 specific 
  • 含有指定目标地址
  •  PF < 0xF0 (240)
  • 点对点通信
  • PS 为指定接收节点地址

节点 0x17 向节点 0xCA 发起点对点 Request

08│18 EA CA 17│04 F0 00 FF FF FF FF FF

“08”  DLC(Data Length Code),8 字节

“18 EA CA 17” —— 29 位扩展 ID (Priority=6, R=0, DP=0, PF=0xEA, PS=0xCA, SA=0x17)

“04 F0 00 FF FF FF FF FF” —— Data[1..8]

CAN ID (29bit):0x18EACA17

二进制拆解(29 位扩展帧)

110 0 0 11101010 11001010 00010111

  • Priority (28–26): 110₂ = 6
  • R        (25)   : 0
  • DP       (24)   : 0
  • PF       (23–16): 11101010₂ = 0xEA (234 < 240)
  • PF < 0xF0 → PDU1(点对点报文)
  • PS       (15–8) : 11001010₂ = 0xCA (目标地址 DA=202)
  • DA = PS = 0xCA
  • SA       (7–0)  : 00010111₂ = 0x17 (源地址 SA=23)
  • PGN = DP << 16 + PF << 8 + 0x00 = 0xEA00

Payload (8 bytes

此示例为“请求发动机转速”(PGN=0x00F004)的 Request 报文:

点击图片可查看完整电子表格

代码

Plain Text
Data = [04 F0 00 FF FF FF FF FF]

  • Byte1–3:LSB→MSB 拼成 0x00F004,表示“发动机转速”参数组
  • Byte4–8:0xFF 填充,表示无效/保留

综上所述, 一帧PDU1的单帧请求就解析完了. 假设我们通过PDU1进行响应,

节点 0xCA PDU1 格式向节点 0x17 单点回复发动机转速(1000 rpm

08│18 EF 17 CA│40 1F FF FF FF FF FF FF

"08" DLC = 8(8 字节数据区)

"18 EF 17 CA" 29 位扩展 ID = 0x18F017CA

  • Priority (28–26) = 110₂ = 6
  • R        (25)   = 0
  • DP       (24)   = 0
  • PF (23–16)      = 11101111₂ = 0xEF (<0xF0 PDU1)
  • PS (15–8)       = 00010111₂ = 0x17 (目标地址 DA)
  • SA (7–0)        = 11001010₂ = 0xCA (源地址)
  • 二进制字段:

Data[1..8] = 40 1F FF FF FF FF FF FF

  • Byte1–2 = 0x1F40 = 8000 → 8000 × 0.125 rpm/bit = 1000 rpm
  • Byte3–8 = 0xFF 填充(无意义/保留)

这里为什么0x1F40 是1000rpm的物理意义,这部分内容是J1939 SPN定义的这个概念我们会在下一个章节介绍.

 J1939 的 PDU1(点对点)通信中:

  • CAN ID 中的 SA(Source Address)永远标识“本帧发送者”
  • PS(PDU1 下的 PDU Specific)永远标识“本帧目标者”

因此,若节点 A(地址 0x17)向节点 B(地址 0xCA)发起请求:

代码

Plain Text
请求帧 ID = …  PF<0xF0 → PDU1  …  PS = 0xCA  SA = 0x17

回复帧要让 B → A,那么就得把“我是谁 (SA)”和“我要发给谁 (PS)”互换:

代码

Plain Text
回复帧 ID = …  PF<0xF0 → PDU1  …  PS = 0x

PDU2 广播通讯

节点 0xCA PDU2 格式向节点 0x17 单点回复发动机转速(1000 rpm

08│18 F0 04 CA│40 1F FF FF FF FF FF FF

“08”   DLC = 8(8 字节数据区)

“18 F0 04 CA” 29 位扩展 ID = 0x18F004CA

  • Priority (28–26) = 110₂ = 6
  • R        (25)   = 0
  • DP       (24)   = 0
  • PF (23–16)      = 11110000₂ = 0xF0 (≥0xF0 → PDU2)
  • PS (15–8)       = 00000100₂ = 0x04 (Group Extension GE)
  • SA (7–0)        = 11001010₂ = 0xCA (源地址)
  • 二进制字段: 110 0 0 11110000 00000100 11001010

Data[1..8] = 40 1F FF FF FF FF FF FF

  • Byte1–2 = 0x1F40 = 8000 → 8000 × 0.125 rpm/bit = 1000 rpm
  • Byte3–8 = 0xFF 填充(无意义/保留)

― PGN 计算 PGN = DP<<16 | PF<<8 | PS = 0x00_ F0_ 04 = 0xF004(发动机转速广播)

Data[1..8] = 40 1F FF FF FF FF FF FF

  • Byte1–2 = 0x1F40 = 8000 → 8000 × 0.125 rpm/bit = 1000 rpm
  • Byte3–8 = 0xFF 填充(无意义/保留)
  • 物理值 = 8000 × 0.125 rpm/bit = 1000 rpm

多帧

当一次要发送的数据长度超过 CAN 最大单帧 8 字节时,SAE J1939 采用“传输协议(Transport Protocol, TP)”来完成多帧分段和重组。TP 包含两部分:

  • 连接管理(Connection Management, CM)
  • 数据传输(Data Transfer, DT)

RTS/CTS + DT 点对点

  • 发起方通过 RTS(Request To Send)控制报文发起一次单点传输
  • 接收方通过 CTS(Clear To Send)控制报文授权分批接收
  • 数据分段后依序通过 DT 报文发送

下面采用点对点模式(RTS/CTS+DT),假设源地址 SA=0x01,目的地址 DA=0x02,PGN=0x00F004,总数据长度 20 字节,共分 3 包。

点击图片可查看完整电子表格

说明

  • 步骤 1 和 2 属于 Connection Management(TP.CM)报文
  • 步骤 3–5 属于 Data Transfer(TP.DT)报文

CM_RTS 报文(TP.CM

CAN ID:18 EC 02 01 Data:14 00 03 F0 00 FF FF FF

点击图片可查看完整电子表格

CM_CTS 报文(TP.CM

CAN ID:18 EC 01 02 Data:02 01 F0 00 FF FF FF FF

点击图片可查看完整电子表格

DT 报文(TP.DT

Data Transfer 报文,每帧第 0 字节为序号 SN,后 1–7 字节为实际数据或填充 FF。

点击图片可查看完整电子表格

PGN 解析

需要注意的是, 这段数据流中CANID+Payload中包含了两个PGN的协议格式

在 J1939 29 位扩展 ID 中,PGN(Parameter Group Number)由数据页 (DP)、PDU 格式 (PF) 和 PDU 专用 (PS) 共同构成。其计算方法为:

Plain Text
PGN = (DP << 16) | (PF << 8) | (PF < 240 ? 0x00 : PS)

  1. CM_RTS/CTS 报文中的 PGN
  • CAN ID(16 进制): 0x18EC0201 (RTS)和 0x18EC0102 (CTS)
  • 拆解字段:
  • DP = 0x00
  • PF = 0xEC (236)
  • PS = 目的地址 (0x02 或 0x01)
  • 因为 PF = 0xEC < 0xF0,属于 PDU1 格式,PGN 的 PS 字段置 0
  • 计算得到:

Plain Text
PGN = 0x00 << 16 | 0xEC << 8 | 0x00 = 0x00EC00

  • 对应十进制:60416

  1. DT 报文中的 PGN
  • CAN ID(16 进制): 0x18EB0102
  • 拆解字段:
  • DP = 0x00
  • PF = 0xEB (235)
  • PS = 目的地址 (0x01)
  • 同样 PF = 0xEB < 0xF0,属于 PDU1,PS 置 0
  • 计算得到:

Plain Text
PGN = 0x00 << 16 | 0xEB << 8 | 0x00 = 0x00EB00

  • 对应十进制:60160

BAM + DT 广播

  • 发起方通过 BAM(Broadcast Announce Message)一次性宣布总长度和分段信息
  • 所有节点无需握手,直接监听并依序通过 DT 接收数据

BAM 控制报文

  • PGN = 0x18ECFF01
  • Data 字段(8 字节)
  • Byte0–1:总字节数
  • Byte2:分包总数
  • Byte3–5:PGN(低→高)
  • Byte6–7:保留

DT 数据报文

  • PGN = 0x18EBFF01
  • Data[0]:分包序号 SN
  • Data[1–7]:载荷;最后一个包不足 7 字节时,空位填 0xFF
  • 无握手,所有节点根据 SN 顺序重组数据

多帧传输示例

假设要广播 20 字节的数据,PGN = 0x00F004,由地址 0x01 发出:

点击图片可查看完整电子表格

BAM 报文(TP.CM.BAM,PGN = 0x00EC00)

29 位扩展 ID 拆解:

  • 优先级 Priority = 6 (0x18 >> 26)
  • 数据页 DP = 0
  • PDU Format PF = 0xEC (< 240 → PDU1)
  • PDU Specific PS = 0xFF (全局广播地址)
  • 源地址 SA = 0x01

PGN 计算: PGN = (DP << 16) | (PF << 8) | 0x00 = 0x00EC00

Data[0..7] 拆解:

  • Byte0 = 0x14 → 总长度 LSB = 20 字节
  • Byte1 = 0x00 → 总长度 MSB
  • Byte2 = 0x03 → 分包总数 = 3
  • Byte3 = 0x04 → 应用层 PGN_LSB
  • Byte4 = 0xF0 → 应用层 PGN_MID
  • Byte5 = 0x00 → 应用层 PGN_MSB  ⇒ 应用 PGN = 0x00F004
  • Byte6–7 = 0xFF 0xFF → 保留
  • 所有监听了 PGN=0x00F004 的节点看到 BAM 即进入重组模式
  • 按 SN 顺序接收 DT 并剔除填充字节 0xFF,重组出完整 20 字节数据

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值