UDS 19服务详解:从DTC状态掩码到快照与扩展数据
2026/9/2 22:00:14 网站建设 项目流程

在实际车载诊断项目里,第一次接触 UDS 的朋友,看到“19 02 FF”或“19 04 0A 05 01”这类报文时,很容易被参数和响应结构绕晕。19 服务是 UDS 中读取故障码信息的核心服务,涵盖数量统计、故障码列表、快照记录、扩展数据等多个子功能。本文以 19 服务的 01、02、04、06 四个高频子功能为主线,结合请求报文和正/负响应报文实例,完整拆解每一帧的含义、参数设计和排查思路。

如果你是刚接触 UDS 诊断协议的学生、测试工程师,或者正在做 ECU 刷写、产线检测、售后诊断工具开发的开发者,这篇文章都适用。看完之后,你不仅知道“怎么发”,还能理解“为什么这样设计”。

1. 19服务是什么:从UDS诊断体系说起

1.1 UDS诊断协议定位

UDS(Unified Diagnostic Services,统一诊断服务)是 ISO 14229 标准定义的一套汽车诊断协议,目前在整车电子电气架构中基本属于标配。它在 OSI 七层模型中位于应用层,底层可以承载在 CAN、CAN FD、LIN、以太网(DoIP)等不同的传输层协议上。

在 UDS 的协议框架里,服务通过 SID(Service Identifier,服务标识符)区分。例如 0x10 是诊断会话控制,0x22 是按标识符读取数据,0x27 是安全访问,0x14 是清除故障码,0x19 则是读取故障码信息。

每个服务还可以细分为不同的子功能,19 服务是整个 UDS 体系中结构最丰富、使用频率最高的服务之一。故障码的产生、确认、恢复、历史存储、环境数据记录,都要依赖 19 服务来读取。

1.2 19服务解决什么问题

ECU(Electronic Control Unit,电子控制单元)在运行过程中会持续监控传感器、执行器、通信链路的状态。当某个监测项超出阈值或逻辑不满足时,ECU 内部会记录一个 DTC(Diagnostic Trouble Code,诊断故障码),并在状态字节中标记故障类型。

但记录 DTC 只是第一步,诊断人员还需要知道:

  • 当前 ECU 一共存了多少条 DTC?
  • 这些 DTC 是当前激活的还是历史残留的?
  • 每个 DTC 对应的故障状态、发生次数、行驶里程、环境温度等附加信息是什么?
  • 怎么在清除 DTC 之前把现场数据保存下来,方便复现和分析?

这些诉求全部由 19 服务来承载。所以 19 服务的核心定位就是:按条件读取 DTC 相关信息

1.3 19服务子功能总览

19 服务下有多个子功能,不同子功能获取的信息粒度不同。本文重点讲解实际项目中最常用的 4 个:

子功能名称作用
0x01reportNumberOfDTCByStatusMask按状态掩码统计 DTC 数量
0x02reportDTCByStatusMask按状态掩码返回 DTC 列表
0x04reportDTCSnapshotRecordByDTCNumber返回指定 DTC 的快照记录
0x06reportDTCExtDataRecordByDTCNumber返回指定 DTC 的扩展数据记录

简单理解:01 是“数一下有多少条”,02 是“把故障码列出来”,04 是“查看某个故障码发生时的现场快照”,06 是“查看某个故障码的附加统计信息”。这几类信息组合起来,基本能覆盖故障诊断和售后分析的绝大多数场景。

2. 必须理解的基础概念:DTC、状态字节与状态掩码

2.1 DTC常见格式

在传统 CAN 诊断系统中,最常用的是 ISO 15031-6 规定的 2 字节 DTC 格式。例如 0x0A05、0x0A06、0x12AA 这类数值。2 字节 DTC 中的高 2 位用于表示故障类型,例如:

  • 00:P 开头(动力系统)
  • 01:C 开头(底盘系统)
  • 10:B 开头(车身系统)
  • 11:U 开头(网络通信系统)

剩余位用于表示具体的故障编号和子类型。

随着 ISO 14229-1:2020 标准的更新,DTC 也可以使用 3 字节格式,其中第三字节用于描述故障的具体类型,例如“信号无效”“信号超时”“信号不合理”等。目前很多新平台已经在使用 3 字节 DTC,但对于老平台和现产车,2 字节 DTC 仍然大量存在。

在 19 服务的响应中,DTCFormatIdentifier(DTC 格式标识符)字段用于告知调用方当前 ECU 使用的 DTC 格式。例如 0x00 通常表示 ISO 14229-1 定义的标准格式。读者在实际开发时,必须先确认目标项目使用的是 2 字节还是 3 字节 DTC,否则解析 DTC 列表时会出现错位。

2.2 DTC状态字节每一位的含义

DTC 状态字节是 19 服务中最重要的概念之一。它不只表示“是不是有故障”,而是一个包含 8 个独立含义的位域,每一位都代表一种诊断状态。

以 2 字节 DTC + 1 字节状态为例,状态字节定义如下:

Bit掩码值含义
bit00x01testFailed:最近一次测试失败
bit10x02testFailedThisOperationCycle:当前操作循环中测试失败
bit20x04pendingDTC:待确认故障码
bit30x08confirmedDTC:已确认故障码
bit40x10testNotCompletedSinceLastClear:上次清除后测试未完成
bit50x20testFailedSinceLastClear:上次清除后测试失败过
bit60x40testNotCompletedThisOperationCycle:当前操作循环测试未完成
bit70x80warningIndicatorRequested:请求点亮故障指示灯

实际报文中一个状态字节可能同时包含多位。例如 0x45 表示 bit0、bit2、bit6 置位,即“最近测试失败 + 待确认 + 当前循环未完成”。这里的组合逻辑完全取决于故障检测策略,不同 ECU 可能给出不同的状态组合。

2.3 状态掩码如何筛选目标DTC

19 服务的 01 和 02 子功能都要求调用方传入一个状态掩码,用于筛选想要查看的 DTC。例如:

  • 状态掩码 0xFF:匹配所有状态位,返回全部 DTC。
  • 状态掩码 0x08:只匹配 confirmedDTC 位,即只返回已确认的 DTC。
  • 状态掩码 0x04:只匹配 pendingDTC 位,即只返回待确认的 DTC。
  • 状态掩码 0x29:匹配 bit0、bit3、bit5,即返回最近测试失败且已确认的 DTC。

筛选的原理是对状态字节做按位与运算。只要状态字节与掩码的与结果不为 0,该 DTC 就满足查询条件。这里容易误以为 19 服务返回的 DTC 状态必须完全等于掩码值,实际上并不是,正确理解是“状态字节与掩码按位与后非 0”。

因此,在工程中查询“所有 DTC”时,一般直接使用 0xFF;查询“有效故障”时,优先使用包含 confirmedDTC(bit3)的掩码,例如 0x09 或 0x0D;查询“历史故障”时,配合 testFailedSinceLastClear(bit5)、confirmedDTC(bit3)等位一起判断。

2.4 会话控制与安全访问预备知识

19 服务通常在默认会话下就允许调用,但存在一些限制:

  • 部分 ECU 只在扩展诊断会话或编程会话下开放 19 服务的某些子功能。
  • 读取某些敏感 DTC 或环境数据时,可能需要先执行 0x27 安全访问,完成解锁后再发 19 请求。
  • 如果车辆处于行驶模式或总线通信繁忙状态,ECU 可能因为内部条件不满足,返回 NRC 0x22(conditionsNotCorrect)。

所以在排查 19 服务异常响应时,不要一上来就怀疑报文格式,先确认当前诊断会话状态以及是否已解锁安全访问。这也是很多初学者最容易忽略的点。

3. 子功能01:报告DTC数量

3.1 功能说明与请求格式

子功能 01 的名称是 reportNumberOfDTCByStatusMask,作用是让 ECU 统计符合条件的 DTC 数量。它只返回数量,不返回具体 DTC 内容,因此报文很短。

请求报文格式如下:

字节位置内容说明
byte00x19SID,读 DTC 信息
byte10x01子功能:报告 DTC 数量
byte2状态掩码筛选规则,例如 0xFF

举一个最简单的例子,发一帧 CAN 请求:

19 01 FF
  • 0x19:服务 ID
  • 0x01:子功能 01
  • 0xFF:状态掩码,匹配所有状态

这里如果使用物理寻址,请求报文 ID 通常是指向目标 ECU 的诊断物理请求 ID(例如 0x7E0),实际值取决于整车网络设计。如果使用功能寻址(例如 0x7DF),总线上的多个 ECU 都可能响应,需要特别注意响应冲突。

3.2 正响应报文结构

ECU 收到 19 01 请求后,如果支持该子功能且参数合法,会返回正响应:

字节位置内容说明
byte00x59正响应 SID,等于请求 SID + 0x40
byte10x01子功能回显
byte2DTCFormatIdentifierDTC 格式标识
byte3numberOfDTC_HighByteDTC 数量高字节
byte4numberOfDTC_LowByteDTC 数量低字节
byte5statusOfDTC回显请求中的状态掩码

其中 numberOfDTC 是两字节大端整数,最大可以表示 65535 个 DTC。statusOfDTC 字段回显请求掩码,用于告诉调用方这个数量是基于什么筛选条件统计出来的。

3.3 报文实例

假设某个 BMS(电池管理系统)内存有两条 DTC:0x0A05 和 0x0A06,发送 19 01 FF 后,正响应示意如下:

59 01 00 00 02 FF

逐字节解析:

  • 0x59:正响应 SID
  • 0x01:子功能回显,确认是 01 的响应
  • 0x00:DTCFormatIdentifier,表示 ISO 14229-1 标准格式
  • 0x00 0x02:DTC 数量为 2
  • 0xFF:回显状态掩码 0xFF

如果发送 19 01 04,只统计 pendingDTC 状态的故障码,而当前只有 0x0A05 处于 pending 状态,响应就可能是:

59 01 00 00 01 04

这里 DTC 数量变成了 1,状态掩码回显为 0x04。通过这种方式,诊断仪可以在不获取完整 DTC 列表的情况下,快速判断是否存在某个状态下的故障码。

4. 子功能02:报告DTC

4.1 功能说明与请求格式

子功能 02 的名称是 reportDTCByStatusMask,作用是按状态掩码返回 DTC 列表以及每个 DTC 的状态字节。这是诊断工具显示故障码列表时最常用的请求。

请求报文格式如下:

字节位置内容说明
byte00x19SID
byte10x02子功能:报告 DTC
byte2状态掩码筛选规则,例如 0xFF

示例请求:

19 02 FF

这条报文的意思是:把当前 ECU 存储的所有 DTC 和状态返回给我。

4.2 正响应报文结构

19 02 的正响应相对复杂一些,因为它包含了一个变长的 DTC 列表。以 2 字节 DTC 格式为例:

字节位置内容说明
byte00x59正响应 SID
byte10x02子功能回显
byte2状态掩码回显请求中的 statusOfDTC
byte3DTCFormatIdentifierDTC 格式标识
byte4~byte5numberOfDTCDTC 总数量
byte6~byte8DTC1 + Status1第 1 条 DTC 和状态
byte9~byte11DTC2 + Status2第 2 条 DTC 和状态
......以此类推

每条 DTC 记录由 3 字节组成:2 字节 DTC 号 + 1 字节状态。如果响应很长,底层传输层会按照 ISO-TP 协议拆分成多帧发送。

4.3 报文实例

继续使用上述 BMS 的示例。请求:

19 02 FF

假设 ECU 返回单帧正响应:

59 02 FF 00 00 02 0A 05 45 0A 06 0A

逐字节解析:

  • 0x59:正响应 SID
  • 0x02:子功能回显
  • 0xFF:状态掩码回显
  • 0x00:DTC 格式标识
  • 0x00 0x02:共有 2 条 DTC
  • 0x0A 0x05:第 1 条 DTC 是 0x0A05
  • 0x45:DTC 0x0A05 的状态字节,示例状态值为 45
  • 0x0A 0x06:第 2 条 DTC 是 0x0A06
  • 0x0A:DTC 0x0A06 的状态字节,示例状态值为 0A

这里 0x45 表示 0100 0101,即 bit0、bit2、bit6 置位,代表“最近测试失败”“待确认”“当前循环测试未完成”。0x0A 表示 0000 1010,即 bit1、bit3 置位,代表“当前循环测试失败”且“已确认”。实际项目中状态字节的具体含义需要结合故障监测策略判断。

如果只查询已确认故障码,请求为:

19 02 08

响应可能只剩已确认的 DTC:

59 02 08 00 00 01 0A 06 0A

这里返回了 1 条 DTC,说明只有 0x0A06 处于 confirmed 状态。

4.4 多帧响应与缓冲区不足的处理

当 DTC 列表数量较大,或者 DTC 状态数据结构较长时,单帧 CAN 报文可能放不下,底层会自动使用 ISO-TP 多帧传输。在 CAN 2.0 中,单帧数据场最多 8 字节,而 19 02 的正响应很可能超过 8 字节,因此大部分项目都会进入多帧流程。

多帧传输包括首帧、连续帧和流控帧。工具侧需要正确解析 ISO-TP 层,才能把多个连续帧拼接成完整数据,再交给上层解析 19 02 的有效载荷。如果在 CANoe 等工具中看到 19 02 响应只返回了前半部分,通常是因为:

  • 没有正确配置 ISO-TP 接收缓冲区。
  • 测试工具的网络层没有启用接收流控能力。
  • 请求中未要求 ECU 拆分传输。

另外需要注意,19 02 响应中把 numberOfDTC 放在 DTC 列表前面,是为了让上位机可以预估数据长度。但由于一帧 CAN 报文很难装下全部 DTC,上位机不能只根据首帧长度判断列表结束,必须按 numberOfDTC 字段循环解析完整 DTC 记录。

5. 子功能04:报告快照记录

5.1 快照记录的概念和用途

快照记录(Snapshot Record)是故障发生瞬间 ECU 保存的一批环境数据。比如单体电压、SOC、电池温度、车速、总里程、系统电压等。

快照记录的意义在于,故障发生后,很多现场信息会随工况变化而消失。诊断人员通过读取快照,可以还原故障发生时的“现场”,从而判断故障原因。这是一种非常关键的诊断手段。

每个 DTC 可以关联一个或多个快照记录,快照记录编号从 1 开始。不同的快照记录可能代表不同工况或不同故障分类下的环境数据。

5.2 请求报文结构

子功能 04 的请求必须指定 DTC 号和快照记录号:

字节位置内容说明
byte00x19SID
byte10x04子功能:报告快照记录
byte2~byte3DTC number目标 DTC,例如 0x0A05
byte4快照记录号0x01 表示第 1 条快照,0xFF 表示全部

示例请求:

19 04 0A 05 01

含义:读取 DTC 0x0A05 的第 1 条快照记录。

5.3 正响应报文结构

19 04 正响应包含 DTC 信息以及一个快照记录参数列表。由于快照的数据内容由 OEM 自定义,所以参数标识符、参数长度和参数值都无法一概而论。报文中必须通过“参数标识符 + 参数长度 + 参数值”的方式组织数据,上位机才能逐个解析。

典型的正响应结构如下:

字节位置内容说明
byte00x59正响应 SID
byte10x04子功能回显
byte2~byte3DTC number当前 DTC
byte4statusOfDTCDTC 当前状态
byte5snapshotRecordNumber当前快照记录号
byte6参数项数量该快照中包含的参数个数
byte7~byteN参数列表多个“参数ID + 参数长度 + 参数值”

快照记录的核心是参数列表。只要数据组织方式一致,诊断工具就能把其中所有参数解析出来,并以表格或曲线形式展示给用户。

5.4 报文实例

假设 DTC 0x0A05 的第 1 条快照包含两个参数:电池组最高电压(参数标识符 0x01,长度 2 字节)和电池组最高温度(参数标识符 0x02,长度 1 字节)。

请求:

19 04 0A 05 01

正响应示例:

59 04 0A 05 45 01 02 01 02 03 E8 02 01 5A

逐字节解析:

  • 0x59:正响应 SID
  • 0x04:子功能回显
  • 0x0A 0x05:DTC 为 0x0A05
  • 0x45:DTC 当前状态字节
  • 0x01:当前快照记录号
  • 0x02:该快照包含 2 个参数
  • 0x01:第 1 个参数的标识符,表示“电池组最高电压”
  • 0x02:参数长度为 2 字节
  • 0x03 0xE8:参数值,即电压 1000(单位 0.1V,实际为 100.0V)
  • 0x02:第 2 个参数的标识符,表示“电池组最高温度”
  • 0x01:参数长度为 1 字节
  • 0x5A:参数值,即温度 90(单位 1℃,实际为 90℃)

从这个例子可以看出,19 04 的难点并不在于协议本身,而在于参数标识符和参数长度的 OEM 自定义规则。开发诊断工具时,需要先拿到对应 ECU 的诊断规范或 DBC/CDD 文件,才能正确翻译快照数据。

6. 子功能06:报告扩展数据记录

6.1 扩展数据记录的概念和用途

扩展数据记录(Extended Data Record)也是附加在 DTC 上的信息,但和快照记录略有不同。快照记录强调的是“故障发生瞬间的环境数据”,扩展数据则更偏向“统计与累计信息”。

常见的扩展数据包括:

  • 故障出现次数
  • 故障老化计数器
  • 故障第一次发生的时间或里程
  • 故障最后一次发生的时间或里程
  • 故障连续激活次数
  • 内存中循环测试的累计次数

扩展数据主要用于故障频次分析和老化评估。售后场景中,通过扩展数据可以知道某个故障码是偶发还是持续,是刚出现还是已经存在很长时间。

6.2 请求报文结构

子功能 06 的请求格式与 04 非常相似,也需要 DTC 号和扩展数据记录号:

字节位置内容说明
byte00x19SID
byte10x06子功能:报告扩展数据记录
byte2~byte3DTC number目标 DTC
byte4扩展数据记录号0x01 表示第 1 块扩展数据,0xFF 表示全部

示例请求:

19 06 0A 05 01

含义:读取 DTC 0x0A05 的第 1 块扩展数据记录。

6.3 正响应报文结构

19 06 的正响应与 19 04 类似:

字节位置内容说明
byte00x59正响应 SID
byte10x06子功能回显
byte2~byte3DTC number当前 DTC
byte4statusOfDTCDTC 当前状态
byte5扩展数据记录号当前记录号
byte6~byteN扩展数据参数参数长度与参数值

与快照记录一样,扩展数据的具体内容由 ECU 诊断规范定义,不同厂商的差异很大。例如同一个“故障出现次数”字段,在 A 厂商的 ECU 里可能使用 2 字节,在 B 厂商的 ECU 里可能使用 4 字节。开发工具时必须以目标 OEM 的规范为准。

6.4 报文实例

假设 DTC 0x0A05 的第 1 块扩展数据只有一项:故障出现次数,长度 2 字节,当前值为 10(0x000A)。

请求:

19 06 0A 05 01

正响应示例:

59 06 0A 05 45 01 01 02 00 0A

逐字节解析:

  • 0x59:正响应 SID
  • 0x06:子功能回显
  • 0x0A 0x05:DTC 为 0x0A05
  • 0x45:DTC 当前状态字节
  • 0x01:扩展数据记录号
  • 0x01:当前扩展数据项数量为 1
  • 0x02:数据长度 2 字节
  • 0x00 0x0A:故障出现次数为 10

如果 ECU 把故障出现次数放在偏移固定位置,也可能不返回参数标识符,而直接返回定长数据。例如某些 OEM 会规定扩展数据记录按固定字节结构排列,这样上位机只需要按照字节偏移去解析即可。所以 19 06 的响应格式会有“定长结构”和“TLV 结构”两种常见形态,必须在开发前确认。

7. 负响应与常见NRC梳理

7.1 NRC报文格式

当 ECU 无法处理请求时,不会返回 0x59 开头的正响应,而是返回负响应报文:

字节位置内容说明
byte00x7F负响应 SID
byte10x19原始服务 ID,表示是 19 服务的负响应
byte2NRC负响应码

例如

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询