2. 汽车诊断基础

各位工程师,咱们今天聊点实在的。UDS诊断说白了就是ECU和诊断仪之间的对话。既然是对话,就得有规矩——谁先说、说什么、怎么确认对方听懂了。这套规矩,就是请求与响应机制。

我个人习惯把UDS通信比作打电话。你拨号,对方接听,你说“喂”,对方回“喂”。如果对方没反应,或者回了一句“你打错了”,那你就得知道问题出在哪儿。UDS里,这个“喂”就是请求ID(SID),而“喂”的回应就是响应ID(SID+0x40)。

2.1 请求ID(SID)与响应ID(SID+0x40)

每个UDS服务都有一个唯一的服务标识符,也就是SID。比如读取数据的服务是0x22,写入数据的服务是0x2E。诊断仪发出去的是请求,ECU收到后必须回复。回复的时候,ECU会把请求的SID加上0x40,作为响应ID。

举个例子:

  • 诊断仪发送:0x22 0xF1 0x90(请求读取VIN码)
  • ECU正常回复:0x62 0xF1 0x90 ...(0x22 + 0x40 = 0x62)

为什么是0x40?说白了,这是协议设计者留的一个“标记位”。你看到响应报文的高字节,一眼就能判断这是对哪个请求的回复。我在项目中遇到过好几次,有人把请求和响应报文搞混了,结果排查了半天,最后发现是抓包时看反了方向。嗯,从那以后我养成了一个习惯——先看报文第一个字节,小于0x40的是请求,大于等于0x40的是响应。

关键点:响应ID = 请求ID + 0x40。这是UDS协议最基础的规则,也是诊断通信的“握手信号”。

2.2 肯定响应与否定响应(NRC)

ECU收到请求后,有两种回应方式:

  • 肯定响应:ECU说“好的,我照做了”,并返回请求的数据或执行结果。
  • 否定响应:ECU说“不行,因为……”,并附带一个否定响应码(NRC)。

否定响应的报文格式是:0x7F + 请求SID + NRC。比如:

  • 诊断仪发送:0x22 0xF1 0x90
  • ECU回复:0x7F 0x22 0x31(0x31表示请求超出范围)

常见的NRC有哪些?我整理了一个表格,方便你对照:

NRC值 含义 常见场景
0x10 一般拒绝 ECU正忙,无法处理
0x11 服务不支持 ECU不支持该SID
0x12 子功能不支持 SID支持,但子功能无效
0x13 报文长度或格式错误 数据长度不对,或格式有误
0x22 条件不满足 ECU当前状态不允许执行
0x31 请求超出范围 数据ID或参数值无效
0x33 安全访问拒绝 未解锁安全等级
0x35 无效密钥 安全访问的密钥错误
0x78 请求正确接收,响应待定 ECU需要更多时间处理

我的经验:NRC 0x78是个特殊的存在。它表示ECU收到了请求,但需要时间处理。这时候诊断仪不能傻等,得按协议要求轮询。我曾经在一个项目中,ECU处理写入操作需要500ms,但诊断仪只等了200ms就超时了,结果反复报错。后来加了0x78的处理逻辑,问题就解决了。

2.3 物理寻址与功能寻址

UDS通信有两种寻址方式:物理寻址和功能寻址。你想想看,这就像你给同事发消息:

  • 物理寻址:一对一。你直接@某个人,只有他能看到。
  • 功能寻址:一对多。你在群里发消息,所有相关的人都能看到。

在CAN总线上,这两种寻址通过CAN ID来区分。物理寻址的CAN ID是唯一的,只对应一个ECU。功能寻址的CAN ID是广播式的,所有ECU都会接收。

举个例子:

  • 物理寻址:诊断仪发送CAN ID 0x7DF,目标ECU的CAN ID是0x7E0。只有这个ECU会响应。
  • 功能寻址:诊断仪发送CAN ID 0x7DF,所有ECU都会接收并处理。

功能寻址有什么用?最常见的场景是“网络唤醒”或“全局读取”。比如你想知道总线上所有ECU的软件版本,用功能寻址发一个请求,所有ECU都会回复。但要注意,如果多个ECU同时回复,总线可能会冲突。所以功能寻址一般用于不需要回复的服务,或者回复量很小的场景。

避坑指南:我曾经在一个项目中,用功能寻址发了一个写入请求,结果所有ECU都执行了写入操作,导致数据混乱。后来我们规定:写入类服务只能用物理寻址,读取类服务可以用功能寻址。这个原则,建议你也记住。

2.4 知识结构图

下面这张图,帮你理清本章的核心逻辑:

诊断请求与响应机制知识结构图 诊断请求与响应机制 UDS诊断通信 请求ID (SID) 响应ID (SID+0x40) 寻址方式 肯定响应 否定响应 (NRC) 物理寻址 功能寻址 核心原则 响应ID = 请求ID + 0x40 否定响应格式:0x7F + 请求SID + NRC

2.5 实战中的注意事项

说了这么多理论,咱们聊聊实战中容易踩的坑:

  1. 响应超时:ECU处理请求需要时间。如果诊断仪超时设置太短,就会误判为通信失败。一般建议设置500ms到1000ms。
  2. NRC 0x78的处理:ECU返回0x78后,诊断仪必须继续发送请求,直到ECU返回肯定或否定响应。不能直接放弃。
  3. 功能寻址的冲突:多个ECU同时回复时,CAN总线可能发生仲裁。建议只在读取类服务中使用功能寻址。
  4. SID的合法性:ECU收到请求后,会先检查SID是否支持。如果不支持,返回NRC 0x11。

我的习惯:每次写诊断代码前,我都会先画一张“请求-响应”流程图。把每个服务的SID、响应ID、可能的NRC都列出来。这样写代码时思路清晰,调试时也容易定位问题。

好了,这一章的内容就到这里。记住:请求ID和响应ID是UDS通信的“身份证”,肯定响应和否定响应是ECU的“态度”,物理寻址和功能寻址是通信的“方式”。把这三点搞清楚了,UDS诊断你就入门了。