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 广播机制:什么时候发?
车辆声明不是随便发的,它有严格的时机要求。我总结了一下:
- 上电启动时:ECU上电后,延迟一段时间(通常是0.5秒到2秒),发送一次车辆声明。
- 收到诊断仪的车辆识别请求时:诊断仪会发送一个UDP广播,请求所有DoIP节点回应。ECU收到后,发送车辆声明。
- VIN发生变化时:比如在产线末端,VIN被刷写更新了。ECU需要重新发送车辆声明,通知网络VIN变了。
- 节点状态变化时:比如从正常模式进入编程模式,需要重新声明。
这里有个细节:上电后的首次声明,要加一个随机延迟。为什么?你想想看,如果一辆车里有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的连接建立和路由激活。到时候你会看到,车辆声明只是开胃菜,真正的通信建立过程,还有更多细节等着我们。