![]()
一、服务概要
服务名称:ClearDiagnosticInformation (CDTCI)
**服务标识 (SID)**:0x14
**肯定响应 (PRSID)**:0x54
功能摘述:客户端请求清除ECU内存中存储的诊断信息,这些信息主要指故障码 (DTC) 及与之关联的快照数据、扩展数据和各类统计信息。
典型场景:软件更新后清除陈旧信息以避免干扰、生产线下线检测关闭时的故障记录初始化,以及维修保养结束或高级服务执行前重置历史数据。
Byte #
Parameter
Value
缩写
1
ClearDiagnosticInformation Request SID
0x14
CDTCI
2
groupOfDTC[0] (HighByte)
0x00–0xFF
GODTC_HB
3
groupOfDTC[1] (MiddleByte)
0x00–0xFF
GODTC_MB
4
groupOfDTC[2] (LowByte)
0x00–0xFF
GODTC_LB
该服务无子功能参数,直接由 SID 和 3 字节的
groupOfDTC构成。groupOfDTC以大端模式表示:3 字节 = [HighByte, MiddleByte, LowByte]。特殊字符0xFFFFFF表示清除所有 DTC。groupOfDTC除了 0xFFFFFF,还可指定为 DTC 分组或具体某个 DTC 代码。分组值依据 OEM 在协议中的定义,例如 0xFFFF33 对应排放/动力总成组。
格式:0x54
服务完全处理完成后,服务器应返回肯定响应,即使当前未存储任何 DTC。3. 否定响应
格式:
0x7F+0x14+NRC(1 byte)。
NRC 代码
名称
描述
0x13
incorrectMessageLengthOrInvalidFormat
请求报文长度不正确(groupOfDTC不足 3 字节)
0x22
conditionsNotCorrect
当前会话条件不满足(如服务需要在默认会话模式执行)
0x31
requestOutOfRange
请求的groupOfDTC值不被 ECU 支持
0x33
securityAccessDenied
所需安全等级验证未通过(针对高安全清除策略)
0x7F
serviceNotSupportedInActiveSession
服务在活动诊断会话模式下不支持
0x11
serviceNotSupported
服务根本不被 ECU 支持
0x12
subFunctionNotSupported
实际上 14 服务无子功能,若报此错说明格式错误
NRC 优先级参考(ISO 未明确定义,但多数实现遵循):0x11 > 0x7F > 0x13 > 0x12 > 0x7E > 0x33 > 0x22 > 0x31 > 0x14。
三、清除的架构设计:内存处理与多副本
项目
RAM 管理 (主要副本)
非易失存储器管理 (备份副本)
清除目标
立即执行:清除状态字节、快照数据、扩展数据、计数器、标志
清除诊断服务的主要副本后,备份副本不应即时清除
操作流程
① 收到 0x14 服务;② 硬件或软件直接清空;③ 刷新通信时对应用层报告数据
ECU 进入低功耗锁存阶段 (Power-Latch) 时,根据备份策略用 RAM 的新内容覆盖 EEPROM/Flash
常见数据不一致原因
程序内部未按设计清除 ALL DTC 相关数据和副本
如果在电力锁存阶段受到干扰(如意外断开电池),可能导致 RAM 与长期存储器之间数据不一致
四、模拟 ECUSim — C++ 示例与详解 1. 定义核心组件和类结构
2. 模拟通讯运行函数#include
#include
#include
#include
#include // for std::find, std::remove_if
#include // for memcpy
usingnamespacestd;
// --------------------------------
// 1. DTC 的数据结构
// --------------------------------
struct DtcSnapshot {
std::vector snapshotRecord; // 冻结帧数据
};
struct DtcExtendedData {
std::vector extendedRecord; // 扩展数据
uint16_t occurrenceCounter; // 故障发生次数
uint16_t agingCounter; // 老化计数器
};
struct DiagnosticTroubleCode {
uint32_t dtcCode; // 3字节 DTC 代码 (大端)
uint8_t statusMask; // DTC 状态字节 (按照 ISO 14229-1 定义)
DtcSnapshot snapshot;
DtcExtendedData extendedData;
bool isPermanent; // 是否为永久性故障(不可清除)
};
// --------------------------------
// 2. ECU 模拟类
// --------------------------------
class ECU {
private:
std::map storedDTCs;
bool isSecurityGranted;
// 工具函数: 将 3 字节 DTC (大端) 转为 uint32_t (实际低24位有效)
uint32_t dtcToUint32(uint8_t high, uint8_t mid, uint8_t low) const {
return (static_cast(high) << 16) |
(static_cast(mid) << 8) |
static_cast(low);
}
public:
ECU() : isSecurityGranted(false) {}
void grantSecurityAccess() { isSecurityGranted = true; }
void revokeSecurityAccess() { isSecurityGranted = false; }
// 新增 DTC (模拟故障发生器)
void addDTC(uint32_t dtcCode, uint8_t status, bool permanent) {
DiagnosticTroubleCode dtc;
dtc.dtcCode = dtcCode;
dtc.statusMask = status;
dtc.isPermanent = permanent;
dtc.extendedData.occurrenceCounter = 1;
storedDTCs[dtcCode] = dtc;
}
// 模拟读取 DTC 状态(用于清空后验证)
void reportStoredDTCs() const {
if (storedDTCs.empty()) {
cout << "[ECU] No DTC stored." << endl;
return;
}
cout << "[ECU] Stored DTCs:" << endl;
for (constauto& pair : storedDTCs) {
uint32_t code = pair.first;
cout << hex << " DTC: 0x" << ((code >> 16) & 0xFF) << " "
<< ((code >> 8) & 0xFF) << " " << (code & 0xFF)
<< " | StatusMask: 0x" << (int)pair.second.statusMask
<< " | Permanent: " << (pair.second.isPermanent ? "Yes" : "No")
<< dec << endl;
}
}
// 核心: ClearDiagnosticInformation 服务 (0x14)
// 返回: 0x54 -> 肯定响应
// 0x7F 0x14 0x?? -> 否定响应
uint32_t clearDiagnosticInformation(const uint8_t* request, uint32_t len) {
// --- 步骤 1: 长度校验 ---
if (len != 4) { // SID + 3字节 groupOfDTC
cout << "[Server] NRC 0x13: incorrectMessageLength" << endl;
return0x13;
}
// 提取 GroupOfDTC
uint8_t grpHigh = request[1];
uint8_t grpMid = request[2];
uint8_t grpLow = request[3];
uint32_t groupVal = dtcToUint32(grpHigh, grpMid, grpLow);
// 临时存储需要删除的 DTC 列表
std::vector toDelete;
// --- 步骤 2: 安全级别检查 ---
// 假设 OEM 要求针对某些特定组 (例如排放组) 清除时需要安全访问
if (groupVal == 0xFFFF33 && !isSecurityGranted) {
cout << "[Server] NRC 0x33: securityAccessDenied" << endl;
return0x33;
}
// --- 步骤 3: groupOfDTC 值支持范围校验 ---
// 检查 groupVal 是否属于已定义支持的范围
// 假设支持清除: 0xFFFFFF (全部), 0xFFFF33 (排放组), 0x000100 (示例单个DTC代码)
bool groupSupported = (groupVal == 0xFFFFFF) ||
(groupVal == 0xFFFF33) ||
(groupVal == 0x000100);
if (!groupSupported) {
cout << "[Server] NRC 0x31: requestOutOfRange" << endl;
return0x31;
}
// --- 步骤 4: 清除逻辑 (根据 groupOfDTC 匹配) ---
for (auto& pair : storedDTCs) {
DiagnosticTroubleCode& dtc = pair.second;
// 永久性故障 (不可清除) 跳过
if (dtc.isPermanent) continue;
bool match = false;
if (groupVal == 0xFFFFFF) {
match = true; // 清除所有 DTC
} elseif (groupVal == 0xFFFF33) {
// 排放组匹配检查: 按 DTC 的高字节是否为 0xFFFF33 定义的组内;
// 演示: 假设 highByte == 0xFF 属于排放组
uint8_t highByte = (pair.first >> 16) & 0xFF;
if (highByte == 0xFF) match = true;
} elseif (groupVal == pair.first) {
match = true; // 精确匹配单个 DTC 代码
}
if (match) {
toDelete.push_back(pair.first);
}
}
// 执行删除 (仿照 "内存中用于 ReadDTCInformation 的主副本被清除")
for (uint32_t code : toDelete) {
storedDTCs.erase(code);
cout << "[Server] Cleared DTC: 0x" << hex << ((code >> 16) & 0xFF)
<< " " << ((code >> 8) & 0xFF) << " " << (code & 0xFF)
<< dec << endl;
}
// --- 步骤 5: 模拟电源锁存 (Power-Latch) 阶段的备份更新 ---
// 在实际系统中,主副本清空后,备份副本会在 Power-Latch 阶段由 RAM 数据自动覆盖;
// 这里仅示意一致性: 如果需要触发 EEPROM 更新,在代码层面预留接口即可。
// 在该阶段,如果电池意外断电,RAM 与 EEPROM 可能不一致,本示例假设一致。
// 肯定响应始终返回 0x54
return0x54;
}// 模拟处理整体 UDS 请求
void processUDSRequest(const uint8_t* req, uint32_t len) {
if (len == 0) return;
uint8_t sid = req[0];
if (sid == 0x14) {
uint32_t result = clearDiagnosticInformation(req, len);
if (result == 0x54) {
cout << "[Tester] Received positive response: 0x54" << endl;
} else {
cout << "[Tester] Received negative response: 0x7F 0x14 0x" << hex << (int)result << dec << endl;
}
} else {
cout << "[Server] Service not supported for SID: 0x" << hex << (int)sid << dec << endl;
}
}
};
int main() {
ECU myECU;
// 预设一些 DTC 用于清除测试
// DTC: 0xFF 01 02 (高字节 0xFF, 用作排放组示例), 非永久故障
myECU.addDTC(0xFF0102, 0x09, false);
// DTC: 0x00 01 00 (另一个 DTC), 非排放组, 非永久
myECU.addDTC(0x000100, 0x08, false);
// DTC: 0xAA BB CC (永久故障, 不能清除)
myECU.addDTC(0xAABBCC, 0x09, true);
// DTC: 0xFF 03 04 (另一排放组 DTC), 非永久
myECU.addDTC(0xFF0304, 0x09, false);
cout << "Before Clear:" << endl;
myECU.reportStoredDTCs();
// 示例 1: 清除所有 DTC (group = 0xFFFFFF)
uint8_t clearAllRequest[] = {0x14, 0xFF, 0xFF, 0xFF};
cout << "\n--- Clearing All DTCs (0x14 FF FF FF) ---" << endl;
myECU.processUDSRequest(clearAllRequest, 4);
myECU.reportStoredDTCs();
// 示例 2: 清除指定单个 DTC (0x00 01 00)
cout << "\n--- Clearing Single DTC (0x14 00 01 00) ---" << endl;
uint8_t clearSingleRequest[] = {0x14, 0x00, 0x01, 0x00};
myECU.processUDSRequest(clearSingleRequest, 4);
myECU.reportStoredDTCs();
// 示例 3: 如果安全访问失败 (模拟未授权清除排放组)
cout << "\n--- Attempt Clear Emission Group without Security ---" << endl;
uint8_t clearEmissionNoSecurity[] = {0x14, 0xFF, 0xFF, 0x33};
myECU.processUDSRequest(clearEmissionNoSecurity, 4);
myECU.reportStoredDTCs();
// 示例 4: 先模拟安全访问,再清除排放组
cout << "\n--- Grant Security and Clear Emission Group (0x14 FF FF 33) ---" << endl;
myECU.grantSecurityAccess();
uint8_t clearEmissionWithSecurity[] = {0x14, 0xFF, 0xFF, 0x33};
myECU.processUDSRequest(clearEmissionWithSecurity, 4);
myECU.reportStoredDTCs();
// 示例 5: 长度校验 (错误报文)
cout << "\n--- Error: Incorrect Length (missing group data) ---" << endl;
uint8_t badLenRequest[] = {0x14, 0xAA};
myECU.processUDSRequest(badLenRequest, 2);
// 预期: 服务器应不修改 DTC 存储,返回 NRC 0x13
// 示例 6: 不支持 groupOfDTC 值
cout << "\n--- Error: unsupported groupOfDTC (0x14 AA BB CC) ---" << endl;
uint8_t unsupportedGroup[] = {0x14, 0xAA, 0xBB, 0xCC};
myECU.processUDSRequest(unsupportedGroup, 4);return0;
}
五、常见测试用例与验证
测试用例:
-用例1:基本清除
步骤:[TX]14FFFFFF→预期:[RX]54→DTC存储为空
-用例2:清除时未存储DTC
步骤:当无DTC存储时请求14FFFFFF→[RX]54 →(即使无存储,仍相应肯定)
-用例3:组清除
步骤:[TX]14FFFF33(指定某个定义好的组)→[RX]54→验证仅该组DTC消失。
-用例4:安全访问
步骤:清除前先调用27服务解锁,然后再使用14FFFFFF功能成功清除。
-用例5:长度校验
步骤:[TX]14FF(长度不足)→预期:NRC0x13
-用例6:不支持group值
步骤:[TX]14AABBCC→预期:NRC0x31
-用例7:故障重现
步骤:清除后重启ECU,若故障重现→实际故障未消除,需执行11服务软复位后再读取。
六、常见问题与解决问题
原因
解决
清除后故障码立即重现
物理故障未完全修复,ECU 再次监控到故障触发; 或清除仅清了 DTC 状态字节,但计数器、冻结帧未被全清(实现不完整)
① 彻底排查故障;② 部分 ECU 支持扩展清除帧,利用 14 服务特定 groupOfDTC 深度清除; ③ 清除后发送 11 01 软复位,避免软件缓存残留
永久故障码无法清除
永久性 DTC 的isPermanent标志为真,不允许清除;法规要求必须保留
这是正常行为,此类 DTC 需通过其它机制(如老化计数器归零)自动清除,诊断仪无法强制清除;定期检查到该 DTC 未发生后,通过计数器自行移除。
备份副本不一致
电源锁存阶段意外掉电或中断,导致 RAM 与 EEPROM 内容不同步
设计异常保护逻辑,在下次上电时自动校验并依据多数策略修复
不同会话下不可用
14 服务仅在默认会话或扩展会话中支持;如果在编程会话中调用,ECU 可能响应 NRC 0x7F
切换至合适的会话再执行清除流程
七、补充说明
零星的思路:14 服务(ClearDiagnosticInformation)与 19 服务(ReadDTCInformation)相辅相成。清除之前,可以通过 19 服务读取当前 DTC 列表和状态;清除成功后,再次通过 19 服务读取结果来验证。
其它类似服务:UDS 里
0x85(ControlDTCSetting) 服务用来临时开启或关闭 DTC 存储,而不是清除已有信息。两者经常配合使用。可用性见解:实现时,注意必须清除 DTC 状态字节、快照、扩展数据、计数器等全部项。如果
groupOfDTC设置为清除某个组,那么该组内部所有 DTC 必须删除。供电锁存阶段要遵循备份策略,确保 RAM 和 EEPROM 的数据一致。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.