3. 诊断协议核心概念

在ECU诊断测试自动化工程中,UDS(Unified Diagnostic Services,ISO 14229)是绝大多数诊断交互的协议基础。自动化脚本能否稳定执行,取决于工程师是否真正理解UDS的服务语义、会话状态机、安全访问机制,以及DTC、DID、例程控制等数据对象如何被寻址和读写。本节把这些核心概念串成一条可落地的知识链,为后续测试用例设计、脚本封装和故障排查打基础。

一、UDS服务:诊断请求的“动词”

UDS把诊断功能抽象为服务(Service),每个服务由1字节SID(Service Identifier)标识。请求格式通常为 SID + 子功能 + 参数,正响应为 SID+0x40 + 子功能 + 数据,负响应固定为 0x7F + SID + NRC。自动化脚本最常打交道的服务包括:

  • 0x10 诊断会话控制:切换默认会话、编程会话、扩展会话。
  • 0x27 安全访问:请求种子(Seed)并发送密钥(Key)解锁受保护服务。
  • 0x22 / 0x2E:按DID读/写数据。
  • 0x19:读取DTC信息,子功能决定读数量、快照或扩展数据。
  • 0x14:清除DTC。
  • 0x31:例程控制,用于执行自检、标定、学习等动作。
  • 0x3E:TesterPresent,维持非默认会话不被超时踢回。

理解SID与子功能的组合关系,是编写诊断请求报文的第一步。例如读取VIN通常写作 22 F1 90,其中F190是VIN对应的DID。

二、会话与安全访问:状态机的两道门

UDS不是无状态协议。ECU内部维护会话状态,默认会话(0x01)权限最低,扩展会话(0x03)开放大部分诊断服务,编程会话(0x02)用于刷写。会话切换由0x10服务完成,且存在S3超时(通常5秒),超时后自动回默认会话。自动化脚本若在扩展会话中执行长流程,必须周期性发送 3E 80 保持会话。

安全访问是第二道门。0x27服务采用“种子—密钥”挑战机制:测试端先请求种子,ECU返回随机数;测试端用约定算法计算密钥并回送;ECU校验通过后解锁。不同安全级别对应不同子功能,例如 27 01 请求种子、27 02 发送密钥。自动化中必须实现与ECU一致的密钥算法,否则会收到NRC 0x35(invalidKey)。

常见误区:把安全访问当成“登录一次永久有效”。实际上会话切换、ECU复位或超时都会重新锁定,脚本必须在每个需要权限的用例前确认解锁状态。

三、DTC、DID与例程控制:诊断数据对象

DTC(Diagnostic Trouble Code)是故障码,通常为3字节,配合状态字节(如testFailed、confirmedDTC)表达故障生命周期。0x19服务的子功能02读取DTC数量、04读取快照、06读取扩展数据、0A读取全部支持的DTC。清除故障用0x14,可指定3字节DTC或 FF FF FF 清全部。

DID(Data Identifier)是2字节的数据标识,用于访问ECU内部参数,如软件版本、VIN、传感器原始值。0x22读、0x2E写,写操作通常需要安全解锁和扩展会话。

例程控制0x31用于触发ECU内部动作,格式为 31 + 子功能 + routineIdentifier + 参数。子功能01启动、02停止、03请求结果。典型场景包括执行执行器自检、学习离合器零点、擦除Flash等。例程往往有执行时长,脚本需要轮询结果或等待正响应。

四、通信参数与寻址方式:报文如何到达ECU

UDS本身是应用层协议,实际传输依赖底层总线。诊断报文在CAN上使用ISO-TP(ISO 15765-2)分段传输,关键参数包括:

参数含义典型值
请求ID测试端发送诊断请求的CAN ID0x7DF(功能寻址)
响应IDECU返回诊断响应的CAN ID0x7E8~0x7EF
STmin连续帧最小间隔0~127ms
BS块大小,连续帧数量0或8
P2/P2*响应超时与增强超时50ms / 5000ms

寻址方式分为物理寻址和功能寻址。物理寻址一对一,用于读取具体ECU数据;功能寻址一对多,常用于0x10、0x3E、0x14等广播型服务。功能寻址时多个ECU可能同时响应,脚本需按响应ID区分来源。

# 典型诊断请求与响应(CAN ID + 数据)
请求: 7DF  02 10 03        # 功能寻址,进入扩展会话
响应: 7E8  06 50 03 00 32 01 F4
请求: 7E0  02 27 01        # 物理寻址,请求安全种子
响应: 7E8  06 67 01 12 34 56 78
请求: 7E0  06 27 02 87 65 43 21  # 发送密钥
响应: 7E8  02 67 02        # 安全解锁成功

五、综合案例:一次自动化诊断流程

假设要自动化读取某ECU的软件版本并清除历史故障,脚本流程如下:

  1. 发送 10 03 进入扩展会话,检查正响应 50 03。
  2. 发送 27 01 请求种子,用算法计算密钥后发送 27 02 解锁。
  3. 发送 22 F1 89 读取软件版本DID,解析响应数据。
  4. 发送 19 02 FF 读取DTC数量,确认存在历史故障。
  5. 发送 14 FF FF FF 清除全部DTC。
  6. 再次发送 19 02 FF 验证DTC数量为0。
  7. 发送 3E 80 保持会话,或发送 10 01 回到默认会话。
自动化脚本应把“会话状态”和“安全状态”作为上下文变量维护,而不是每次盲目重发。这样既能减少总线负载,也能避免因状态不一致导致的随机失败。

六、误区与复盘

第一,忽略NRC含义。NRC 0x78表示响应挂起,不是失败,脚本应继续等待;NRC 0x33表示安全拒绝,需检查解锁流程。第二,混淆物理寻址与功能寻址,导致请求发给了错误的ECU或收到多份响应。第三,把DID和例程ID混用,二者都是标识符但服务不同。第四,未处理ISO-TP流控,长报文读取时丢帧。第五,安全算法硬编码在脚本中,未做参数化,换车型即失效。

掌握这些核心概念后,诊断自动化就不再是“拼报文”,而是基于状态机、数据对象和通信参数的系统工程。后续章节将在此基础上展开测试框架设计与脚本实现。

UDS诊断核心概念关系图 诊断测试端 Tester / 自动化脚本 CANoe / Python-uds 通信与寻址 ISO-TP / CAN / DoIP 物理寻址 · 功能寻址 目标ECU UDS协议栈 应用层服务处理 请求 传输 响应 会话与安全访问 0x10 会话控制 默认 / 扩展 / 编程会话 0x27 种子—密钥解锁 0x3E 保持会话 诊断数据对象 DTC:0x19读 / 0x14清 DID:0x22读 / 0x2E写 例程:0x31启动/停止/结果 快照 · 扩展数据 · 状态字节 通信参数 请求ID / 响应ID STmin / BS 流控 P2 / P2* 超时 S3 会话超时 典型自动化诊断流程 10 03 扩展会话 27 01/02 安全解锁 22 F1 89 读DID 19 02 FF 读DTC 14 FF FF FF 清DTC 每步校验正响应;NRC 0x78 继续等待;NRC 0x33 检查安全状态