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)
严格来说,上传下载是远程激活类的一部分。但因为刷写功能太重要了,很多人把它单独拎出来讲。这里我简单提一下流程:
- 先通过0x10切到编程会话
- 通过0x27解锁安全访问
- 用0x34请求下载,告诉ECU要下载多少数据
- 用0x36分块传输数据
- 用0x37退出传输
- 最后用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的读写流程,到时候咱们再细聊。