![]()
1. 前言
在UDS(ISO 14229-1)診斷協議中,故障碼(DTC,Diagnostic Trouble Code)不僅僅是“有故障”或“無故障”的簡單標記。每個DTC都附帶一個1字節的狀態位(Status Byte),用于精確描述該故障在當前操作循環及歷史記錄中的生命周期。同時,14服務用于重置這些狀態。
理解狀態位的跳變邏輯,是開發高質量診斷軟件(如ECU固件)或診斷工具(如Tester)的基礎。
2. 故障碼狀態位詳解 2.1 狀態位定義(Bit 0 - Bit 7)
根據ISO 14229-1定義,DTC狀態字節的8個位含義如下:
Bit
名稱
描述
核心邏輯
0
TestFailed
當前操作循環中,最近一次測試結果為失敗。
瞬時故障標志
1
TestFailedThisOperationCycle
當前操作循環中,曾經檢測到故障。
本循環歷史
2
PendingDTC
當前循環失敗,但尚未達到確認閾值(防抖中)。
待確認故障
3
ConfirmedDTC
故障已確認(達到閾值),存儲在NVM中。
固化故障
4
TestNotCompletedSinceLastClear
自上次清除后,該DTC從未被測試過。
測試未運行
5
TestFailedSinceLastClear
自上次清除后,至少一次測試結果為失敗。
永久歷史標志
6
TestNotCompletedThisOperationCycle
當前操作循環中,該DTC測試未完成。
本循環未測
7
WarningIndicatorRequested
請求點亮警告燈(如MIL燈)。
報警標志
2.2 常用狀態位組合(十六進制值)
在實際診斷中,工具通常通過讀取狀態字節來判斷故障類型:
狀態位組合 (Bit)
Hex
含義解釋
bit0=1
0x01
當前正好有故障(瞬態)
bit3=1
0x08
歷史確認故障(存儲在內存中)
bit3=1, bit0=1
0x09
當前存在且已確認的硬故障
bit2=1
0x04
待處理故障(防抖中,未確認)
bit5=1
0x20
上次清除后發生過故障(用于二手車檢測)
3. 狀態位跳變邏輯(核心難點)
狀態位并不是隨機變化的,而是遵循“測試-防抖-確認-老化”的嚴格狀態機。
3.1 跳變流程圖解
下圖中,橫坐標為操作循環(點火循環)。假設該DTC的確認閾值(Confirmed Threshold)為 2個操作循環。
操作循環 1 操作循環 2
|-----------------------| |-----------------------|
測試結果: 無 合格(Pass) 失敗(Fail) 失敗 無 失敗
| | | | | | | |
bit0(當前):0-->0-->1-->0-->1------------>0?-->1----------->? (車企自定義)
bit1(本循環):0-->0-->1-->1-->1------------>0-->1----------->1
bit3(確認):0-->0-->0-->0-->0------------>0-->0-->1(計數2)->1
bit6(未測):1-->0-->0-->0-->0------------>1-->0----------->0
3.2 關鍵跳變邏輯詳解初始化 :ECU上電或執行14服務后,
bit4=1,bit6=1(表示尚未測試)。**測試通過 (Passed)**:當監控器執行檢測且結果為“合格”。
bit0置 0,bit4置 0,bit6置 0。
測試失敗 (Failed) - 防抖階段 :
一旦檢測到失敗,**
bit0立即置 1**。bit1置 1(本循環發生過失敗)。bit2(Pending) 置 1。注意 :此時
bit3(Confirmed) 不一定為1,需要計數器累加。
從 Pending 到 Confirmed :
內部計數器
DTCFailureCounter累加。當
FailureCounter >= ConfirmationThreshold(如 2)時,**bit3置 1**,故障寫入NVM。
**跨操作循環 (Power Cycle)**:
下電再上電(操作循環2開始):
bit6被初始化為 1(本循環還未測)。如果故障消失,
bit0變為 0,但bit3維持 1(歷史故障)。bit1重置為 0(新的循環開始)。
0x14 服務用于清除ECU中一個或多個DTC的相關信息(狀態位、快照、擴展數據、計數器)。
4.1 報文格式
請求 (Request):14 [GroupOfDTC]
14: SID (Service Identifier)GroupOfDTC(3字節): 指定清除范圍。最常用的是FF FF FF,代表清除所有DTC。
肯定響應 (Positive Response):54 [GroupOfDTC]
54: 肯定響應SID(14 + 0x40)
否定響應 (Negative Response):7F 14 [NRC]
常見NRC:
13: 報文長度錯誤。22: 當前條件不滿足(例如車輛速度不為0時禁止清除)。31: 請求的DTC組不支持。
ECU收到14服務后,執行流程如下:
1. 驗證長度 (len == 4?) -> 否則返回 NRC 13
2. 驗證 GroupOfDTC 支持性 -> 不支持返回 NRC 31
3. 檢查安全條件 (例如: 是否已解鎖SecurityAccess) -> 否返回 NRC 22
4. 遍歷DTC列表:
- 清除狀態字節 (置為特定值,通常是 0x00 或 0x40/0x80)
- 清除快照數據 (Snapshot)
- 清除擴展數據 (Extended Data)
- 重置 Confirmation Counter 和 Aging Counter
5. 返回肯定響應 0x54
5. C++代碼實現示例以下是一個在ECU端模擬DTC狀態管理及14服務的C++類實現。
代碼輸出預期#include
#include
#include
#include
#include
// 模擬DTC結構體
struct DtcInfo {
uint32_t id; // DTC編號 (如 0x123456)
uint8_t status; // 狀態位
uint8_t failureCounter; // 確認計數器 (用于防抖)
bool existsInNvm; // 是否已存儲在NVM中
DtcInfo(uint32_t dtcId) : id(dtcId), status(0x40), failureCounter(0), existsInNvm(false) {
// 初始狀態: TestNotCompletedSinceLastClear (bit4=1)
}
};
class UdsDiagnosticManager {
private:
std::map dtcDatabase; // 存儲所有DTC
uint8_t sessionMode; // 當前會話 (默認1-默認會話, 2-編程會話等)
// 模擬NVM讀寫 (生產環境需調用Flash驅動)
void WriteToNvm(uint32_t dtcId, uint8_t status) {
std::cout << "[NVM] 寫入DTC: 0x" << std::hex << dtcId << " 狀態: 0x" << (int)status << std::endl;
}
void EraseNvmForDtc(uint32_t dtcId) {
std::cout << "[NVM] 擦除DTC記錄: 0x" << std::hex << dtcId << std::endl;
}
// 核心邏輯: 更新DTC狀態 (當監控器上報測試結果時調用)
void UpdateDtcStatus(DtcInfo& dtc, bool testResultPassed) {
uint8_t oldStatus = dtc.status;
// 1. 清除 "測試未完成" 標志 (bit4和bit6)
dtc.status &= ~0x50; // 清除 bit4(0x40) 和 bit6(0x10)? 注意掩碼: bit4=16 (0x10), bit6=64 (0x40) -> 糾正: bit6=64, bit4=16
// 糾正掩碼: bit4=0x10, bit6=0x40, 兩者清除: ~0x50
dtc.status &= ~0x50;
if (testResultPassed) {
// 測試合格: 清除當前故障標志
dtc.status &= ~0x01; // bit0 = 0
// 如果當前是 "待確認" 狀態,且計數器遞減? (實際邏輯更復雜,這里簡化)
if (dtc.failureCounter > 0) {
// 防抖遞減邏輯: 如果連續合格,計數器減1,但不低于0
// 此處簡化為: 如果計數器小于閾值,暫時不清除Confirmed標志
}
std::cout << "診斷結果: 通過 (Pass) -> DTC 0x" << std::hex << dtc.id << std::endl;
}
else {
// 測試失敗: 置位當前故障標志
dtc.status |= 0x01; // bit0 = 1 (TestFailed)
dtc.status |= 0x02; // bit1 = 1 (TestFailedThisOpCycle)
dtc.status |= 0x04; // bit2 = 1 (PendingDTC)
dtc.status |= 0x20; // bit5 = 1 (TestFailedSinceLastClear)
// 防抖計數: 增加FailureCounter
dtc.failureCounter++;
std::cout << "診斷結果: 失敗 (Fail), 當前計數器=" << (int)dtc.failureCounter << std::endl;
// 檢查確認閾值 (假設閾值為2)
if (dtc.failureCounter >= 2) {
if (!(dtc.status & 0x08)) { // bit3 = 0 尚未確認
dtc.status |= 0x08; // bit3 = 1 (ConfirmedDTC)
std::cout << "故障已確認 (Confirmed)! 寫入NVM." << std::endl;
// 存儲到NVM
WriteToNvm(dtc.id, dtc.status);
dtc.existsInNvm = true;
}
}
}
std::cout << "狀態更新: 0x" << std::hex << (int)oldStatus << " -> 0x" << (int)dtc.status << std::endl;
}
public:
UdsDiagnosticManager() : sessionMode(1) {}
// 模擬診斷監控器調用 (周期性執行)
void ReportTestResult(uint32_t dtcId, bool passed) {
auto it = dtcDatabase.find(dtcId);
if (it == dtcDatabase.end()) {
// 動態創建DTC (如果不存在)
dtcDatabase.emplace(dtcId, DtcInfo(dtcId));
it = dtcDatabase.find(dtcId);
}
UpdateDtcStatus(it->second, passed);
}
// 實現14服務 (清除診斷信息)
std::vector HandleService_14(const std::vector& request) {
std::vector response;
// 1. 長度檢查: 14服務請求必須為 4字節 (SID + 3字節 GroupOfDTC)
if (request.size() != 4) {
response = {0x7F, 0x14, 0x13}; // NRC 13: incorrectMessageLength
return response;
}
// 提取 GroupOfDTC (例如 0xFFFFFF 表示清除所有)
uint32_t group = (request[1] << 16) | (request[2] << 8) | request[3];
// 2. 會話檢查 (某些組需要編程會話)
if (group == 0xFFFF00 && sessionMode != 2) { // 假設清除所有DTC需要編程會話
response = {0x7F, 0x14, 0x22}; // NRC 22: conditionsNotCorrect
return response;
}
// 3. 執行清除操作
std::cout << "\n[14服務] 收到清除請求, Group: 0x" << std::hex << group << std::endl;
if (group == 0xFFFFFF) { // 清除所有DTC
for (auto& pair : dtcDatabase) {
DtcInfo& dtc = pair.second;
// 清除狀態位: 重置為 0x40 (TestNotCompletedSinceLastClear)
dtc.status = 0x40;
dtc.failureCounter = 0;
EraseNvmForDtc(dtc.id);
dtc.existsInNvm = false;
std::cout << "清除DTC: 0x" << std::hex << dtc.id << std::endl;
}
// 如果允許CDD抑制,還需清除全局快照數據
}
else if (group == 0x000001) { // 清除特定組: 排放相關
// 遍歷過濾邏輯...
}
// 4. 返回肯定響應
response = {0x54, request[1], request[2], request[3]};
return response;
}
// 打印所有DTC當前狀態 (用于調試)
void PrintAllDtcStatus() {
std::cout << "\n========== 當前DTC列表 ==========" << std::endl;
for (const auto& pair : dtcDatabase) {
std::cout << "DTC: 0x" << std::hex << pair.first
<< " | Status: 0x" << (int)pair.second.status
<< " | FailCnt: " << std::dec << (int)pair.second.failureCounter
<< std::endl;
}
std::cout << "================================\n" << std::endl;
}
};// 主函數示例
int main() {
UdsDiagnosticManager diag;
// 場景模擬: 模擬一個電壓故障 (DTC 0x123456)
uint32_t voltDtc = 0x123456;
std::cout << "=== 操作循環 1 開始 ===" << std::endl;
diag.ReportTestResult(voltDtc, false); // 第一次失敗 -> Pending
diag.PrintAllDtcStatus();
diag.ReportTestResult(voltDtc, false); // 第二次連續失敗 -> Confirmed (bit3=1)
diag.PrintAllDtcStatus();
std::cout << "\n=== 操作循環 2 開始 (模擬下電上電) ===" << std::endl;
// 注意: 在實際ECU中,跨循環時會重置 bit1=0, bit6=1,此處省略模擬重置函數,僅演示清除邏輯
std::cout << "\n=== 執行 14 服務清除故障 ===" << std::endl;
std::vector clearReq = {0x14, 0xFF, 0xFF, 0xFF};
auto resp = diag.HandleService_14(clearReq);
// 打印響應
if (resp[0] == 0x54) {
std::cout << "14服務肯定響應成功!" << std::endl;
} else if (resp[0] == 0x7F) {
std::cout << "14服務拒絕, NRC: 0x" << std::hex << (int)resp[2] << std::endl;
}
diag.PrintAllDtcStatus(); // 觀察狀態位被重置為 0x40
return 0;
}
6. 總結=== 操作循環 1 開始 ===
診斷結果: 失敗 (Fail), 當前計數器=1
狀態更新: 0x40 -> 0x27 (二進制: 0010 0111 -> bit0,1,2,5 = 1)
========== 當前DTC列表 ==========
DTC: 0x123456 | Status: 0x27 | FailCnt: 1
診斷結果: 失敗 (Fail), 當前計數器=2
故障已確認 (Confirmed)! 寫入NVM.
狀態更新: 0x27 -> 0x2F (bit3 變 1)
========== 當前DTC列表 ==========
DTC: 0x123456 | Status: 0x2F | FailCnt: 2
=== 執行 14 服務清除故障 ===
[14服務] 收到清除請求, Group: 0xffffff
[NVM] 擦除DTC記錄: 0x123456
清除DTC: 0x123456
14服務肯定響應成功!========== 當前DTC列表 ==========
DTC: 0x123456 | Status: 0x40 | FailCnt: 0
狀態位是動態的 :
bit0代表此時此刻,bit3代表歷史包袱,bit5代表自上次清零后的“案底”。跳變依賴防抖機制 :從
Pending (bit2)到Confirmed (bit3)需要達到預設的失敗計數閾值,防止偶發干擾導致誤報。14服務是重置動作 :它不僅清除狀態位,還會銷毀快照和計數器。執行14服務前通常需要
SecurityAccess(27服務) 解鎖,且不同DTC組可能對應不同權限。開發建議 :在ECU代碼中,務必使用狀態機管理DTC,并嚴格區分 RAM 中的當前狀態和 NVM 中的固化狀態。診斷工具側讀取到
0x08(Confirmed DTC) 時,即可認為車輛確實存在歷史故障記錄。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
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.