J1939-21协议入门:CAN总线与29位标识符详解
系列文章:《深入浅出J1939-21:从原理到实战》第一篇
适合读者:初学者、需要系统了解J1939基础的工程师
阅读时间:约20分钟
引言
如果你是一名商用车、工程机械或农业机械领域的嵌入式工程师,那么J1939协议一定是你绕不开的话题。这套由美国汽车工程师协会(SAE)制定的通信协议,已经成为重型车辆和非公路设备电子控制单元(ECU)之间的通信标准。
本文作为系列的第一篇,将带你从零开始理解J1939-21协议的核心概念,重点讲解CAN总线基础和至关重要的29位标识符结构。掌握这些知识,是深入学习J1939协议的第一步。
一、J1939协议家族概述
1.1 SAE J1939标准体系
SAE J1939不是一个单一的标准文档,而是一个庞大的协议家族。主要包括:
| 标准编号 | 名称 | 主要内容 |
|---|---|---|
| J1939/21 | 数据链路层 | 本文重点,定义CAN消息格式和传输协议 |
| J1939/11 | 物理层 | CAN收发器、连接器、电缆规范 |
| J1939/31 | 网络层 | 网络管理、地址分配 |
| J1939/71 | 车辆应用层 | PGN定义、发动机、变速箱等应用 |
| J1939/73 | 应用层-诊断 | 故障代码(DTC)、诊断消息 |
| J1939/81 | 网络管理 | 网络管理消息 |
┌─────────────────────────────────────────┐
│ 应用层(J1939/71, J1939/73) │
│ 定义具体PGN、SPN、诊断消息等 │
├─────────────────────────────────────────┤
│ 网络层(J1939/31, J1939/81) │
│ 地址管理、网络管理 │
├─────────────────────────────────────────┤
│ 数据链路层(J1939/21)⭐ 本文重点 │
│ 29位标识符、传输协议(TP) │
├─────────────────────────────────────────┤
│ 物理层(J1939/11) │
│ CAN 2.0B、电气特性、连接器 │
└─────────────────────────────────────────┘
1.2 J1939-21在协议栈中的位置
**J1939-21(数据链路层)**是整个协议栈的核心,它定义了:
- ✅ 29位标识符的结构和含义
- ✅ 参数组号(PGN)的编码规则
- ✅ 传输协议(TP),用于传输超过8字节的数据
- ✅ 网络管理的基本机制
可以说,理解J1939-21是掌握整个J1939协议的关键。
1.3 应用场景
J1939协议广泛应用于:
-
商用车辆
- 卡车、大巴、货车
- 发动机、变速箱、ABS、仪表盘通信
-
工程机械
- 挖掘机、装载机、推土机
- 液压系统、动力系统控制
-
农业机械
- 拖拉机、联合收割机、播种机
- 作业控制、GPS导航、产量监测
-
船舶和发电设备
- 船用发动机
- 发电机组监控
二、CAN 2.0B基础回顾
2.1 为什么选择CAN总线?
J1939协议构建在CAN 2.0B(Controller Area Network)之上。CAN总线由德国Bosch公司开发,具有以下优势:
- 🚀 高可靠性:差分信号、错误检测、自动重传
- 💰 成本低:简单的双绞线,无需屏蔽
- ⚡实时性好:基于优先级的仲裁机制
- 🔧 易于维护:节点故障不影响总线运行
2.2 标准帧 vs 扩展帧
CAN 2.0规范定义了两种帧格式:
| 特性 | 标准帧(CAN 2.0A) | 扩展帧(CAN 2.0B) |
|---|---|---|
| 标识符长度 | 11位 | 29位 ⭐ |
| 标识符范围 | 0-0x7FF (2048) | 0-0x1FFFFFFF (536M) |
| 数据长度 | 0-8字节 | 0-8字节 |
| J1939使用 | ❌ 不使用 | ✅ 使用 |
J1939协议使用29位扩展帧格式,这给了我们足够的空间来编码优先级、源地址、目的地址和参数组号(PGN)。
2.3 CAN帧结构
CAN 2.0B扩展帧结构:
┌─────┬─────┬────┬────┬────┬─────┬────────────┬─────┬────┬────┬───┐
│ SOF │ ID │SRR │IDE │ ID │ RTR │ DLC │ Data│CRC │ACK │EOF│
│ │(11) │ │ │(18)│ │ (4bit) │0-8B │ │ │ │
└─────┴─────┴────┴────┴────┴─────┴────────────┴─────┴────┴────┴───┘
↑ ↑
Base ID Extension ID
(11 bits) (18 bits)
总共 29 位标识符
关键字段说明:
- SOF:帧起始位
- ID:标识符(29位 = 11位基础ID + 18位扩展ID)
- SRR:替代远程请求(扩展帧专用)
- IDE:标识符扩展位(标识扩展帧)
- RTR:远程传输请求(J1939中为0)
- DLC:数据长度代码(0-8)
- Data:数据域(0-8字节)
- CRC:循环冗余校验
- ACK:应答位
- EOF:帧结束
2.4 仲裁机制
CAN总线使用非破坏性基于优先级的仲裁:
- 多个节点同时发送时,标识符数值越小,优先级越高
- 仲裁过程中,发送显性位(0)的节点获胜
- 失败节点自动停止发送,等待下次机会
示例:
节点A发送ID:0x0CF00400 (优先级3)
节点B发送ID:0x18F00400 (优先级6)
比特流对比:
位置: 28 27 26 ...
节点A: 0 0 0 ... → 获胜!
节点B: 0 1 1 ... → 仲裁失败,停止发送
2.5 波特率选择
J1939标准规定了两种标准波特率:
| 波特率 | 最大总线长度 | 应用场景 |
|---|---|---|
| 250 kbps | 40米 | 标准配置,最常用 ⭐ |
| 500 kbps | 20米 | 高速应用,消息量大 |
注意:同一个J1939网络中,所有节点必须使用相同的波特率!
三、29位标识符完全解析
3.1 整体结构
J1939-21协议巧妙地将29位标识符划分为多个字段,再加上数据域,构成完整的PDU(Protocol Data Unit,协议数据单元):
1. 优先级(P)
这三个比特位仅用于优化总线上传输消息的延迟,接收端应全局屏蔽(忽略)这些位。
消息优先级可设置为最高位0(000b)或最低位7(111 b)。所有控制类消息默认优先级为3(011 b),
而信息类、专有类、请求类及确认类消息默认优先级为6(110 b)。
2. 扩展数据页(EDP)
EDP与DP共同用于确定CAN数据帧的CAN ID结构。所有SAE J1939消息在发送时都应将EDP设置为零。
将EDP设置为一的未来定义可能扩展PDU格式字段,定义新的PDU格式或增加地址空间。
3. 数据页(DP)
DP与EDP一起使用,以确定CAN数据帧的CAN ID的结构。将EDP设置为零时,DP在PGN描述的第0页和第1页之间进行选择。
4. PDU格式(PF)
PDU格式是一个8位字段,用于定义PGN是否采用PDU1或PDU2格式,同时也是确定数据字段所分配PGN的参考字段之一。
若PF字段的值小于240,则PS字段为DA;若PF字段的值介于240至255之间,PS字段则包含GE值。
5. PDU特定(PS)
PDU特定字段是一个8位字段,其定义取决于PF字段。根据PF字段的不同,该字段可以是目的地址(DA)或组扩展(GE)。
6. 目标地址(DA)
此字段定义要发送邮件的特定地址。请注意,任何其他设备都应忽略此邮件。全局DA(255)要求所有设备作为邮件收件
人侦听并相应地进行响应。
注:EDP在J1939-21中通常为1,与DP配合使用
重要说明:
- 应用层和网络层会生成一系列信息,这些信息会被整合成协议数据单元(PDU)
- PDU为每个CAN数据帧提供了关键的信息组织框架
- SAE J1939标准的PDU包含7个字段:P、EDP、DP、PF、PS、SA以及数据域
- 这些字段会被封装成一个或多个CAN数据帧,通过物理介质传输给其他网络设备
- 每个CAN数据帧仅对应一个PDU
关于传输协议(TP)的说明
某些参数组(PG)定义需要超过8个数据字节,因此需要多个CAN数据帧来发送相应数据。传输协议(TP)消息用于传输超过8个数据字节的PG。
传输协议的详细内容将在本系列的第三篇文章中深入讲解。
J1939协议数据单元(PDU)的定义
J1939协议数据单元(PDU)的定义中刻意省略了CAN数据帧中的某些字段,因为这些字段完全由ISO 11898-1标准定义并控制,对数据链路层之上的所有OSI模型层来说都是不可见的。
采用这种控制方式的字段包括:
- SOF(信号开始字段)
- SRR(响应请求字段)
- IDE(识别地址字段)
- RTR(接收请求字段)
- FDF(帧结束字段)
- r0(响应码字段)
- CRC(校验和字段)
- ACK(确认字段)
- EOF(帧结束字段)
这些是CAN物理层和MAC层的控制字段,J1939协议不需要关心它们。
完整示例分解:
CAN ID: 0x18FEF117 = 0001 1000 1111 1110 1111 0001 0001 0111 (二进制)
拆解:
┌─────────────────────────────────────────────────┐
│ P=011 (3) │ R=0 │ DP=0 │ PF=FE │ PS=F1 │ SA=17 │
└─────────────────────────────────────────────────┘
优先级6 保留 页0 格式254 GE=F1 地址23
让我们逐个字段详细解析。
3.2 Priority(优先级,3 bits)
位置:bit 28-26
范围:0-7(共8个优先级)
标准文档定义
这三个比特位用于优化总线上传输消息的延迟,接收端应全局屏蔽(忽略)这些位。
消息优先级可设置为:
- 最高位:0(000b)
- 最低位:7(111b)
默认优先级规则:
- 所有控制类消息默认优先级为 3(011b)
- 信息类、专有类、请求类及确认类消息默认优先级为 6(110b)
该机制允许根据未来分配的新PGN及总线流量变化调整优先级。当PGN被添加到应用层文档时,系统会为其分配推荐优先级值。
⚠️ 但需注意,优先级字段应支持可编程设置,以便OEM厂商在必要时进行网络调优。
优先级值详细表
| 优先级值 | 二进制 | 十六进制位 | 应用场景 | 示例 |
|---|---|---|---|---|
| 0 | 000b | 0x00 | 最高优先级 | 高优先级控制消息 |
| 1 | 001b | 0x04 | 高优先级 | 实时控制 |
| 2 | 010b | 0x08 | 高优先级 | 实时控制 |
| 3 | 011b | 0x0C | 默认控制消息 ⭐ | EEC1发动机数据 |
| 4 | 100b | 0x10 | 中等优先级 | - |
| 5 | 101b | 0x14 | 中等优先级 | - |
| 6 | 110b | 0x18 | 默认信息消息 ⭐ | 诊断消息 |
| 7 | 111b | 0x1C | 最低优先级 | 非关键数据 |
实际应用建议:
- 关键安全消息(刹车、转向):0-1
- 发动机控制消息:3
- 诊断和配置消息:6
- 日志和统计数据:7
3.3 EDP + DP(扩展数据页+数据页,2 bits)
位置:bit 25-24
组成:EDP(1 bit)+ DP(1 bit)
扩展数据页(EDP)
EDP与DP共同用于确定CAN数据帧的CAN ID结构。
所有SAE J1939消息在发送时都应将EDP设置为零。请参阅下表查看EDP和DP的定义用途。
数据页(DP)
DP与EDP一起使用,以确定CAN数据帧的CAN ID的结构。
将EDP设置为零时,DP在PGN描述的第0页和第1页之间进行选择。请参阅下表。还可以查看标准中的图2,以查看SAE J1939参数组编号模板。
EDP和DP组合表
| 扩展数据页(第25位) CAN ID(第25位) | 数据页(第24位) CAN ID(第24位) | 描述 |
|---|---|---|
| 0 | 0 | SAE J1939第0页PGNs ⭐ 最常用 |
| 0 | 1 | SAE J1939第1页PGNs |
| 1 | 0 | SAE J1939保留 |
| 1 | 1 | ISO 11992-4定义 |
重要说明:
- EDP=0, DP=0:标准的SAE J1939 PGN(第0页),最常用的配置
- EDP=0, DP=1:SAE J1939第1页PGN,用于扩展
- EDP=1, DP=0:SAE J1939保留,未来使用
- EDP=1, DP=1:ISO 11992-4标准定义(卡车-挂车通信)
将EDP设置为一的未来定义可能扩展PDU格式字段,定义新的PDU格式或增加地址空间。
3.4 PF字段(PDU Format,8 bits)
位置:bit 23-16
范围:0-255(0x00-0xFF)
PF字段是J1939标识符的核心,它决定了消息的类型!
PF值的分界点:240(0xF0)
┌──────────────────────┬──────────────────────┐
│ PF < 240 (0xF0) │ PF ≥ 240 (0xF0) │
│ │ │
│ PDU1 格式 │ PDU2 格式 │
│ 点对点通信 │ 广播通信 │
│ PS = 目的地址(DA) │ PS = 组扩展(GE) │
└──────────────────────┴──────────────────────┘
3.5 PS字段(PDU Specific,8 bits)
位置:bit 15-8
范围:0-255(0x00-0xFF)
PS字段是一个"变色龙",它的含义取决于PF字段的值!
情况1:PDU1格式(PF < 240)
PS = 目的地址(Destination Address, DA)
示例:发送给地址0x17的节点
┌────────────────────────────────┐
│ PF=0xEA │ PS=0x17 │ SA=0x00 │
│ Request │ 目的=23 │ 源=0 │
└────────────────────────────────┘
这是一个点对点的Request消息,发给地址23
情况2:PDU2格式(PF ≥ 240)
PS = 组扩展(Group Extension, GE)
示例:EEC1消息
┌────────────────────────────────┐
│ PF=0xF0 │ PS=0x04 │ SA=0x00 │
│ 格式240 │ GE=4 │ 源=0 │
└────────────────────────────────┘
这是EEC1广播消息(PGN=0xF004)
3.6 SA字段(Source Address,8 bits)
位置:bit 7-0
范围:0-255(0x00-0xFF)
SA是消息发送者的地址,每个ECU节点都有唯一的源地址。
| 地址值 | 含义 | 说明 |
|---|---|---|
| 0-253 | 可用地址 | ECU节点使用 ⭐ |
| 254 (0xFE) | NULL地址 | 节点无法获得地址 |
| 255 (0xFF) | 全局地址 | 广播/未声明地址 |
常用地址分配示例:
0x00: 发动机控制器 #1
0x01: 发动机控制器 #2
0x03: 变速箱控制器
0x0B: 制动系统控制器
0x11: 车身控制器
0x17: 仪表盘
0x21: 诊断工具
...
四、PDU1 vs PDU2格式详解
4.1 PDU1格式:点对点通信
特征:PF < 240(0xF0)
用途:专用通信,发送给特定ECU节点
PS字段含义:目的地址(DA)
PDU1 格式(PF < 240):
关键特征:
- PF < 240(0xF0)
- PS字段表示目的地址(Destination Address)
- 用于点对点通信
示例1:请求PGN(Request)
CAN ID: 0x18EA1700
= 0001 1000 1110 1010 0001 0111 0000 0000
分解:
- Priority: 0x06 (6) → 低优先级
- DP: 0
- PF: 0xEA (234 < 240) → PDU1格式
- PS: 0x17 (23) → 目的地址 = 23
- SA: 0x00 (0) → 源地址 = 0
解读:
节点0向节点23请求某个PGN的数据
示例2:传输协议连接管理(TP.CM)
CAN ID: 0x0CEB2511
= 0000 1100 1110 1011 0010 0101 0001 0001
分解:
- Priority: 0x03 (3) → 高优先级
- DP: 0
- PF: 0xEB (235 < 240) → PDU1格式
- PS: 0x25 (37) → 目的地址 = 37
- SA: 0x11 (17) → 源地址 = 17
解读:
节点17向节点37发送TP控制消息
4.2 PDU2格式:广播通信
特征:PF ≥ 240(0xF0)
用途:广播消息,所有节点都可以接收
PS字段含义:组扩展(GE),用于扩展PGN空间
PDU2 标准结构图
PDU2 格式(PF ≥ 240):
关键特征:
- PF ≥ 240(0xF0)
- PS字段表示组扩展(Group Extension)
- 用于广播通信
- 目的地址隐含为0xFF(全局)
示例1:EEC1(发动机控制器1)
CAN ID: 0x0CF00400
= 0000 1100 1111 0000 0000 0100 0000 0000
分解:
- Priority: 0x03 (3) → 高优先级
- DP: 0
- PF: 0xF0 (240 ≥ 240) → PDU2格式
- PS: 0x04 (4) → 组扩展 = 4
- SA: 0x00 (0) → 源地址 = 0
解读:
节点0广播EEC1消息(PGN=0xF004)
所有节点都可以接收
示例2:CCVS(巡航控制/车速)
CAN ID: 0x18FEF117
= 0001 1000 1111 1110 1111 0001 0001 0111
分解:
- Priority: 0x06 (6) → 低优先级
- DP: 0
- PF: 0xFE (254 ≥ 240) → PDU2格式
- PS: 0xF1 (241) → 组扩展 = F1
- SA: 0x17 (23) → 源地址 = 23
解读:
节点23广播CCVS消息(PGN=0xFEF1)
4.3 对比总结表
| 特性 | PDU1格式 | PDU2格式 |
|---|---|---|
| PF范围 | 0-239 (0x00-0xEF) | 240-255 (0xF0-0xFF) |
| 通信方式 | 点对点(Peer-to-Peer) | 广播(Broadcast) |
| PS含义 | 目的地址(DA) | 组扩展(GE) |
| 目的地址 | 由PS指定 | 0xFF(全局) |
| PGN范围 | 0x00000-0xEFFF | 0xF000-0xFFFF |
| 典型应用 | 请求消息、TP消息、命令 | 状态消息、传感器数据 |
五、CAN ID计算实例
5.1 手工计算示例
场景:发动机控制器(地址0x00)广播EEC1消息
已知信息:
- 优先级:3(推荐值)
- DP:0(标准页)
- PF:0xF0(EEC1的PF值)
- PS:0x04(EEC1的GE值)
- SA:0x00(发动机地址)
计算步骤:
步骤1:将各字段转换为二进制
Priority = 3 = 011 (3 bits)
R = 0 = 0 (1 bit)
DP = 0 = 0 (1 bit)
PF = 0xF0 = 11110000 (8 bits)
PS = 0x04 = 00000100 (8 bits)
SA = 0x00 = 00000000 (8 bits)
步骤2:拼接成29位标识符
P R DP PF PS SA
┌───┬───┬───┬────────┬────────┬────────┐
│011│ 0 │ 0 │11110000│00000100│00000000│
└───┴───┴───┴────────┴────────┴────────┘
完整二进制:
00001100 11110000 00000100 00000000
转换为十六进制:
0x0CF00400
结果:CAN ID = 0x0CF00400
六、总结与下期预告
本文要点回顾
通过本文,你应该已经掌握了:
✅ J1939协议家族
- J1939-21是数据链路层的核心标准
- 定义了29位标识符和传输协议
✅ CAN 2.0B基础
- 扩展帧格式(29位标识符)
- 基于优先级的仲裁机制
- 波特率:250 kbps / 500 kbps
✅ 29位标识符结构
- Priority:优先级(3 bits),0-7
- R + DP:保留位+数据页(2 bits)
- PF:PDU格式(8 bits),决定消息类型
- PS:PDU特定(8 bits),双重含义
- SA:源地址(8 bits),0-253
✅ PDU1 vs PDU2
- PDU1(PF < 240):点对点,PS=目的地址
- PDU2(PF ≥ 240):广播,PS=组扩展
✅ 编程实现
- 构建CAN ID的算法
- 解析CAN ID的函数
- PGN提取的正确方法
关键知识点
💡 记住这个分界点:240(0xF0)
- PF < 240 → PDU1 → 点对点 → PS是目的地址
- PF ≥ 240 → PDU2 → 广播 → PS是组扩展
下期预告
在下一篇《参数组号(PGN)与可疑参数号(SPN):J1939数据解析基础》中,我们将深入探讨:
📖 第二篇内容:
- PGN的完整计算方法
- 常用PGN速查表(系统PGN、应用PGN)
- SPN的定义和解析
- EEC1消息完整解析(发动机转速、扭矩等)
- DBC文件格式入门
- Python代码实战:自动解析J1939消息
参考资料
- SAE J1939/21-2021:Data Link Layer Standard
- CAN Specification 2.0:Robert Bosch GmbH
- 《A Comprehensible Guide to J1939》:Wilfried Voss
关于作者
本系列文章由资深商用车电控系统工程师撰写,拥有10年+的J1939协议开发经验。如果你有任何问题或建议,欢迎留言交流!
系列文章目录:
- ✅ 第一篇:J1939-21协议入门:CAN总线与29位标识符详解(本文)
- 🔜 第二篇:参数组号(PGN)与可疑参数号(SPN):J1939数据解析基础
- 🔜 第三篇:传输协议(TP)深度剖析:如何传输超过8字节的数据
- 🔜 第四篇:地址声明机制:J1939网络节点管理与冲突解决
- 🔜 第五篇:J1939-21实战开发:从代码实现到工具调试
本文完
字数统计:约5800字
最后更新:2025年10月