ISO 15765-2 拆帧的核心逻辑是:先看 UDS 应用层数据有多长,再判断能否放进一个 CAN 帧;放不下就拆成“首帧 + 连续帧”,中间用“流控帧”控制节奏。
1. 先判断:要不要拆帧?
以常见 CAN 2.0 为例,一个 CAN 帧数据域最多8 字节。ISO-TP 还要占用 1 字节做帧头,所以:
| 情况 | 判断方式 | 使用帧类型 |
|---|---|---|
| 数据 ≤ 7 字节 | 一个 CAN 帧装得下 | 单帧 SF |
| 数据 > 7 字节 | 一个 CAN 帧装不下 | 首帧 FF + 连续帧 CF |
| 接收方需要控速 | 多帧传输中 | 流控帧 FC |
CAN FD 下阈值会更高,但原理相同。
2. 四种帧怎么区分?
ISO 15765-2 用 CAN 数据域第 1 个字节的高 4 位 N_PCI type来区分帧类型。
| 帧类型 | N_PCI 高 4 位 | 作用 |
|---|---|---|
| 单帧 SF | 0x0 | 短数据一帧发完 |
| 首帧 FF | 0x1 | 告诉对方总长度,并携带前 6 字节数据 |
| 连续帧 CF | 0x2 | 携带后续数据,带序列号 SN |
| 流控帧 FC | 0x3 | 接收方控制发送节奏 |
3. 单帧 SF:短数据不拆
当 UDS 报文 ≤ 7 字节时,直接发单帧。
例如读取 DID 的请求:
02 22 F1 90 00 00 00 0002:单帧,有效数据长度 222 F1 90:UDS 服务 0x22,DID 0xF190- 后面补 0 或填充字节
这种在 Trace 里最简单,一眼就能看出是一条完整 UDS 请求或响应。
4. 多帧传输:FF → FC → CF
当数据超过 7 字节时,典型流程是:
发送方 接收方 |── FF(首帧)───────────────>| |<── FC(流控帧)─────────────| |── CF#1(连续帧)───────────>| |── CF#2(连续帧)───────────>| |── ... ────────────────────>| |<── FC(下一个块)───────────| 如果 BS 有限制 |── CF#n ───────────────────>|首帧 FF
首帧负责两件事:
- 声明总数据长度;
- 携带前 6 字节有效数据。
格式大致是:
1X XX D1 D2 D3 D4 D5 D6- 第 1 字节高 4 位 = 1,表示首帧;
- 第 1 字节低 4 位 + 第 2 字节组成12 位总长度 FF_DL;
- 第 3~8 字节是前 6 字节数据。
例如:
10 0F 22 F1 90 00 00 00表示总长度 0x00F = 15 字节,后面还有 9 字节要通过连续帧发送。
流控帧 FC
接收方收到首帧后,要先回一个流控帧,告诉发送方“怎么发”。
30 00 14 00 00 00 00 0030:高 4 位 = 3,表示流控帧;低 4 位 = 0,表示 CTS,继续发送;00:BS = 0,表示连续帧数量无限制;14:STmin = 20 ms,表示连续帧之间至少间隔 20 ms。
流控帧里的三个关键字段:
- FS 流状态:
0x0继续发送,0x1等待,0x2溢出/终止; - BS 块大小:允许连续发送多少个 CF,0 表示无限制;
- STmin 最小间隔:两个连续帧之间最小等待时间。
连续帧 CF
连续帧负责搬运剩余数据,每帧最多携带 7 字节。
21 D7 D8 D9 DA DB DC DD 22 DE DF 00 00 00 00 00- 高 4 位 = 2,表示连续帧;
- 低 4 位是序列号 SN;
- SN 从 1 开始递增:
21, 22, 23 ... 2F, 20, 21 ...,到 0xF 后回绕。
接收方根据 FF 声明的总长度和 CF 的 SN,把数据按序拼回完整 UDS 报文。
5. 在 CANoe Trace 里怎么看?
排查时可以把日志按 PCI 类型快速过滤:
0x开头:单帧,通常是一条完整诊断请求/响应;1x xx开头:首帧,说明后面还有连续帧;2x开头:连续帧,注意 SN 是否连续;3x开头:流控帧,重点看 FS、BS、STmin。
如果看到首帧之后长时间没有流控帧,可能是N_Bs 超时;如果连续帧中途断开,可能是总线负载过高、STmin 过小、BS 配置不当或 ECU 处理超时。
6. 一句话记忆
单帧看长度,首帧报总量,流控定节奏,连续帧搬数据,序列号保顺序。
看 Trace 时先找1x首帧,再顺着2x连续帧和3x流控帧,就能还原整条 UDS 长报文。