4、UDS服务分类:强制服务与可选服务,6大类服务概览
好,咱们今天聊聊UDS服务的分类。说实话,刚接触UDS那会儿,我看着那一堆服务号(SID)也挺懵的。0x10、0x22、0x2E……这都啥跟啥?后来做项目多了,慢慢就摸清了门道。
UDS协议里,服务不是随便定义的。它有一套清晰的分类逻辑。我个人习惯,先看它是「强制」还是「可选」,再看它属于哪一类功能。这样记起来就轻松多了。
4.1 强制服务 vs 可选服务
先说说强制服务。什么叫强制?就是ECU只要宣称支持UDS,这几个服务必须得有。少了任何一个,诊断仪连上你的ECU,第一步就卡住了。
强制服务有哪些?
- 0x10(诊断会话控制):没有它,你连会话都切不了。ECU默认上电是默认会话,想干点正事,得先切到扩展会话或编程会话。
- 0x11(ECU复位):这个不用多说,诊断完要复位ECU,或者刷完软件要重启,全靠它。
- 0x27(安全访问):嗯,这个我得多说两句。我在项目中遇到过,有些ECU把安全访问的种子和密钥算法写得太简单,结果被第三方轻松破解。后来我们强制要求密钥长度至少32位,算法还得加盐。记住,安全访问不是摆设,它是ECU的第一道防线。
- 0x28(通信控制):控制ECU的通信行为,比如关掉某些报文,方便你刷写或测试。
- 0x3E(测试仪在线):这个服务特别容易被忽略。你想想看,诊断会话是有超时机制的。如果你发完一条请求,半天没动静,ECU就自动切回默认会话了。0x3E就是用来「保活」的。我曾经调试一个ECU,发现会话老是莫名其妙超时,查了半天,原来是诊断仪没发0x3E。
- 0x83(访问时间参数):用来读写ECU内部的时间参数,比如超时时间、重试次数。
- 0x84(安全数据传输):这个在需要加密通信的场景下必须支持。
- 0x85(控制DTC设置):诊断故障码(DTC)的开关控制。刷写软件时,你得先把DTC记录关掉,不然刷一半报一堆故障码,那画面太美我不敢看。
- 0x86(事件响应):处理ECU内部事件响应的服务。
- 0x87(链路控制):控制诊断链路的连接状态。
说完强制,再说可选服务。可选服务就多了,比如0x22(读取数据)、0x2E(写入数据)、0x31(例程控制)等等。这些服务,ECU可以根据实际需求选择实现。比如一个简单的传感器ECU,可能不需要0x2E写入数据,那就可以不实现。
但要注意,可选服务虽然叫「可选」,但在实际项目中,客户需求往往把它变成了「必选」。比如做OBD(车载诊断)的ECU,0x22读取数据是必须的,不然过不了法规。
4.2 6大类服务概览
UDS把服务分成了6大类。这个分类是基于功能来划分的。我个人觉得,理解了这个分类,你看到任何一个服务号,就能大概猜到它是干嘛的。
| 类别 | 功能描述 | 典型服务 |
|---|---|---|
| 诊断和通信管理类 | 管理诊断会话、通信控制、安全访问等 | 0x10, 0x11, 0x27, 0x28, 0x3E, 0x83, 0x84, 0x85, 0x86, 0x87 |
| 数据传输类 | 读写ECU内部数据,比如DID(数据标识符) | 0x22(读取数据), 0x2E(写入数据), 0x23(读取内存), 0x24(读取缩放数据) |
| 存储数据传输类 | 读写ECU的存储区域,比如Flash、EEPROM | 0x34(请求下载), 0x35(请求上传), 0x36(传输数据), 0x37(请求退出传输) |
| 输入输出控制类 | 控制ECU的输入输出信号,比如强制某个引脚输出高电平 | 0x2F(输入输出控制) |
| 例程类 | 执行ECU内部的特定例程,比如自检、擦除、编程 | 0x31(例程控制) |
| 上传/下载类 | 用于ECU刷写、数据上传下载 | 0x34, 0x35, 0x36, 0x37(与存储数据传输类有重叠,但侧重点不同) |
你看,这样一分类,是不是清晰多了?比如你看到0x22,就知道它是「数据传输类」的,用来读数据。看到0x31,就知道它是「例程类」,用来执行某个功能。
我的经验: 在实际项目中,最常用的其实是诊断和通信管理类(0x10、0x27、0x3E)和例程类(0x31)。尤其是0x31,刷写软件、自检、擦除Flash,全得靠它。我建议你把0x31的例程ID(RID)规划好,每个例程做什么,参数是什么,返回值是什么,提前定义清楚。不然等到项目后期,例程ID冲突了,那改起来可真是要命。
4.3 避坑指南:服务分类的常见误区
做UDS诊断栈,有几个坑我踩过,分享给你。
误区一: 把强制服务当成可选服务。比如0x3E(测试仪在线),有些人觉得「我的ECU会话超时时间很长,不需要发0x3E」。错!强制服务必须实现,哪怕你超时时间设成1小时,0x3E也得支持。不然诊断仪连上你的ECU,第一步就报错。
误区二: 服务分类搞混。比如0x31(例程控制)和0x2F(输入输出控制),功能上有点像,但分类不同。0x31是执行一段代码(例程),0x2F是直接控制硬件引脚。我曾经见过一个工程师,把控制继电器的功能用0x31实现,结果诊断仪发0x2F请求时,ECU直接返回NRC 0x12(子功能不支持)。嗯,这就是分类没搞清。
误区三: 忽略服务间的依赖关系。比如你要用0x2E写入数据,必须先通过0x27安全访问。如果你直接发0x2E,ECU会返回NRC 0x33(安全访问拒绝)。我调试时经常遇到这种问题,诊断仪发了一堆请求,ECU全给拒了,一看日志,安全访问没通过。
4.4 小结
好了,这一章咱们聊了UDS服务的分类。说白了,就是两件事:
- 强制服务:必须实现,缺一不可。
- 可选服务:按需实现,但客户需求往往把它变成必选。
然后就是6大类服务:诊断和通信管理、数据传输、存储数据传输、输入输出控制、例程、上传/下载。记住这个分类,你看到任何服务号,都能快速定位它的功能。
下一章,咱们开始动手写代码。我会带你从0开始,搭建一个最简单的UDS诊断栈。嗯,到时候你会看到,这些服务分类在实际代码里是怎么落地的。