1. 引言
在UDS刷写流程中,DTC控制(0x85 Service) 与上一篇文章介绍的通信控制(0x28 Service)是一对"黄金搭档",它们共同构成了刷写前"清场"的关键两步。
DTC(Diagnostic Trouble Code,诊断故障码)是ECU用于记录和报告故障状态的重要机制。当CAN总线上出现通信异常(如节点丢失、总线错误等),ECU会实时更新DTC状态位并存储故障信息。然而,在固件刷写过程中,这些DTC更新行为会带来严重问题:
-
误报故障:刷写过程中ECU的通信会被0x28服务暂时关闭,其他ECU检测到通信丢失后会误报"节点丢失"DTC
-
干扰刷写:DTC的存储和更新会占用ECU资源,影响刷写速度和稳定性
-
污染记录:刷写完成后,DTC存储器中会充满与本次刷写无关的故障码,干扰后续故障诊断
TOOMOSS_SID85_ControlDTCSetting.vi的作用就是在刷写开始前关闭DTC状态位的更新 ,刷写完成后重新开启DTC更新,确保整个刷写过程不受DTC机制干扰。
2. 子VI功能概述
2.1 设计目标
-
根据用户指定的子功能(开启/关闭),构造0x85服务请求报文
-
调用通信基座发送请求并等待ECU响应
-
解析响应报文,判断DTC控制是否成功
-
返回响应数据和执行状态
2.2 UDS 0x85服务协议说明
功能:控制ECU中DTC状态位的更新,即启用或禁用DTC检测与记录功能。
2.2.1 子功能参数(DTCSettingType)
0x85服务的子功能只有两个常用值:
| 子功能值 | 名称 | 说明 |
|---|---|---|
| 0x01 | ON(开启) | ECU应根据正常运行条件恢复DTC状态位的更新 |
| 0x02 | OFF(关闭) | ECU应停止DTC状态位的更新 |
注意:0x03 ~ 0x3F为ISO保留值,0x40 ~ 0x5F为车辆制造商特定值,0x60 ~ 0x7E为系统供应商特定值。
2.2.2 请求格式
基本请求格式非常简洁,只使用两个字节:
Byte 0: SID = 0x85
Byte 1: subFunction(DTCSettingType)
扩展说明 :ISO 14229标准中定义了可选的
DTCSettingControlOptionRecord参数,用于指定要控制的特定DTC或DTC组,但该参数在常规刷写场景中极少使用。本子VI暂不实现此扩展功能。
2.2.3 肯定响应格式
Byte 0: SID = 0xC5(0x85 + 0x40)
Byte 1: subFunction(回声,与请求中的DTCSettingType一致)
2.2.4 否定响应格式
Byte 0: SID = 0x7F
Byte 1: 0x85
Byte 2: NRC(负响应码)
2.3 输入参数
| 控件 | 类型 | 说明 |
|---|---|---|
| 设备句柄 | U32 | 由TOOMOSS_OpenDev(CAN).vi返回的设备句柄 |
| 通道号 | 枚举(CAN1/CAN2) | 选择使用CAN1还是CAN2通道 |
| 物理地址 | U32 | 请求报文ID(发送给ECU的CAN ID) |
| 响应地址 | U32 | 期望的响应报文ID(ECU回复的CAN ID) |
| 子功能 | 枚举(开启/关闭) | DTC设置类型 |
2.4 输出参数
| 控件 | 类型 | 说明 |
|---|---|---|
| 响应数据 | U8数组 | ECU返回的完整响应数据 |
| 返回值 | I32 | 0表示成功,-1表示失败 |
| 错误信息 | 字符串 | 失败时的错误描述 |
3. 前面板设计

4. 程序框图设计
4.1 整体流程
子功能枚举值 → 构造请求数据[0x85, subFunction]
↓
调用 TOOMOSS_SendAndWaitResp.vi
↓
判断响应类型
┌───────────────┼───────────────┐
↓ ↓ ↓
返回<0 返回=0 返回>0
(调用失败) (超时) (收到响应)
↓ ↓ ↓
返回-1 返回-1 判断响应首字节
┌───────────────┼───────────────┐
↓ ↓
0xC5 0x7F
(肯定响应) (否定响应)
↓ ↓
返回0 返回-1
解析NRC返回错误信息
4.2 第一步:构造请求数据
根据子功能枚举值,构造请求数据数组:
| 子功能枚举 | 值 | 请求数据 |
|---|---|---|
| 开启(ON) | 0x01 | [0x85, 0x01] |
| 关闭(OFF) | 0x02 | [0x85, 0x02] |
在LabVIEW中,使用创建数组函数将SID(0x85)和子功能值组合为2字节数组。
4.3 第二步:调用通信基座
将上一步构造的请求数据作为输入,调用TOOMOSS_SendAndWaitResp.vi:
| 输入参数 | 来源/值 |
|---|---|
| 设备句柄 | 子VI输入 |
| 通道号 | 子VI输入 |
| 物理地址 | 子VI输入 |
| 响应地址 | 子VI输入 |
| 请求数据 | 构造的[0x85, subFunction] |
| 数据长度 | 2 |
| 超时时间 | 500ms(建议值) |
4.4 第三步:判断响应类型
从通信基座获取返回值,分三种情况处理:
情况一:返回值 < 0(通信失败)
-
通信基座内部调用DLL失败
-
直接透传错误信息,子VI返回 -1
情况二:返回值 = 0(无响应/超时)
-
ECU未响应
-
设置错误信息为"ECU未响应,请检查物理地址和通信连接"
-
子VI返回 -1
情况三:返回值 > 0(收到响应)
-
响应数据有效,继续解析
-
判断响应数据的首字节(Byte 0)
肯定响应判断:
if 响应数据[0] == 0xC5 → DTC控制成功,返回0
响应数据0 = 0xC5 = 0x85 + 0x40,符合UDS肯定响应规则。
否定响应判断:
if 响应数据[0] == 0x7F → DTC控制失败
NRC = 响应数据[2]
根据NRC值生成对应的错误信息
返回-1
4.5 常见NRC错误信息映射
| NRC | 含义 | 错误信息 |
|---|---|---|
| 0x12 | 子功能不支持 | "该ECU不支持请求的DTC设置类型" |
| 0x13 | 报文长度或格式错误 | "请求报文长度或格式不正确" |
| 0x22 | 条件不满足 | "先决条件不满足,请检查当前状态" |
| 0x31 | 请求超出范围 | "请求的DTC控制参数超出范围" |
| 0x7E | 当前会话下子功能不支持 | "当前会话下不支持该子功能,请先进入扩展会话" |
| 0x7F | 当前会话下服务不支持 | "当前会话下不支持85服务,请先进入扩展会话" |
| 其他 | 未知 | "DTC控制失败,NRC=0x%02X" |
重要提示 :0x85服务要求在非默认会话(如扩展会话)下执行。如果在默认会话下发送请求,ECU会返回NRC=0x7F。
5. 程序框图关键节点示意
5.1 请求数据构造

5.2 通信基座调用

5.3 响应解析

6. 在UDS刷写流程中的位置
在整个UDS刷写流程中,TOOMOSS_SID85_ControlDTCSetting.vi位于预编程阶段的核心位置【参见系列文章(序)中的升级流程图】:
预编程阶段:
(1) 切换到扩展会话 [10 03]
(2) 编程条件检查 [31 01 02 03]
(3) 关闭DTC存储 [85 02] ← 调用本子VI(关闭DTC)
(4) 通信控制 [28 03 01]
6.1 典型用法
刷写开始前(关闭DTC):
-
子功能 = 关闭(0x02)
-
请求数据:
85 02 -
效果:停止DTC状态位的更新,避免误报故障码
刷写结束后(开启DTC):
-
子功能 = 开启(0x01)
-
请求数据:
85 01 -
效果:恢复DTC状态位的正常更新
6.2 与0x28服务的配合关系
0x85服务与0x28服务在刷写流程中的配合顺序至关重要:
刷写开始顺序:
1. 0x85 关闭DTC(停止记录故障)
2. 0x28 关闭通信(停止收发报文)
刷写结束顺序(反向):
1. 0x28 开启通信(恢复报文收发)
2. 0x85 开启DTC(恢复故障记录)
为什么要先关闭DTC再关闭通信?
-
如果先关闭通信(0x28),其他ECU检测到该ECU通信丢失后会产生DTC
-
因此必须先执行0x85服务,通知所有ECU"不要记录DTC",然后再执行0x28服务关闭通信
6.3 DTC控制的恢复机制
即使上位机忘记发送0x85开启DTC,以下情况也会自动恢复DTC更新:
-
ECU复位:执行0x11服务后,DTC控制自动恢复
-
会话切换:从扩展会话/编程会话切换回默认会话时,自动恢复
-
超时:非默认会话超时后自动切回默认会话,同时恢复DTC
7. 典型调用示例
7.1 关闭DTC更新(刷写前)
输入配置:
-
物理地址 = 0x700
-
响应地址 = 0x708
-
子功能 = 关闭(0x02)
实际发送 :[0x85, 0x02]
期望响应 :[0xC5, 0x02](肯定响应)
7.2 开启DTC更新(刷写后)
输入配置:
-
物理地址 = 0x700
-
响应地址 = 0x708
-
子功能 = 开启(0x01)
实际发送 :[0x85, 0x01]
期望响应 :[0xC5, 0x01](肯定响应)
7.3 否定响应示例(会话错误)
若ECU在默认会话下收到0x85请求,返回 [0x7F, 0x85, 0x7F],表示当前会话下服务不支持。子VI应解析NRC=0x7F,返回错误信息:"当前会话下不支持85服务,请先进入扩展会话"。
8. 错误处理
| 错误场景 | 返回值 | 错误信息 |
|---|---|---|
| 设备句柄无效 | -1 | "设备句柄无效,请检查设备是否已打开" |
| 通信基座返回<0 | -1 | 透传通信基座的错误信息 |
| 通信基座返回=0 | -1 | "ECU未响应,请检查物理地址和通信连接" |
| 响应首字节为0x7F | -1 | 根据NRC返回对应错误信息 |
| 响应首字节非0xC5非0x7F | -1 | "收到未知响应,SID=0x%02X" |
9. 注意事项
| 要点 | 说明 |
|---|---|
| 会话要求 | 0x85服务必须在非默认会话下执行,建议在扩展会话(0x03)下使用 |
| 与0x28的配合顺序 | 刷写前:先0x85关闭DTC,再0x28关闭通信;刷写后:先0x28开启通信,再0x85开启DTC |
| 与0x14的区别 | 0x85控制DTC的更新 ,0x14清除DTC的记录,两者互不影响 |
| DTC状态保持 | 关闭DTC后,DTC状态位会冻结在当前值,不再更新 |
| 自动恢复 | ECU复位或切回默认会话后,DTC控制会自动恢复为开启状态 |
| 功能寻址 | 在多ECU系统中,可使用功能寻址同时控制多个ECU的DTC设置 |
| 会话切换保持 | 在当前会话支持0x85服务的范围内切换时,DTC控制状态保持不变 |
10. 总结
TOOMOSS_SID85_ControlDTCSetting.vi封装了UDS 0x85 DTC控制服务,虽然它的请求报文只有两个字节,却是UDS刷写流程中不可或缺的"清道夫"。
它的核心价值在于:
-
防止误报:刷写过程中关闭DTC更新,避免其他ECU误报通信故障
-
保护诊断记录:确保DTC存储器中不会混入与刷写过程无关的故障码
-
配合0x28服务:与通信控制服务共同组成完整的刷写前"清场"流程
理解0x85与0x28的配合顺序(先关DTC、再关通信),以及DTC控制自动恢复的触发条件(复位、会话切换),有助于构建稳定可靠的UDS刷写流程。
下一篇将介绍 TOOMOSS_SID2E_WriteDataByID.vi --- 写入数据(写入指纹信息),敬请期待。