4、车辆发现与声明:VIN/GID/EID的广播机制、车辆声明消息格式、节点状态管理

好,咱们进入第四章节。这一章讲的是DoIP里一个非常有意思的环节——车辆发现与声明。

你想想看,诊断仪插到车上,或者连到网络里,它怎么知道周围有哪些ECU?这些ECU又怎么告诉诊断仪“我在这儿”?这就是车辆发现机制要解决的问题。说白了,就是让车和诊断仪互相认识一下。

4.1 为什么需要车辆发现?

DoIP跑在以太网上,跟CAN总线不一样。CAN总线是广播式的,你发个报文,所有节点都能收到。但以太网不一样,它是点对点通信。诊断仪刚连上来的时候,它根本不知道网络上有哪些DoIP节点。

我刚开始做DoIP项目时,就遇到过这个问题。测试环境里,诊断仪死活找不到ECU。后来发现,是ECU没有正确发送车辆声明报文。嗯,这种坑踩过一次就记住了。

所以,DoIP定义了一套发现机制。核心就是:车辆声明(Vehicle Announcement)。ECU主动告诉网络:“我在这儿,这是我的VIN、我的逻辑地址、我的EID。”

4.2 三种标识符:VIN、GID、EID

在车辆声明里,会用到三种标识符。我分别说一下:

标识符 全称 长度 作用
VIN Vehicle Identification Number 17字节 车辆唯一身份,全球唯一
EID Entity Identification 6字节 ECU的唯一标识,通常是MAC地址
GID Group Identification 6字节 组标识,用于将多个ECU分组

VIN 不用多说,就是这辆车的身份证。17个字符,包含制造商、车型、年份等信息。

EID 是每个DoIP实体的唯一标识。我习惯直接用ECU的MAC地址作为EID,这样既唯一又方便。但注意,EID不强制等于MAC地址,只是通常这么用。

GID 这个有点意思。它可以把多个ECU分到一个组里。比如,一辆车里有网关、ADAS域控制器、座舱域控制器,它们可以共享同一个GID。这样诊断仪发现一个,就等于发现了一组。

重点:VIN是整车的标识,EID是单个ECU的标识,GID是组的标识。三者用途不同,不要搞混。

4.3 车辆声明消息格式

车辆声明消息,用的是UDP广播。目标地址是255.255.255.255,端口是UDP 13400。

为什么用UDP广播?因为诊断仪刚连上来,还不知道任何ECU的IP地址。广播是唯一能让所有节点都收到的方式。

消息格式如下:

字节偏移 | 字段名          | 长度(字节) | 说明
--------|----------------|-----------|------
0       | 协议版本        | 1         | 当前为0x02
1       | 反向协议版本    | 1         | 取反,用于校验
2       | 负载类型        | 2         | 0x0004表示车辆声明
4       | 负载长度        | 4         | 后面数据的长度
8       | VIN            | 17        | 车辆识别码
25      | 逻辑地址        | 2         | ECU的逻辑地址
27      | EID            | 6         | 实体标识
33      | GID            | 6         | 组标识
39      | 保留           | 2         | 填充为0x0000
41      | 进一步动作标志  | 1         | 见下文说明

这个进一步动作标志(Further Action Byte)很重要。它告诉诊断仪,这个ECU接下来要做什么:

  • 0x00:无进一步动作,正常状态
  • 0x10:ECU即将进入编程模式
  • 0x20:ECU即将进入安全模式

我记得有一次,客户反馈说诊断仪连不上ECU。排查了半天,发现是进一步动作标志设置成了0x10,但ECU根本没进编程模式。诊断仪收到这个标志后,以为ECU在特殊状态,就不做正常通信了。所以,这个标志位一定要如实设置。

4.4 广播机制:什么时候发?

车辆声明不是随便发的,它有严格的时机要求。我总结了一下:

  1. 上电启动时:ECU上电后,延迟一段时间(通常是0.5秒到2秒),发送一次车辆声明。
  2. 收到诊断仪的车辆识别请求时:诊断仪会发送一个UDP广播,请求所有DoIP节点回应。ECU收到后,发送车辆声明。
  3. VIN发生变化时:比如在产线末端,VIN被刷写更新了。ECU需要重新发送车辆声明,通知网络VIN变了。
  4. 节点状态变化时:比如从正常模式进入编程模式,需要重新声明。

这里有个细节:上电后的首次声明,要加一个随机延迟。为什么?你想想看,如果一辆车里有10个ECU,同时上电,同时发广播,网络就拥塞了。所以每个ECU的延迟时间要随机化,避免冲突。

我的建议:随机延迟的范围可以设在500ms到2000ms之间。太短了容易冲突,太长了诊断仪等得着急。我一般用1000ms ± 500ms的随机值,效果不错。

4.5 节点状态管理

DoIP节点不是一直在线就完事了。它有几种状态,需要管理好:

状态 说明 车辆声明行为
正常模式 ECU正常运行,可接受诊断请求 按需发送声明
编程模式 ECU正在刷写固件 声明中设置进一步动作标志为0x10
安全模式 ECU处于安全限制状态 声明中设置进一步动作标志为0x20
休眠模式 ECU进入低功耗 发送声明后进入休眠,不再响应

状态切换时,ECU要主动发送车辆声明。比如从正常模式切到编程模式,就要发一个声明,告诉诊断仪:“我现在要刷写了,你别打扰我。”

我曾经遇到过一个bug:ECU进入编程模式后,没有发送新的车辆声明。诊断仪那边还认为它在正常模式,继续发诊断请求。结果ECU正在擦写Flash,根本不理它。诊断仪超时了,报了个通信故障。后来加上了状态切换时的声明发送,问题就解决了。

4.6 避坑指南

我曾经踩过的坑,分享给你:

  • VIN长度必须17字节:少一个字节都不行。有人用16字节的VIN,结果解析全乱了。
  • EID不要重复:同一个网络里,两个ECU的EID不能一样。否则诊断仪会混乱。
  • 广播不要发太频繁:有些ECU每秒钟发一次车辆声明,把网络带宽占满了。正常情况,上电发一次就够了。
  • 进一步动作标志要准确:不要为了省事,一直设成0x00。该设0x10的时候一定要设。

4.7 小结

车辆发现与声明,是DoIP通信的第一步。没有这一步,诊断仪连ECU都找不到,后面什么都做不了。

核心就三点:

  • 三种标识符(VIN、EID、GID)各司其职
  • 车辆声明消息格式要严格遵循
  • 节点状态变化时,及时发送声明

下一章,咱们会讲DoIP的连接建立和路由激活。到时候你会看到,车辆声明只是开胃菜,真正的通信建立过程,还有更多细节等着我们。