3. 诊断通信基础:物理层与寻址方式

各位同学,咱们今天聊聊诊断通信的底层基础。说实话,这部分内容看起来有点枯燥,但它是整个诊断栈的根基。我见过不少工程师,上来就写应用层代码,结果在物理层上栽了跟头——报文发不出去,或者收不到响应,排查半天才发现是地址配错了。

嗯,咱们一步步来。先看物理层,再看寻址方式。

3.1 物理层:CAN、LIN、以太网

诊断协议本身是应用层的规范,它不关心数据到底走什么物理介质。但实际项目中,物理层选型直接影响你的诊断策略。我个人的习惯是:先定物理层,再定诊断方案。

3.1.1 CAN总线

CAN是目前车载诊断的绝对主力。为什么?因为它可靠、实时性好、支持多主通信。你在OBD接口上看到的那些诊断报文,绝大多数都是走CAN的。

CAN诊断有几个关键参数:

  • 波特率:常见的有125kbps、250kbps、500kbps。我遇到过一些项目,ECU和诊断仪波特率没对上,结果通信失败。排查了半天才发现是配置问题。
  • CAN ID:诊断报文使用29位扩展ID(CAN 2.0B),也有用11位标准ID的,但很少见。
  • 数据场长度:CAN帧最多8字节数据。UDS诊断服务如果数据量超过8字节,就得拆分成多帧传输——这就是后面要讲的TP层(传输协议层)。

重点:CAN诊断的物理层,说白了就是两根线(CAN_H、CAN_L),加上一个终端电阻。但实际项目中,线束长度、节点数量、电磁干扰都会影响通信质量。我曾经在一个项目中,因为CAN线束过长,导致信号反射严重,诊断报文频繁出错。后来加了终端电阻才解决。

3.1.2 LIN总线

LIN总线成本低,但速度慢(最大20kbps)。它主要用于车身附件,比如车窗、座椅、车灯这些不太需要高速通信的节点。

LIN诊断有个特点:它是主从架构。只有主节点能发起诊断请求,从节点只能响应。这意味着你不能像CAN那样随意发诊断报文。

我个人觉得,LIN诊断适合做简单的功能,比如读取故障码、写入配置参数。你要是想在LIN上做复杂的刷写操作,那速度会让你崩溃的。

小提示:LIN诊断的报文格式和CAN不太一样。LIN帧的数据场最多8字节,但它的ID范围只有0x00-0x3F(64个)。诊断请求通常使用保留ID,比如0x3C和0x3D。

3.1.3 以太网

以太网是近年来车载诊断的新宠。DoIP(Diagnostic over Internet Protocol)就是基于以太网的诊断协议。它的优势很明显:速度快(100Mbps甚至更高),数据量大,适合刷写和大量数据传输。

但以太网诊断也有坑:

  • IP地址配置:ECU需要分配IP地址,要么静态配置,要么通过DHCP获取。我见过一个项目,ECU的IP地址和诊断仪冲突,导致通信中断。
  • TCP/UDP选择:诊断请求通常走TCP(可靠传输),但有些场景也用UDP(比如发现服务)。
  • 物理层:车载以太网通常使用100BASE-T1或1000BASE-T1,和普通以太网不一样,需要专用收发器。

说实话,以太网诊断在传统ECU上用得不多,但在域控制器、自动驾驶控制器上越来越普遍。如果你做的是高端项目,这块必须掌握。

3.2 诊断地址:ECU的身份证

每个ECU在诊断通信中都有一个唯一的地址,叫做诊断地址(Diagnostic Address)。它就像ECU的身份证,诊断仪通过这个地址找到目标ECU。

诊断地址的定义在ISO 13400(DoIP)和ISO 15765-2(CAN)中有规定。常见的地址范围:

地址范围 用途 示例
0x01 - 0x0F OBD(车载诊断系统) 0x01(发动机)
0x10 - 0x1F UDS诊断(功能寻址) 0x18(功能寻址)
0x20 - 0xFF UDS诊断(物理寻址) 0x21(ECU A)

注意:诊断地址不是随便选的。ISO标准中有明确的地址分配规则。我曾经见过一个项目,工程师把ECU地址设成了0x00,结果诊断仪根本识别不了——因为0x00是广播地址,不能用于单个ECU。

3.3 功能寻址 vs 物理寻址

这是诊断通信中最容易混淆的概念。我刚开始做诊断时也搞不清楚,后来踩了坑才明白。

3.3.1 物理寻址

物理寻址,说白了就是一对一通信。诊断仪发送一个请求,只有目标ECU会响应。其他ECU看到这个地址,知道不是找自己的,就忽略掉。

举个例子:

  • 诊断仪发送请求到地址0x21(ECU A)
  • 只有ECU A会处理这个请求并回复
  • ECU B、ECU C看到地址0x21,直接忽略

物理寻址的优点是精准。你想读取哪个ECU的故障码,就发到它的物理地址。不会出现多个ECU同时回复的情况。

3.3.2 功能寻址

功能寻址是一对多通信。诊断仪发送一个请求到功能地址,所有支持该功能的ECU都会响应。

举个例子:

  • 诊断仪发送请求到功能地址0x18(所有ECU)
  • ECU A、ECU B、ECU C都会处理这个请求并回复
  • 但注意:每个ECU的回复是独立的,诊断仪需要处理多个响应

功能寻址的典型应用场景:

  • 诊断会话控制:你想让所有ECU同时进入扩展诊断会话
  • ECU复位:你想让所有ECU同时复位
  • 读取故障码:你想知道哪些ECU有故障

关键区别:物理寻址是点对点,功能寻址是广播。你想想看,如果你用物理寻址去复位所有ECU,那得发几十条报文,效率太低了。功能寻址一条报文搞定。

3.3.3 实际项目中的选择

我个人的经验是:

  • 日常诊断(读取故障码、读取数据):用物理寻址。因为你通常只关心某个特定ECU的状态。
  • 批量操作(复位、进入会话):用功能寻址。效率高,一条报文搞定所有ECU。
  • 刷写:必须用物理寻址。刷写过程中,你只希望目标ECU响应,其他ECU不能干扰。

我曾经在一个项目中,工程师在刷写时用了功能寻址,结果所有ECU都进入了刷写模式,总线上一片混乱。嗯,从那以后我再也不敢在刷写时用功能寻址了。

3.4 避坑指南

最后,分享几个我踩过的坑:

  1. 地址冲突:两个ECU用了相同的物理地址。诊断仪发请求,两个ECU同时回复,总线冲突。解决办法:在项目初期就规划好地址分配表。
  2. 功能寻址滥用:有些工程师图省事,所有诊断请求都用功能寻址。结果多个ECU同时回复,诊断仪处理不过来,丢帧严重。记住:功能寻址只适合广播类操作。
  3. 物理层不匹配:CAN和LIN的物理层参数(波特率、终端电阻)必须一致。我见过一个项目,ECU用250kbps,诊断仪用500kbps,结果通信失败。排查了三天才发现是波特率问题。

总结一下:物理层决定了你能不能通信,寻址方式决定了你和谁通信。两者缺一不可。下一章咱们讲传输层(TP层),看看数据量超过8字节时怎么处理。