3、UDS服务分类与SID:诊断服务标识符定义、六大类服务、常用速查表

好,咱们进入第三章。这一章讲的是UDS最基础的东西——SID。说白了,SID就是每个诊断服务的身份证号。你想想看,ECU收到一帧诊断请求,它怎么知道你要干嘛?就是靠这个字节来判断的。

我刚开始接触UDS时,最头疼的就是记这些SID。后来发现,其实不用死记硬背,理解分类逻辑就好。六大类服务,每一类都有固定的范围,你只要记住大类,小服务自然就顺下来了。

3.1 SID的定义与格式

SID全称是Service Identifier,占用1个字节。范围从0x00到0x3E,再往上就是OEM自定义或者保留的了。ISO 14229-1里明确规定了哪些SID是标准服务,哪些留给厂家自己玩。

一个典型的诊断请求长这样:

请求: [SID] [SubFunction] [Data]
响应: [SID+0x40] [SubFunction] [Data]

注意看,正响应里SID要加上0x40。比如0x10是诊断会话控制,正响应就是0x50。这个设计挺巧妙的,你一看响应字节的最高位,就知道是正响应还是负响应。负响应是0x7F开头,后面跟着SID和错误码。

关键点:SID的范围是0x00-0x3E,其中0x10-0x3E是标准服务。0x00-0x0F和0x40-0xFF留给OEM自定义或将来扩展用。我个人建议,做项目时尽量别碰标准SID,除非你有充分的理由。

3.2 六大类服务详解

ISO 14229把诊断服务分成了六大类。每一类解决一类问题。我按顺序给你捋一遍。

3.2.1 诊断与通信管理类 (0x10-0x3E中的一部分)

这类服务负责管理诊断会话、控制ECU的通信行为。说白了就是「握手」和「维持连接」用的。

  • 0x10 诊断会话控制:切换默认会话、扩展会话、编程会话等。我遇到过一个问题,ECU在默认会话下很多服务不让用,必须先切到扩展会话。很多新手会在这里卡住。
  • 0x11 ECU复位:硬复位、软复位、快速上电复位。注意复位后会话会回到默认会话。
  • 0x27 安全访问:解锁ECU的受保护功能。这个服务我后面会专门讲,坑很多。
  • 0x28 通信控制:开启或关闭某些通信报文。比如你想让ECU安静一点,可以用这个。
  • 0x3E 测试仪保持连接:也叫Tester Present。防止ECU因为超时自动退出诊断会话。

我的经验:0x3E这个服务经常被忽略。有些ECU的会话超时时间只有5秒,如果你不发Tester Present,它就会自动退出。我曾经调试一个项目,发现诊断总是断断续续,查了半天才发现是忘了发0x3E。

3.2.2 数据传输类 (0x22, 0x23, 0x24)

这类服务用来读取ECU内部的数据。比如传感器值、状态标志、版本号等。

  • 0x22 通过ID读取数据:最常用的服务之一。你给一个DID(数据标识符),ECU返回对应的数据。比如读取VIN码、读取软件版本。
  • 0x23 通过地址读取内存:直接按物理地址读。这个比较底层,一般用于调试或刷写。
  • 0x24 通过ID读取周期数据:类似0x22,但可以设置周期,ECU会按周期自动上报数据。

我个人习惯,能用0x22就别用0x23。因为0x23需要你知道具体的内存地址,不同芯片、不同软件版本地址可能不一样,维护起来很麻烦。

3.2.3 存储数据传输类 (0x14, 0x19)

这类服务跟DTC(诊断故障码)打交道。说白了就是读故障、清故障。

  • 0x14 清除诊断信息:清除DTC和快照数据。注意,清除前通常需要安全访问。
  • 0x19 读取DTC信息:这个服务子功能很多,比如按状态掩码读DTC、读快照、读扩展数据。我建议你重点掌握0x19的0x02子功能(按状态掩码读DTC),这是最常用的。

避坑指南:我曾经遇到过一个问题,0x14清除DTC后,ECU的某些学习值也被重置了。后来发现是设计问题,清除DTC时不应该影响非易失性存储的学习值。所以设计时一定要把DTC存储和其他数据分开。

3.2.4 输入输出控制类 (0x2F)

这个服务很强大,可以让你直接控制ECU的物理输出,或者模拟输入信号。常用于产线测试或维修诊断。

  • 0x2F 通过ID控制输入输出:你可以控制一个继电器吸合、控制一个LED点亮、或者模拟一个传感器信号。子功能包括:强制值、冻结当前值、短时控制等。

嗯,这里要注意。0x2F控制的是物理层,如果你控制错了,可能会损坏硬件。比如你让一个电机长时间堵转,可能会烧掉驱动芯片。所以设计时一定要加保护机制,比如超时自动恢复。

3.2.5 远程激活类 (0x31, 0x34, 0x35, 0x36, 0x37)

这类服务用于执行ECU内部的例程,或者启动一些特殊功能。

  • 0x31 例程控制:启动、停止、查询一个例程。比如启动一个自检例程、启动一个校准例程。这个服务很灵活,你可以把任何需要多步操作的功能封装成一个例程。
  • 0x34 请求下载:刷写的第一步,告诉ECU我要下载数据了。
  • 0x35 请求上传:从ECU读取数据,比如读出一段内存。
  • 0x36 传输数据:实际的数据传输,配合0x34或0x35使用。
  • 0x37 请求退出传输:结束传输过程。

我记得有一次做OTA刷写,0x31例程控制用来做刷写前的条件检查,比如检查电池电压、检查点火状态。如果条件不满足,例程直接返回负响应,刷写流程就终止了。这个设计很安全。

3.2.6 上传下载类 (0x34-0x37)

严格来说,上传下载是远程激活类的一部分。但因为刷写功能太重要了,很多人把它单独拎出来讲。这里我简单提一下流程:

  1. 先通过0x10切到编程会话
  2. 通过0x27解锁安全访问
  3. 用0x34请求下载,告诉ECU要下载多少数据
  4. 用0x36分块传输数据
  5. 用0x37退出传输
  6. 最后用0x11复位ECU

这个流程我建议你背下来,面试经常问,实际项目也天天用。

3.3 常用SID速查表

下面这个表是我自己整理的,工作中最常用的SID。你把它打印出来贴在工位上,用着用着就熟了。

SID 服务名称 所属大类 常用子功能
0x10 诊断会话控制 诊断与通信管理 0x01默认, 0x02编程, 0x03扩展
0x11 ECU复位 诊断与通信管理 0x01硬复位, 0x02软复位, 0x03快速上电
0x14 清除诊断信息 存储数据传输 0xFF清除所有DTC
0x19 读取DTC信息 存储数据传输 0x02按状态掩码读, 0x0A读快照
0x22 通过ID读取数据 数据传输 无子功能, 直接带DID
0x27 安全访问 诊断与通信管理 0x01请求种子, 0x02发送密钥
0x28 通信控制 诊断与通信管理 0x00使能, 0x01禁用, 0x02使能Rx, 0x03禁用Rx
0x2F 通过ID控制输入输出 输入输出控制 0x00强制, 0x01冻结, 0x02短时控制
0x31 例程控制 远程激活 0x01启动, 0x02停止, 0x03查询
0x34 请求下载 上传下载 无子功能, 带地址和长度
0x36 传输数据 上传下载 无子功能, 带块序号和数据
0x3E 测试仪保持连接 诊断与通信管理 0x00零子功能, 0x80带抑制响应

小技巧:0x3E的0x80子功能很有用。如果你不想让ECU每次都回正响应(减少总线负载),可以用0x80。ECU收到后不会发正响应,但会刷新超时计时器。

好了,这一章的内容就这些。SID是UDS的基石,你把它搞清楚了,后面的服务实现就是水到渠成的事。下一章我会讲具体的服务实现细节,比如0x22和0x2E的读写流程,到时候咱们再细聊。