第3章:网络层与传输层:ISO 15765-2 (DoCAN) 协议详解

好,咱们今天来聊聊诊断协议栈里最核心的一层——网络层与传输层。说白了,就是 ISO 15765-2,也就是大家常说的 DoCAN。我个人觉得,搞懂这一层,你才算真正入了车载诊断的门。

为什么这么说?因为应用层的诊断消息(比如 UDS 请求)不能直接在 CAN 总线上裸奔。CAN 报文一次最多只能带 8 个字节的数据,而一个诊断请求动不动就几十个字节。怎么办?这就需要网络层来拆包、打包、控制流量。

3.1 单帧与多帧传输机制

ISO 15765-2 定义了两种传输模式:单帧和多帧。判断标准很简单——看数据长度。

  • 单帧 (SF, Single Frame):当诊断数据长度 ≤ 7 字节(常规 CAN)或 ≤ 63 字节(CAN FD)时,一个 CAN 报文就能搞定。我习惯把这种场景叫做“一句话说完”。
  • 多帧 (FF/CF, First Frame / Consecutive Frame):数据长度超过单帧限制时,就需要拆成多个报文发送。第一个报文叫首帧,后面跟着一堆连续帧。

举个例子,你发送一个 20 字节的诊断请求。网络层会这样处理:

首帧 (FF): 包含总长度信息 + 前 6 或 8 字节数据
连续帧 (CF): 后续每帧带 7 或 64 字节数据,直到发完

嗯,这里要注意:首帧的 PCI (协议控制信息) 字节里,高 4 位是 0x10,低 12 位表示总数据长度。我在项目中遇到过有人把长度算错,结果接收方一直等不到数据,直接超时了。

3.2 流控制与时间参数

多帧传输里有个关键角色——流控制帧 (FC, Flow Control)。它负责告诉发送方:“你慢点发,我处理不过来”或者“你快点发,我等着呢”。

流控制帧包含三个参数:

参数 含义 典型值
FS (Flow Status) 流状态:0=继续发送,1=等待,2=溢出/中止 0x00
BS (Block Size) 连续帧的最大数量,达到后需等待下一个 FC 0x00(无限制)或 0x01~0xFF
STmin (Separation Time minimum) 连续帧之间的最小间隔时间(单位 ms) 0x00~0x7F(0~127ms)或 0xF1~0xF9(100μs~900μs)

我个人习惯把 STmin 设成 0x00,也就是不限制间隔。但有些老旧的 ECU 处理能力弱,你发太快它会丢帧。我曾经调试过一个项目,连续帧间隔设成 2ms 就丢包,改成 5ms 就稳了。说白了,这就是个“速度与激情”的平衡问题。

时间参数方面,有几个关键定时器:

  • N_As:发送方从开始发送到 CAN 总线确认的时间。超时通常 1000ms。
  • N_Bs:接收方收到首帧后,到发出流控制帧的时间。超时 1000ms。
  • N_Cs:发送方收到流控制帧后,到发出下一个连续帧的时间。超时 1000ms。
  • N_Ar:接收方从收到连续帧到发出流控制帧的时间。超时 1000ms。
  • N_Br:发送方从收到流控制帧到发出下一个连续帧的时间。超时 1000ms。
  • N_Cr:接收方从收到连续帧到发出下一个流控制帧的时间。超时 1000ms。
避坑指南: 我曾经遇到过一个问题:发送方把 N_Bs 设成 1000ms,但接收方处理首帧需要 1200ms。结果每次多帧传输都超时重发,诊断效率极低。后来我把 N_Bs 改成 2000ms,问题解决。记住,时间参数要根据实际 ECU 性能来调整,别死磕标准值。

3.3 网络层路由与网关

现代汽车里有多个 CAN 网络,比如动力 CAN、舒适 CAN、信息娱乐 CAN。诊断仪可能挂在动力 CAN 上,但想诊断舒适 CAN 上的一个门控模块。这时候就需要网关来做网络层路由。

网关的核心工作就是:把收到的诊断请求,从源网络转发到目标网络。它需要做三件事:

  1. 地址转换:不同网络的 CAN ID 可能不同,网关要重新映射。
  2. 数据转发:把单帧或多帧数据原封不动地搬过去。
  3. 流控制代理:如果源网络和目标网络的速度不同,网关要充当“缓冲器”。

举个例子,动力 CAN 是 500kbps,舒适 CAN 是 125kbps。诊断仪发一个多帧请求到网关,网关收到后,不能直接往舒适 CAN 上狂发,否则舒适 CAN 上的 ECU 根本来不及处理。网关会先缓存数据,然后按照舒适 CAN 的 STmin 要求,慢慢发出去。

我的经验: 网关路由时,最容易出问题的是流控制帧的处理。有些网关实现得比较“傻”,直接把流控制帧透传,结果发送方和接收方的流控制参数不匹配,导致传输失败。我建议网关在转发时,主动管理流控制,而不是简单透传。

另外,网络层路由还涉及一个概念——路由表。网关里有一张表,记录了每个诊断请求应该转发到哪个网络。这张表通常是静态配置的,但有些高级网关支持动态学习。嗯,这里要注意:路由表配置错了,诊断请求就会“迷路”,永远到不了目标 ECU。

最后,我想强调一点:ISO 15765-2 的网络层是独立于物理层的。也就是说,不管底层是 CAN、CAN FD 还是 LIN,网络层的逻辑是一样的。你想想看,这给跨平台移植带来了多大的便利。我当年从 CAN 迁移到 CAN FD 时,网络层代码几乎没改,只改了底层驱动和 DLC 处理。

好了,这一章的内容就到这里。下一章我们会深入应用层——UDS 协议,看看诊断服务是怎么在网络层之上工作的。