![]()
一、服務概要
服務名稱: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.