
在整车网络诊断开发中0x85 服务ControlDTCSetting是一个低频出现但影响面很大的服务。它不直接参与故障读取也不负责功能寻址刷写但它决定了“ECU 在什么条件下允许记录 DTC”。如果你的工作是诊断测试、台架标定或者刷写流程设计控制不好 0x85可能会出现“故障码不见了”或者“故障码莫名其妙全冒出来”的情况。这篇文章继续网络诊断系列把 0x85 服务的需求拆解、用例设计、验证方法和排查思路完整展开。先明确一点0x85 的核心是“DTC 设置的开关控制”不是“删除 DTC”也不是“读取 DTC”。所有用例设计都要围绕开关语义、状态保持、安全访问和会话权限四个维度来做。从实际需求出发一个合格的 0x85 服务测试方案至少要覆盖五类场景正常开关控制、异常参数请求、安全访问限制、会话模式限制、与其他诊断服务的联动。下面我们从协议规范开始逐步搭建一套可以直接落到测试用例文档里的完整方案。1. 0x85 服务核心能力速览能力项说明服务名称ControlDTCSetting控制 DTC 设置服务 ID0x85肯定响应 ID0xC5主要功能控制 ECU 是否允许记录/存储 DTC子功能 0x01on关闭 DTC 设置即停止记录新的 DTC子功能 0x02off开启 DTC 设置即恢复记录新的 DTC典型应用刷写前置处理、标定模式、下线检测、特殊测试模式关键依赖通常需要安全访问0x27解锁扩展会话或编程会话下可用测试关注点状态切换、NRC 覆盖、时序、状态保持、与 0x19/0x2E/0x11 的联动适合对象诊断测试工程师、ECU 软件开发、台架测试、OTA 刷写流程设计从材料来看0x85 服务在 UDS 协议栈中属于“DTC 相关服务”但它的行为边界很容易被人忽略。很多测试用例只写了“0x85 发送 01 返回 C5 01”就结束了这远远不够。真正需要验证的是关闭 DTC 记录后故障事件是否不再写入 NVMDTC恢复记录后之前冻结的 DTC 是否继续工作在没有安全解锁的情况下0x85 是否被拒绝在默认会话下请求是否返回 0x7F。这些才是 0x85 用例的核心。2. 0x85 服务适用场景与使用边界2.1 适用场景0x85 服务最常见的需求场景有三个。第一个是刷写前置处理。ECU 在进行 Bootloader 刷写或者应用软件升级时可能会因为电压不稳、通信中断、校验失败等原因产生大量非预期 DTC。这些 DTC 会干扰整车下线检测或者售后故障分析。所以刷写流程的第一步通常是发送 0x85 01 关闭 DTC 记录刷写完成后再发送 0x85 02 恢复记录。第二个是标定和台架测试。标定工程师在反复调整参数时会人为制造一些越界条件。如果 DTC 一直记录会导致台架测试的故障统计不准确。关闭 DTC 设置后测试过程就不会被大量故障码打断。第三个是下线检测EOL和产线配置。车辆下线时需要写入 VIN、配置项等数据这个过程会触发一些“未配置完成”类 DTC。通过 0x85 关闭记录可以保证下线检测数据的干净。2.2 使用边界0x85 服务不是万能的设计用例前必须明确边界。0x85 只控制“是否允许记录新的 DTC”不能清除已有的 DTC。清除 DTC 要用 0x14ClearDiagnosticInformation。0x85 不等于“屏蔽故障报警”。故障仍可能发生并且被识别只是不写入 DTC 存储区。0x85 的作用通常是临时的。ECU 复位后DTC 设置控制状态可能会恢复到默认开启状态除非需求明确规定持久化保存。0x85 执行前一般需要安全访问。如果需求中没有定义安全解锁要求就必须和诊断规范严格对齐否则测试环境会出现“同样的请求在台架上通过在整车上被拒”的情况。3. 测试环境与前置条件3.1 硬件环境硬件设备用途ECU 测试台架或实车提供被测对象CAN/CAN FD 接口卡例如 Vector VN1610、VN1640、PCAN、同星 CAN卡可编程电源模拟 ECU 上电和下电万用表或示波器排查通信物理层问题故障注入工具模拟传感器断路、对地短路、对电源短路等3.2 软件环境CANoe / CANalyzer或者 PCAN-ViewCANdb至少需要 DBC 文件诊断测试脚本平台CAPL 或 PythonECU 的诊断规范文档DLL 或诊断需求说明书ISO 14229-1 标准文本作为用例设计的参考依据。3.3 测试前置条件ECU 正常上电网络通信稳定诊断仪能够进入扩展会话0x10 03 或 0x10 02已通过 0x27 安全访问解锁无其他诊断服务占用总线已确认数据库中的 0x85 服务定义与规范一致。4. 0x85 服务报文格式与基础验证4.1 请求报文格式0x85 服务的诊断请求格式为字节序号名称取值Byte 0服务 ID0x85Byte 1子功能0x01on或 0x02offbit 6-7 为抑制肯定响应位Byte 2...nDTCSettingControlOptionRecord可选参数具体由整车厂定义标准 ISO 14229-1 中定义的 DTCSettingType 为值含义0x01on关闭 DTC 记录0x02off开启 DTC 记录DTCSettingControlOptionRecord 是可选字段。部分 ECU 实现中直接省略该字段此时请求长度就是 2 字节部分 ECU 要求带一个字节的控制选项记录请求长度就是 3 字节。设计用例时必须确认 ECU 诊断规范里的精确要求。4.2 肯定响应报文格式正常情况下ECU 返回的肯定响应为字节序号名称取值Byte 0服务 ID 0x400xC5Byte 1子功能回显请求中的子功能值Byte 2...nDTCSettingControlOptionRecord可选回显参数标准的肯定响应示例请求85 01 响应C5 01请求85 02 响应C5 024.3 否定响应报文格式当请求不满足条件时ECU 返回否定响应7F 85 NRC常见 NRC 包括NRC含义触发条件0x12子功能不支持子功能位不是 01 或 020x13报文长度错误长度不符合规范定义0x22条件不满足点火状态、电压、禁止条件等不满足0x31请求超出范围DTCSettingControlOptionRecord 无效0x33安全访问拒绝未解锁或安全等级不足0x7F当前会话服务不支持默认会话下请求 0x854.4 基础验证示例Python 模拟诊断请求在测试环境中如果使用 Python 和 CAN 接口库可以通过类似下面的方式来发送 0x85 请求import can bus can.interface.Bus(bustypepcan, channelPCAN_USBBUS1, bitrate500000) def send_uds_request(request_bytes, arbitration_id0x7E0): msg can.Message( arbitration_idarbitration_id, datarequest_bytes, is_extended_idFalse ) bus.send(msg) # 发送 0x85 02请求恢复 DTC 记录 send_uds_request([0x85, 0x02])这里只是基础发送示例。实际工程中还需要接收 ECU 响应并做时序判断建议把请求发送和响应接收放到同一个线程中循环处理避免丢帧。5. 0x85 服务正常用例设计根据需求设计用例时第一步是列出正常场景。0x85 的正常场景围绕子功能 01 和 02 的状态切换。5.1 子功能 02恢复 DTC 记录用例编号TC_0x85_001用例名称扩展会话下恢复 DTC 记录前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 022. 等待 ECU 响应预期结果ECU 返回 0xC5 02验证点肯定响应正确DTC 记录功能处于开启状态该用例是 0x85 服务最基础的验证项。如果 ECU 返回 NRC 0x22优先检查是否缺少前置条件例如没有进入扩展会话、电压异常或安全解锁未通过。5.2 子功能 01关闭 DTC 记录用例编号TC_0x85_002用例名称扩展会话下关闭 DTC 记录前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 012. 等待 ECU 响应预期结果ECU 返回 0xC5 01验证点肯定响应正确DTC 记录功能处于关闭状态这个用例验证的是 on 语义。发送成功后ECU 应当不再记录新的 DTC。注意这里说的是“不再记录新的”已经存在的 DTC 不会被清除状态位也不会复位。5.3 开关状态反复切换用例编号TC_0x85_003用例名称DTC 设置开关反复切换前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 012. 确认响应 C5 013. 发送 0x85 024. 确认响应 C5 025. 重复 20 次预期结果每次请求都收到对应的肯定响应无异常响应验证点状态切换稳定性无粘连、无卡死、无响应延迟递增这个用例的重点是状态机稳定性。如果 ECU 的 DTC 设置状态机实现有缺陷反复切换可能出现第二次 on 请求被错误拒绝的情况。5.4 关闭 DTC 记录后故障注入验证用例编号TC_0x85_004用例名称0x85 01 后注入故障验证不记录前置条件ECU 已上电扩展会话安全解锁完成0x85 01 已成功测试步骤1. 发送 0x85 012. 注入 CAN 通信故障或传感器故障3. 等待一段时间4. 读取 0x19 02 或 0x19 01预期结果ECU 不产生新的 DTCDTC 状态位不变验证点on 语义真正生效故障被识别但不被记录这个用例是验证 0x85 功能“有没有真的关掉”。如果测试人员只做报文响应验证很容易漏掉这个关键步骤。5.5 恢复记录后故障记录恢复用例编号TC_0x85_005用例名称0x85 02 后注入故障验证恢复记录前置条件ECU 上电扩展会话安全解锁完成0x85 01 已成功测试步骤1. 发送 0x85 012. 发送 0x85 023. 注入故障4. 读取 DTC预期结果ECU 记录新的 DTC验证点off 语义生效DTC 记录功能恢复正常5.6 断电重启后的状态验证用例编号TC_0x85_006用例名称断电重启后 DTC 设置状态前置条件ECU 上电扩展会话安全解锁完成测试步骤1. 发送 0x85 012. 记录响应3. 关闭电源4. 等待 10 秒5. 重新上电6. 再次请求 0x85 02 或读取 0x19预期结果ECU 恢复到默认状态DTC 记录功能开启验证点各 ECU 对 0x85 状态保持策略可能不同需以需求为准这里需要特别强调如果需求文档规定“断电后保持关闭状态”那么 ECU 必须通过非易失存储记录状态如果需求规定“断电后恢复默认”则无需持久化。这个用例的设计必须严格按照需求文档来定预期结果。6. 0x85 服务异常与 NRC 用例设计6.1 未安全解锁时请求用例编号TC_0x85_007用例名称未解锁请求 0x85前置条件ECU 已上电扩展会话未执行安全访问测试步骤1. 直接发送 0x85 01预期结果ECU 返回 7F 85 33验证点安全访问逻辑生效如果 ECU 在没有安全访问要求的情况下也允许 0x85那属于安全漏洞。此用例是安全类用例中的必测项。6.2 默认会话下请求用例编号TC_0x85_008用例名称默认会话请求 0x85前置条件ECU 已上电处于默认会话测试步骤1. 确保当前在默认会话2. 发送 0x85 02预期结果ECU 返回 7F 85 7F验证点会话权限控制生效该用例覆盖 0x85 的会话模式限制。不同 OEM 可能定义 0x85 在扩展会话或编程会话下可用但默认会话下大概率被拒绝。如果 ECU 在默认会话下也允许执行需要与需求文档确认是否合规。6.3 无效子功能请求用例编号TC_0x85_009用例名称无效子功能 0x03 请求前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 03预期结果ECU 返回 7F 85 12验证点子功能校验同时还可以测试 0x85 00、0x85 FF、0x85 80抑制响应位 保留子功能位等边界子功能找出“非法子功能被接受”的协议栈漏洞。6.4 无效控制参数请求用例编号TC_0x85_010用例名称无效 DTCSettingControlOptionRecord前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 01 0x102. 等待响应预期结果ECU 返回 7F 85 31验证点参数范围校验注意如果 ECU 实现中不接受任何控制选项记录字段那么发送 0x85 01 0x10 可能返回 0x13 而不是 0x31。具体以 ECU 规范为准。6.5 错误报文长度用例编号TC_0x85_011用例名称0x85 报文长度错误前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送单字节 0x852. 等待响应预期结果ECU 返回 7F 85 13验证点长度校验6.6 抑制肯定响应位测试用例编号TC_0x85_012用例名称抑制肯定响应位前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 0x41即子功能 01 带抑制位2. 等待 500ms预期结果ECU 不发送任何响应但功能正常执行验证点抑制响应位处理正确服务执行但静默响应7. 0x85 服务与其他服务联动用例设计0x85 服务在真实诊断流程中很少单独使用。下面给出 4 个联动用例这些用例通常是被测试团队遗漏的高价值场景。7.1 与 0x10 会话控制联动用例编号TC_0x85_013用例名称扩展会话→关闭 DTC→切换编程会话→恢复 DTC前置条件ECU 已上电测试步骤1. 0x10 03 进入扩展会话2. 0x85 01 关闭 DTC3. 0x10 02 进入编程会话4. 0x85 02 恢复 DTC预期结果步骤 2、4 均返回肯定响应验证点会话切换不影响 DTC 设置状态或按需求定义的行为执行这个用例有一个典型争议点切换会话时DTC 设置状态是否保持有的 ECU 在会话切换时会清除未持久化的 DTC 设置状态。该场景必须以实际需求来决定预期结果不能默认“一定保持”。7.2 与 0x27 安全访问联动用例编号TC_0x85_014用例名称安全解锁后执行 0x85前置条件ECU 已上电扩展会话测试步骤1. 0x27 01 请求种子2. 0x27 02 发送密钥3. 0x85 014. 0x85 02预期结果三次请求均成功0x85 肯定响应验证点安全访问后服务权限正常7.3 与 0x19 读取 DTC 联动用例编号TC_0x85_015用例名称关闭 DTC 记录后读取 DTC前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 0x85 012. 注入故障3. 0x19 02 按状态掩码读取4. 0x85 025. 再注入故障6. 0x19 02 读取预期结果步骤 3 未出现新 DTC步骤 6 出现新 DTC验证点0x85 对 DTC 记录功能的实际影响7.4 与 0x11 ECU 复位联动用例编号TC_0x85_016用例名称0x85 01 后执行 ECU 复位前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 0x85 012. 0x11 01 执行硬复位3. 等待重启完成4. 发送 0x85 02预期结果复位后状态符合需求定义验证点0x85 状态在复位后的保持策略8. 0x85 服务边界值与性能用例设计8.1 边界值分析在 0x85 用例设计中边界值主要体现在子功能字段和控制参数上。输入值预期0x85 00子功能不支持0x120x85 01正常 on0x85 02正常 off0x85 03子功能不支持0x120x85 7F子功能不支持0x120x85 80保留子功能位且带抑制位不响应或 0x120x85 41子功能 01 抑制位不响应0x85 42子功能 02 抑制位不响应0x85 01 00参数 00按规范确认是否有效0x85 01 FF参数 FF无效参数0x31 或 0x138.2 连续发送压力测试用例编号TC_0x85_017用例名称连续 100 次 0x85 01 请求前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 循环发送 0x85 01 100 次2. 统计响应时间和肯定响应数量预期结果所有请求均被处理无死锁无总线错误验证点协议栈处理连续请求的能力典型异常是ECU 在处理完第一次 0x85 01 后把“关闭 DTC 记录”误当成一次性操作第二次 0x85 01 返回 0x22。这种情况属于状态设计不合理必须通过压力测试发现。8.3 响应时间测试用例编号TC_0x85_018用例名称0x85 响应时间测量前置条件ECU 已上电扩展会话安全解锁完成测试步骤1. 发送 0x85 012. 记录发送时间戳和接收时间戳预期结果响应时间在规范允许范围内验证点是否符合诊断响应时间要求UDS 规范通常要求 ECU 在 P2 时间内返回响应默认 P2 为 25ms 或 50ms具体以 OEM 诊断规范为准。如果响应时间连续超过 P2说明 0x85 服务处理路径中存在耗时操作需要优化。8.4 总线负载对 0x85 的影响在实车环境或台架环境下总线可能有大量报文。设计用例时可以在 0x85 请求的同时让总线保持 60% 以上的负载观察 0x85 请求是否出现丢帧、超时或错误响应。这个测试往往能暴露网络调度和报文优先级配置问题。9. 常见问题与排查方法问题现象可能原因排查方式解决方案0x85 请求无响应总线报文被过滤查看 CANoe Trace 窗口检查报文是否发送成功检查诊断仪地址和 ECU 地址配置0x85 请求无响应抑制肯定响应位被置位检查发送报文的子功能字节是否带 0x40 或 0x80使用正确的子功能值返回 7F 85 33未执行安全访问检查是否先发送了 0x27 解锁先完成安全访问再发送 0x85返回 7F 85 7F当前会话不支持检查当前会话是否在默认会话先发送 0x10 03 或 0x10 02返回 7F 85 22条件不满足检查电源电压、点火状态、故障注入状态恢复满足条件的状态返回 7F 85 31控制参数超出范围检查 DTCSettingControlOptionRecord 值参照规范修改参数0x85 01 成功但仍产生 DTCDTC 记录关闭逻辑未生效查看 DTC 状态位和事件计数器检查 DTC 记录控制和故障事件的判断逻辑0x85 02 后 DTC 无法记录状态机卡在 on 状态读取内部状态变量或检查日志查看软件实现中状态切换逻辑响应时间超时服务处理路径过长CPU 占用分析、Task 调度分析排查诊断协议栈的优先级和时序针对 0x85 特有的一个坑如果 ECU 在 0x85 01 成功后立即复位且复位逻辑中 DTC 记录状态恢复为默认 on那么此时再发送 0x85 01 是合法的但部分测试脚本会误判为“重复请求”。这里需要结合用例 TC_0x85_016 来设计自动化脚本明确复位后的状态预期。10. 0x85 服务用例设计方法与最佳实践10.1 需求分析先行设计 0x85 用例前必须把需求文档里的功能描述转换成可验证的“状态-事件”模型。建议画出四个维度关键状态DTC 记录开启、DTC 记录关闭、未知状态复位后。触发事件0x85 01 请求、0x85 02 请求、会话切换、复位、断电、故障发生。前置条件安全解锁状态、会话模式、电压条件、点火状态。预期结果肯定响应、否定响应、DTC 记录行为、状态保持行为。把表头列出来之后需求中的每一个“如果...那么...”描述都会变成一个用例。10.2 用例分类按测试目标可以把 0x85 用例分为四类分类覆盖内容功能用例正常 on/off、重复切换、状态保持异常用例无效子功能、错误长度、无效参数安全用例未解锁请求、会话权限、抑制响应位联动用例与其他服务配合、复位后行为、故障注入验证10.3 自动化落地如果是基于 CANoe 做自动化建议用 CAPL 写一个公共函数库把 0x85 请求、响应判定、NRC 断言封装成可复用模块void SendControlDTCSetting(byte subFunction) { byte request[2]; request[0] 0x85; request[1] subFunction; diagRequestSend(0x85, request, elCount(request)); }这样每个测试用例只需调用函数不需要在每个用例里重复写报文拼接逻辑。10.4 基于 Python 的自动化测试在 Python 测试框架中可以这样封装 0x85 的请求和期望响应匹配class UDSClient: def control_dtc_setting(self, sub_function, expected_nrcNone): request [0x85, sub_function] response self.send_request(request) if expected_nrc: assert response[0] 0x7F and response[2] expected_nrc, \ fExpected NRC {expected_nrc:#04x}, got {response.hex()} else: assert response[0] 0xC5 and response[1] sub_function, \ fExpected positive response, got {response.hex()}这里的send_request是底层 CAN/UDS 传输方法。实际接入时可以替换成 python-can、CANoe COM 接口或者其他诊断库。10.5 测试记录和跟踪每次 0x85 测试都要保留测试时间戳和 ECU 软硬件版本请求报文和响应报文原始帧0x85 状态切换前后的 DTC 列表快照总线负载和响应时间记录故障注入方式、注入时间和恢复时间。有了这些记录出现“边界状态下的 DTC 记录异常”时就能快速定位是测试环境问题还是 ECU 实现问题。10.6 合规与安全边界0x85 服务通常和刷写、标定、下线检测相关测试时需要特别注意在实车上测试前确认关闭 DTC 记录不会影响安全相关功能的故障监控涉及 OTA 刷写流程的 0x85 用例必须确认刷写失败后的回退逻辑不会导致 DTC 永远关闭测试过程中产生的 DTC测试完成后必须通过 0x14 服务清理干净不要在生产配置或安全关键 ECU 上随意执行 0x85 01 后断电以免造成诊断数据不可追溯。11. 总结与下一步0x85 服务本身很简单就是两个子功能加上几个 NRC。但真正考验测试功底的是“根据需求设计用例”这件事。需求里写的“控制 DTC 设置”落到用例里至少需要覆盖状态切换、权限校验、会话限制、故障注入、复位行为五个层面。只要你把 4 个典型前置条件和 5 类场景的用例跑完0x85 这块基本就能交付了。最容易踩的坑有三个一是把 0x85 和 0x14 混为一谈二是不验证“关闭后是否真的不记录”三是忽略复位和会话切换对 DTC 设置状态的影响。下一轮测试开始前建议先按照文中的用例清单对一遍现有的测试设计缺口补上再执行。如果你正在做整车诊断或 UDS 协议栈相关的开发和测试欢迎把这套用例框架直接拿过去改造成自己的测试规范。后续文章会继续安排 0x86、0x87 等服务的用例设计保持更新建议收藏备用。