3、网络层(ISO 15765-2)基础:单帧与多帧传输机制、CAN ID分配策略、网络层定时参数
好,咱们今天聊聊网络层。说白了,就是ISO 15765-2这个标准。很多刚入行的朋友,UDS应用层协议背得滚瓜烂熟,一抓报文就懵了。为什么?因为网络层没搞透。报文怎么拆的、怎么合的、ID怎么分配的、超时怎么算的,这些才是实战里的硬骨头。
我个人习惯,把网络层看作是UDS的“快递系统”。应用层只管把包裹(诊断数据)交给它,至于怎么打包、怎么运输、怎么防止丢件,那是网络层的事。你想想看,如果快递员连包裹都拆错、送错地址,那后面全是白搭。
3.1 单帧与多帧传输机制
CAN报文一帧最多只能带8个字节数据。但诊断数据动不动就几十上百个字节。怎么办?拆呗。
单帧(SF,Single Frame)
当诊断数据长度 ≤ 7个字节时,一帧搞定。第一个字节叫“单帧头”,高4位是0,低4位表示数据长度。
// 单帧示例:0x10 0x03(诊断会话控制请求)
// 报文数据:03 10 03 00 00 00 00 00
// 第一个字节 0x03:高4位0表示单帧,低4位3表示后面有3个有效数据
// 实际数据:10 03 00
多帧(FF/CF,First Frame / Consecutive Frame)
数据长度 > 7个字节时,就得拆成多帧了。流程是这样的:
- 首帧(FF):第一个字节高4位是1,低4位和第二个字节组成12位,表示总数据长度。后面6个字节放第一段数据。
- 流控帧(FC,Flow Control):接收方收到首帧后,回复流控帧。告诉发送方:“你慢点发”或“你可以发了”。
- 连续帧(CF,Consecutive Frame):发送方根据流控帧的指示,一帧一帧把剩下的数据发完。
关键点:连续帧的SN(序列号)从1开始,每发一帧加1,到15后回0。我曾经排查过一个Bug,ECU连续帧SN从0开始,导致工具端一直报“序列号错误”。查了三天,最后发现是芯片供应商的协议栈写错了。
// 多帧示例:写入34字节数据
// 首帧(FF):10 22 [数据6字节]
// 0x10:高4位1表示首帧,低4位2表示总长度高4位
// 0x22:总长度低8位 → 总长度 = 0x022 = 34字节
//
// 流控帧(FC):30 00 00
// 0x30:流控标志,30表示允许发送
// 0x00:BS(块大小),0表示无限制
// 0x00:STmin(最小间隔时间),0ms
//
// 连续帧(CF):21 [数据7字节]
// 0x21:高4位2表示连续帧,低4位1表示SN=1
// 后续CF:22, 23, 24...直到发完
避坑指南:我曾经遇到一个项目,ECU的STmin设置成0x10(16ms),但工具端默认是0x00。结果ECU收得太快,缓冲区溢出,直接丢帧。后来我建议把STmin设成0x0A(10ms),问题就解决了。嗯,这里要注意,STmin不是越小越好,得看ECU的处理能力。
3.2 CAN ID分配策略
CAN ID怎么分?这问题看似简单,实际坑不少。说白了,就是给诊断报文一个“身份证号”,让ECU知道这报文是发给谁的、谁发的。
物理寻址 vs 功能寻址
| 类型 | 说明 | CAN ID示例(11位) |
|---|---|---|
| 物理请求 | 点对点,发给指定ECU | 0x7E0(诊断仪→ECU) |
| 物理响应 | 指定ECU回复 | 0x7E8(ECU→诊断仪) |
| 功能请求 | 广播,发给总线上所有ECU | 0x7DF |
我见过最离谱的案例:某供应商把功能请求ID和物理请求ID设成一样。结果一发送功能请求,所有ECU都回复,总线直接爆了。你想想看,那场面多壮观。
29位扩展ID
有些高端车用29位ID,结构更复杂。一般包含:
- 优先级(3位)
- 保留位(1位)
- 数据页(1位)
- PDU格式(8位)
- PDU特定(8位)
- 源地址(8位)
注意:29位ID的分配策略,不同OEM有不同标准。我建议你拿到项目后,先找OEM的《诊断规范》文档。别自己瞎猜,猜错了就是几千台车回厂刷写。
3.3 网络层定时参数
网络层定时参数,说白了就是“等多久算超时”。这些参数设不好,诊断通信要么慢得像蜗牛,要么动不动就超时断开。
核心定时参数一览
| 参数 | 默认值 | 说明 |
|---|---|---|
| N_As | 0~1ms | 发送方从开始发送到帧结束的时间 |
| N_Bs | 0~1ms | 接收方从收到首帧到发出流控帧的时间 |
| N_Cs | 0~1ms | 发送方从收到流控帧到发出下一帧的时间 |
| N_Ar | 0~1ms | 接收方从收到帧到开始处理的时间 |
| N_Br | 0~1ms | 发送方从发出首帧到收到流控帧的超时时间 |
| N_Cr | 0~1ms | 发送方从发出连续帧到收到下一帧流控的超时时间 |
这些参数看着简单,但实际项目中经常出问题。我记得有一次,某ECU的N_Br设成50ms,但工具端默认是100ms。结果ECU发完首帧后,工具端等了80ms才回复流控帧。ECU直接判定超时,重发首帧。工具端收到两个首帧,直接懵了。
我的建议:调试阶段,把N_Br和N_Cr设大一点(比如200ms),等通信稳定了再调小。别一上来就追求极致性能,先把功能跑通再说。
BS(块大小)和STmin(最小间隔时间)
这两个参数在流控帧里设置,直接影响多帧传输的效率。
- BS:接收方允许发送方连续发送的帧数。BS=0表示无限制,BS=5表示发5帧后必须等下一个流控帧。
- STmin:发送方连续帧之间的最小间隔。单位有ms和us两种,具体看编码。
我曾经优化过一个刷写流程,ECU的BS设成1,STmin设成10ms。结果刷一个256KB的固件,要发几万个连续帧,每帧等10ms,总耗时超过4分钟。后来我把BS改成10,STmin改成2ms,刷写时间直接降到40秒。你想想看,这差距多大。
实战技巧:如果你发现诊断通信特别慢,先查BS和STmin。很多ECU出厂设置偏保守,适当调大BS、调小STmin,效果立竿见影。但别调太猛,小心ECU处理不过来。
好了,网络层的基础就这些。单帧多帧的拆装、CAN ID的分配、定时参数的设置,这三块搞明白了,诊断通信的底层逻辑你就通了。下一章咱们聊聊应用层,那才是真正干活的地方。