3、UDS协议核心:服务ID(SID)、子功能、正负响应码的详细解析

UDS(Unified Diagnostic Services,统一诊断服务)协议是ISO 14229标准定义的车载诊断应用层协议,它规定了诊断仪(Tester)与ECU(电子控制单元)之间进行诊断通信的会话规则、服务格式和响应机制。在DoIP(Diagnostic over Internet Protocol,基于IP网络的诊断)的传输基础上,UDS协议是诊断逻辑的真正载体。理解UDS协议的核心三要素——服务ID(SID)、子功能(Sub-function)和正负响应码(Positive/Negative Response Code),是进行ECU刷写、故障读取、数据标定和产线检测的必备基础。本章将逐一拆解这三个核心概念,并结合DoIP场景下的实际应用进行深度解析。

UDS协议核心机制总览 诊断请求帧(Tester → ECU) SID(服务ID,1字节) Sub-function(子功能,1字节) Data(数据参数,0~N字节) 诊断响应帧(ECU → Tester) SID + 0x40(正响应) 0x7F(负响应) NRC(负响应码,1字节) ECU处理 子功能字节(1 Byte)结构 Bit 7 Bit 6 ~ Bit 0(子功能值) Bit7=0:抑制正响应(suppressPosRspMsg) Bit7=1:正常响应(需回复正响应) 响应码分类 正响应(SID+0x40) 负响应(0x7F+NRC) NRC 0x10~0x7F:服务/子功能/条件错误 NRC 0x22~0x7F:数据/安全/时序错误 DoIP + UDS 典型诊断流程 ① 建立TCP连接(端口13400) ② 发送UDS请求(SID+Sub+Data) ③ ECU校验并执行 ④ 返回正响应(SID+0x40+数据) ⑤ 或返回负响应(0x7F+NRC) ⑥ 诊断仪解析并显示结果

3.1 服务ID(SID)——诊断服务的“操作码”

3.1.1 核心原理:SID是UDS协议的命令字

SID(Service Identifier)是UDS请求帧的第一个字节,用于标识诊断仪希望ECU执行的服务类型。它类似于计算机指令集中的操作码(Opcode),决定了后续数据参数的解释方式。ISO 14229-1定义了从0x00到0x7E的标准服务ID范围,其中常用的服务包括:0x10(诊断会话控制)、0x22(按ID读取数据)、0x2E(按ID写入数据)、0x27(安全访问)、0x31(例程控制)、0x34(请求下载)、0x36(传输数据)、0x37(请求传输退出)、0x3E(测试仪在线)等。在DoIP场景下,SID被封装在DoIP消息的Payload中,通过TCP或UDP端口13400传输。

每个SID都有明确的请求格式和响应格式。例如,0x22服务的请求格式为:SID(0x22)+ DID(2字节数据标识符),响应格式为:SID+0x40(即0x62)+ DID + 数据。SID的设计遵循“请求-响应”的严格配对原则,ECU必须根据收到的SID类型执行对应的内部逻辑。

3.1.2 判断方法:SID的合法性与服务映射

诊断仪在发送请求前,需要确认目标ECU是否支持该SID。判断方法包括:

  • 会话状态检查:某些SID仅在特定诊断会话(默认会话、编程会话、扩展会话)下可用。例如,0x34(请求下载)通常只在编程会话中允许。
  • 功能寻址与物理寻址:物理寻址(Physical Addressing)时,SID必须被目标ECU支持;功能寻址(Functional Addressing)时,SID必须被多个ECU同时支持,且通常只允许无子功能或子功能为0x00的服务。
  • 安全等级检查:涉及写入或刷写的服务(如0x2E、0x34、0x36)通常需要先通过0x27安全访问解锁。

ECU收到SID后,会先检查SID是否在自身支持的服务列表中。若SID无效或未定义,ECU将返回负响应码0x11(serviceNotSupported)。

3.1.3 案例拆解:0x22服务读取VIN码

假设诊断仪需要读取车辆的VIN码(车辆识别码),VIN码存储在ECU的0xF190数据标识符中。诊断仪发送的请求帧为:22 F1 90。ECU收到后,解析SID为0x22,确认支持该服务,且当前会话允许读取,则返回正响应:62 F1 90 4C 54 47 56 48 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35。其中0x62是正响应SID(0x22+0x40),0xF190是DID,后续字节为ASCII编码的VIN码。若ECU不支持0x22服务,则返回7F 22 11,表示服务不支持。

3.1.4 常见误区与总结

误区1:将SID与DID混淆。SID是服务类型,DID是数据标识符,一个服务可以访问多个DID。
误区2:忽略会话状态直接发送服务请求。例如在默认会话下发送0x34请求下载,ECU会返回0x7F 0x34 0x7F(serviceNotSupportedInActiveSession)。
误区3:在DoIP中错误地使用UDP发送UDS请求。UDS请求通常使用TCP以保证可靠性,除非是广播类诊断(如功能寻址)才使用UDP。

3.2 子功能(Sub-function)——服务的“参数化开关”

3.2.1 核心原理:子功能扩展服务能力

子功能是请求帧的第二个字节(如果服务支持子功能),用于进一步细化服务的行为。子功能字节的最高位(Bit 7)具有特殊含义:当Bit 7为1时,表示抑制正响应(suppressPosRspMsg),即ECU执行服务后不发送正响应,只发送负响应(如果出错);当Bit 7为0时,ECU必须发送正响应。Bit 6~Bit 0用于表示具体的子功能值,范围从0x00到0x7F。

例如,0x10服务(诊断会话控制)的子功能包括:0x01(默认会话)、0x02(编程会话)、0x03(扩展会话)。0x31服务(例程控制)的子功能包括:0x01(启动例程)、0x02(停止例程)、0x03(查询例程结果)。子功能的设计使得一个SID可以承载多种操作模式,减少了SID的数量,提高了协议的可扩展性。

3.2.2 判断方法:子功能与SID的匹配规则

并非所有SID都支持子功能。例如,0x22(按ID读取数据)和0x2E(按ID写入数据)不支持子功能,请求帧中SID后直接跟DID。而0x10、0x27、0x31、0x3E等服务必须包含子功能字节。判断方法如下:

  1. 查阅ISO 14229-1标准或ECU的诊断规范,确认该SID是否支持子功能。
  2. 若支持,检查子功能值是否在ECU支持的范围内。例如,0x10服务的子功能0x04(扩展诊断会话)在某些ECU中可能不支持。
  3. 检查Bit 7的抑制正响应位。若置1,则ECU不发送正响应,但诊断仪仍需等待负响应(如果出错)或超时处理。

3.2.3 案例拆解:0x10服务切换会话

在DoIP刷写场景中,诊断仪需要将ECU从默认会话切换到编程会话。请求帧为:10 02(0x10是SID,0x02是编程会话子功能,Bit 7为0表示需要正响应)。ECU收到后,执行会话切换,返回正响应:50 02 00 32 01 F4。其中0x50是正响应SID(0x10+0x40),0x02是子功能回显,0x0032是P2(Server)定时器值(50ms),0x01F4是P2*(Server)定时器值(500ms)。若ECU不支持编程会话,则返回7F 10 12(subFunctionNotSupported)。

如果诊断仪希望抑制正响应,可以发送10 82(0x82 = 0x02 | 0x80)。此时ECU执行会话切换,但不发送正响应。诊断仪需要自行判断是否切换成功(例如通过后续的0x3E服务或读取会话状态DID来确认)。

3.2.4 常见误区与总结

经验提示:在DoIP通信中,由于网络延迟和TCP重传机制,抑制正响应(Bit 7=1)可以显著减少总线负载,但必须确保诊断仪有超时重试机制。否则,如果ECU执行失败且未发送负响应(例如ECU崩溃),诊断仪将无法感知错误。
误区:将子功能值与DID混淆。子功能是服务级别的参数,DID是数据级别的标识符,两者作用域不同。

3.3 正响应码与负响应码(NRC)——诊断结果的“状态机”

3.3.1 核心原理:正负响应的编码规则

UDS协议规定,ECU对每个诊断请求必须给出响应。正响应的SID为请求SID加上0x40,例如请求SID为0x22,正响应SID为0x62;请求SID为0x2E,正响应SID为0x6E。正响应中通常包含请求回显的数据或执行结果。负响应的SID固定为0x7F,后跟请求的SID和1字节的NRC(Negative Response Code)。NRC用于指示ECU拒绝请求的具体原因。

NRC的取值范围为0x00~0xFF,其中0x00是保留值,0x10~0x7F是标准定义的错误码,0x80~0xFF是制造商自定义的错误码。常见的NRC包括:0x10(generalReject)、0x11(serviceNotSupported)、0x12(subFunctionNotSupported)、0x13(incorrectMessageLengthOrInvalidFormat)、0x22(conditionsNotCorrect)、0x31(requestOutOfRange)、0x33(securityAccessDenied)、0x35(invalidKey)、0x36(exceedNumberOfAttempts)、0x37(requiredTimeDelayNotExpired)、0x7F(serviceNotSupportedInActiveSession)等。

3.3.2 判断方法:NRC的排查逻辑

当诊断仪收到负响应时,需要根据NRC快速定位问题。排查逻辑如下:

NRC值含义常见触发场景排查建议
0x11服务不支持SID未定义或ECU未实现检查ECU诊断规范,确认SID是否有效
0x12子功能不支持子功能值超出范围检查子功能定义,确认是否支持该模式
0x13报文长度或格式错误请求帧长度与SID要求不符核对请求帧字节数,检查DID长度
0x22条件不满足会话状态、安全等级、电压条件等不满足检查当前会话、安全解锁状态、ECU运行条件
0x31请求超出范围DID不存在、数据值超出上下限检查DID范围和数据有效性
0x33安全访问被拒绝未解锁或密钥错误先执行0x27安全访问流程
0x7F当前会话不支持在默认会话下发送编程会话专属服务先切换会话再发送请求

3.3.3 案例拆解:0x2E写入DID失败排查

场景:诊断仪尝试通过0x2E服务向ECU写入DID 0xF190(VIN码),请求帧为2E F1 90 4C 54 47 56 48 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35。ECU返回负响应7F 2E 22(conditionsNotCorrect)。

分析过程:

  1. 检查当前会话:ECU处于默认会话(0x01),而0x2E写入服务通常需要在扩展会话(0x03)或编程会话(0x02)下执行。
  2. 检查安全等级:0x2E写入操作需要安全访问解锁(0x27服务),当前ECU处于锁定状态。
  3. 检查DID属性:0xF190在ECU中定义为只读DID,不允许写入。

解决步骤:先发送10 03切换到扩展会话,再执行27 01安全访问解锁(发送种子和密钥),最后重新发送0x2E写入请求。若仍失败,检查写入数据的长度和格式是否符合DID定义。

3.3.4 常见误区与总结

复盘要点:NRC是诊断排障的“第一现场”。在DoIP环境下,由于网络层可能引入超时或重传,诊断仪必须区分“ECU未响应”和“ECU返回负响应”两种情况。前者可能是网络故障或ECU忙,后者是ECU明确拒绝。建议在诊断仪中建立NRC统计表,按频率排序,优先解决高频NRC。
误区:将0x7F误认为是负响应SID。0x7F是负响应的固定SID,真正的错误原因在NRC字节中。例如7F 22 31表示0x22服务返回0x31错误(请求超出范围),而不是0x7F服务。

3.4 三要素协同:构建完整的诊断请求-响应链路

3.4.1 核心原理:SID、子功能、NRC的联动关系

在实际诊断中,SID、子功能和NRC不是孤立的。SID决定了服务的类型,子功能决定了服务的行为模式,NRC则反映了ECU对请求的接受程度。三者共同构成了UDS协议的状态机。例如,0x31服务(例程控制)的子功能0x01(启动例程)在ECU执行过程中,如果例程内部参数错误,ECU可能返回0x31(requestOutOfRange);如果例程需要安全解锁,则返回0x33(securityAccessDenied)。诊断仪必须根据NRC动态调整请求策略。

3.4.2 操作流程:诊断请求的完整处理流程

  1. 构建请求帧:根据诊断需求,确定SID、子功能(如有)和数据参数。
  2. 封装DoIP消息:将UDS请求放入DoIP Payload中,添加DoIP头部(版本、类型、长度等)。
  3. 发送并等待响应:通过TCP发送,等待ECU的响应帧。若超时(P2/P2*定时器),则重试或报错。
  4. 解析响应帧:检查响应SID。若为SID+0x40,则处理正响应数据;若为0x7F,则解析NRC并执行对应处理。
  5. 状态更新:根据响应结果更新诊断会话状态、安全等级、故障码等。

3.4.3 实战场景:DoIP刷写流程中的三要素应用

在OTA(Over-The-Air)刷写场景中,诊断仪需要依次执行:0x10(切换到编程会话)→ 0x27(安全访问解锁)→ 0x31(擦除Flash例程)→ 0x34(请求下载)→ 0x36(传输数据)→ 0x37(请求传输退出)→ 0x11(ECU复位)。每一步都可能返回不同的NRC。例如,0x34请求下载时,若内存地址超出范围,ECU返回0x31;若安全等级不足,返回0x33;若当前会话不是编程会话,返回0x7F。诊断仪需要根据NRC决定是重试、切换会话还是终止刷写。

3.4.4 常见误区与总结

关键提醒:在DoIP中,UDS请求的响应时间受网络延迟影响。ECU的P2定时器(默认50ms)和P2*定时器(默认5000ms)是诊断仪等待响应的超时基准。如果网络延迟较大,诊断仪应适当延长超时时间,但不应超过ECU的P2*限制。否则,ECU可能认为诊断仪已离线,主动关闭TCP连接。
总结:掌握SID、子功能和NRC的解析,是UDS协议栈开发的第一步。建议在实际项目中,建立一张“SID-子功能-NRC”映射表,并针对每个服务编写单元测试用例,覆盖正响应和常见负响应路径。