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 知识结构图
下面这张图,帮你理清本章的核心逻辑:
2.5 实战中的注意事项
说了这么多理论,咱们聊聊实战中容易踩的坑:
- 响应超时:ECU处理请求需要时间。如果诊断仪超时设置太短,就会误判为通信失败。一般建议设置500ms到1000ms。
- NRC 0x78的处理:ECU返回0x78后,诊断仪必须继续发送请求,直到ECU返回肯定或否定响应。不能直接放弃。
- 功能寻址的冲突:多个ECU同时回复时,CAN总线可能发生仲裁。建议只在读取类服务中使用功能寻址。
- SID的合法性:ECU收到请求后,会先检查SID是否支持。如果不支持,返回NRC 0x11。
我的习惯:每次写诊断代码前,我都会先画一张“请求-响应”流程图。把每个服务的SID、响应ID、可能的NRC都列出来。这样写代码时思路清晰,调试时也容易定位问题。
好了,这一章的内容就到这里。记住:请求ID和响应ID是UDS通信的“身份证”,肯定响应和否定响应是ECU的“态度”,物理寻址和功能寻址是通信的“方式”。把这三点搞清楚了,UDS诊断你就入门了。