2. UDS基础概念
UDS(Unified Diagnostic Services,统一诊断服务)是ISO 14229标准定义的一套应用层诊断协议,广泛应用于汽车电子控制单元(ECU)的故障诊断、刷写、配置和标定等场景。要真正理解UDS的工作方式,必须首先厘清它在OSI七层模型中的位置,以及构成其报文核心的三个基本要素:服务ID(SID)、子功能(Sub-function)和正/负响应机制。本章将围绕这三个核心概念展开,帮助学员建立UDS诊断协议的基础认知框架,为后续学习具体的诊断服务(如读取故障码、读写数据、例程控制等)打下坚实基础。
上图展示了UDS在OSI模型中的定位以及报文的基本构成。从图中可以看到,UDS位于应用层,其报文通过传输层(CAN TP或DoIP)进行分段和重组,最终经由物理层传输。右侧的报文结构示意了UDS请求帧的核心字段:CAN ID用于寻址,PCI字段控制报文长度,SID和子功能标识具体的服务及变体,数据参数则承载服务所需的输入输出信息。正负响应机制则保证了每一次请求都有明确的反馈,无论是成功执行还是拒绝原因,ECU都会给出对应的响应帧。
2.1 核心原理:OSI模型中的诊断层定位
OSI(Open Systems Interconnection)参考模型将网络通信划分为七层,从物理层到应用层。在汽车诊断领域,UDS协议被明确定义为应用层协议,即第七层。但这并不意味着它只关心应用逻辑——UDS的设计与底层传输介质紧密相关,不同的物理层和传输层会直接影响UDS报文的封装方式和寻址策略。
在实际车载网络中,UDS最常见的底层载体是CAN总线(Controller Area Network)。由于CAN单帧数据场最多只能承载8字节(经典CAN)或64字节(CAN FD),当诊断数据超过单帧容量时,就需要借助传输层协议ISO 15765-2(即CAN TP)进行多帧传输。CAN TP负责将应用层的UDS消息分割为多个CAN帧,并在接收端重组为完整的UDS报文。对于基于以太网的诊断(DoIP,Diagnostic over IP),UDS则直接承载于TCP或UDP之上,利用IP网络的寻址能力实现远程诊断。
理解OSI分层对诊断测试的意义在于:当测试人员遇到报文丢失、超时或数据错乱时,需要能够快速定位问题发生在哪一层。例如,如果CAN物理层受到电磁干扰导致信号畸变,应用层的UDS可能表现为响应超时或CRC错误;如果CAN TP的接收缓冲区溢出,则可能出现多帧报文重组失败。因此,UDS测试不仅仅是应用层的功能验证,还需要结合底层协议栈进行综合分析。
诊断层定位要点:
- 应用层(L7):UDS服务定义、正负响应逻辑、会话管理、安全访问等。
- 传输层(L4):CAN TP(ISO 15765-2)负责分段/重组;DoIP(ISO 13400)负责TCP/UDP封装。
- 网络层(L3):CAN网络中的逻辑寻址(物理寻址/功能寻址);以太网中的IP地址和端口。
- 数据链路层(L2):CAN控制器、MAC层、VLAN(以太网)等。
- 物理层(L1):CAN收发器、100BASE-TX/1000BASE-T物理接口。
2.2 服务ID(SID)与子功能
服务ID(Service Identifier,SID)是UDS报文中的第一个字节,用于标识ECU需要执行的服务类型。ISO 14229-1定义了从0x00到0x7E的标准服务ID范围,其中0x10(诊断会话控制)、0x22(读取数据标识符)、0x2E(写入数据标识符)、0x27(安全访问)、0x31(例程控制)、0x34/0x36/0x37(请求下载/传输数据/请求退出传输)等是开发中最常用的服务。每个SID都有明确的请求格式和响应格式,且响应帧的SID为请求SID加上0x40。
子功能(Sub-function)是紧随SID之后的第二个字节,用于进一步细化服务的操作类型。子功能字节的最高位(Bit 7)被定义为抑制正响应位(Suppress Positive Response,SPR)。当SPR=1时,ECU执行服务后不发送正响应帧,仅在有错误时发送负响应;当SPR=0时,ECU正常发送正响应。这一机制在刷写场景中非常实用——例如在批量传输数据时,测试工具可以设置SPR=1以减少总线负载,提高刷写效率。
子功能编号(Bit 6-0)的具体含义由每个服务独立定义。以0x10服务(诊断会话控制)为例,子功能0x01表示默认会话,0x02表示编程会话,0x03表示扩展诊断会话。不同的会话模式下,ECU允许执行的服务集合不同。例如,编程会话通常用于Bootloader刷写,此时禁止执行常规的读写数据服务,但允许执行0x34/0x36等传输服务。
| SID | 服务名称 | 子功能示例 | 典型应用场景 |
|---|---|---|---|
| 0x10 | 诊断会话控制 | 0x01默认/0x02编程/0x03扩展 | 切换ECU工作模式 |
| 0x22 | 读取数据标识符 | 无子功能(直接跟DID) | 读取电压、温度、VIN码等 |
| 0x27 | 安全访问 | 0x01请求种子/0x02发送密钥 | 解锁受保护的服务 |
| 0x31 | 例程控制 | 0x01启动/0x02停止/0x03请求结果 | 执行自检、清除学习值 |
| 0x34 | 请求下载 | 无子功能(跟数据格式和大小) | 刷写前置准备 |
2.3 正响应与负响应机制
UDS协议采用请求-响应模型,即测试工具(Client)发送请求帧,ECU(Server)返回响应帧。响应帧分为正响应和负响应两种类型。正响应帧的SID为请求SID+0x40,表示服务已成功执行,并携带服务执行结果的数据。例如,请求0x22读取VIN码,正响应帧为0x62 + DID + VIN数据。
负响应帧的SID固定为0x7F,紧随其后的是请求的SID和负响应码(Negative Response Code,NRC)。NRC是一个单字节值,用于指示ECU拒绝执行服务的原因。ISO 14229-1定义了从0x00到0xFF的NRC范围,其中0x10(一般拒绝)、0x11(服务不支持)、0x12(子功能不支持)、0x13(请求长度错误)、0x22(条件不满足)、0x31(请求超出范围)、0x33(安全访问被拒绝)、0x35(密钥不匹配)、0x72(一般编程失败)等是常见的错误码。
正负响应机制的设计哲学在于:ECU必须对每一个请求给出明确的反馈,不能静默丢弃。这为诊断测试提供了可判定性——测试工具可以根据响应帧的类型和NRC码,自动判断ECU的行为是否符合预期。例如,在自动化测试中,如果发送了0x27安全访问请求,期望得到正响应0x67,但实际收到0x7F 0x27 0x35,则说明密钥错误,测试用例应判定为失败。
经验提醒:在编写自动化测试脚本时,建议将NRC码映射为可读的枚举类型,并建立NRC与可能原因的对照表。例如,NRC 0x22(条件不满足)通常意味着ECU当前状态不允许执行该服务,可能是会话模式不对、安全等级不够或前置条件未满足。测试人员应结合ECU的状态机设计来定位问题。
2.4 案例拆解:一个完整的诊断会话切换与安全访问流程
为了将上述概念串联起来,我们以一个典型的ECU刷写前置流程为例,展示UDS请求/响应帧的完整交互过程。假设测试工具需要将ECU从默认会话切换到编程会话,并执行安全访问解锁。
步骤1:切换会话
请求: 0x10 0x02 (SID=0x10, 子功能=0x02 编程会话)
响应: 0x50 0x02 0x00 0x32 0x01 0xF4 (正响应, P2=50ms, P2*=500ms)
ECU返回正响应0x50,并携带了定时参数P2(服务器响应时间)和P2*(增强型响应时间)。这些参数告诉测试工具,ECU在50ms内会响应常规请求,在500ms内会响应增强型请求(如擦除Flash)。
步骤2:请求种子
请求: 0x27 0x01 (SID=0x27, 子功能=0x01 请求种子)
响应: 0x67 0x01 0x1A 0x2B 0x3C 0x4D (正响应, 种子=0x1A2B3C4D)
ECU返回一个4字节的随机种子。测试工具需要根据约定的密钥算法(通常是AES或自定义的移位/异或算法)计算出密钥。
步骤3:发送密钥
请求: 0x27 0x02 0x5E 0x7A 0x91 0x23 (SID=0x27, 子功能=0x02 发送密钥)
响应: 0x67 0x02 (正响应, 安全访问已解锁)
如果密钥正确,ECU返回正响应0x67 0x02,安全等级提升。如果密钥错误,ECU会返回负响应0x7F 0x27 0x35,并且通常会启动延时计数器,防止暴力破解。
步骤4:验证会话状态
请求: 0x22 0xF1 0x90 (读取当前会话模式)
响应: 0x62 0xF1 0x90 0x02 (当前为编程会话)
通过读取数据标识符0xF190确认ECU已处于编程会话且安全等级已解锁,此时可以继续执行0x34请求下载等后续刷写步骤。
风险提示:在实际刷写过程中,如果安全访问失败次数超过ECU设定的阈值(通常为3次),ECU会进入延时锁定状态,可能长达数分钟甚至数小时。自动化测试脚本必须处理这种异常场景,避免因连续失败导致ECU被锁定,影响产线节拍。
2.5 常见误区与总结复盘
在UDS基础概念的学习和测试实践中,初学者常犯以下几类错误,需要特别警惕:
- 混淆SID与DID:SID是服务标识,DID是数据标识符。0x22是服务,0xF190是DID。测试脚本中必须区分请求的服务和该服务操作的数据对象。
- 忽略SPR位:当子功能字节的最高位为1时,ECU不发送正响应。如果测试工具未考虑这一点,可能会误判为超时。在自动化测试中,应明确记录每个请求的SPR设置。
- NRC码理解片面:同一个NRC码在不同服务下可能有不同的触发条件。例如NRC 0x13(请求长度错误)在0x22服务中表示DID长度不对,在0x2E服务中可能表示数据长度超出范围。测试人员应结合具体服务的规范来解读NRC。
- 忽视会话状态约束:某些服务只能在特定会话模式下执行。例如0x34请求下载通常只能在编程会话中执行。如果在默认会话中发送0x34,ECU会返回NRC 0x7F 0x34 0x22(条件不满足)。