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(链路控制):控制诊断链路的连接状态。
注意: 强制服务不是「必须实现所有功能」,而是「必须实现该服务ID」。比如0x27安全访问,你可以只实现种子和密钥的交换,但服务本身必须存在。我曾经见过一个ECU,直接把0x27返回NRC 0x11(服务不支持),结果诊断仪死活连不上。嗯,这就是典型的「强制服务缺失」。

说完强制,再说可选服务。可选服务就多了,比如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诊断栈。嗯,到时候你会看到,这些服务分类在实际代码里是怎么落地的。