网易首页 > 网易号 > 正文 申请入驻

UDS 14服务(ClearDiagnosticInformation)详解:原理、C++实现与测试用例

0
分享至


一、服务概要

  • 服务名称:ClearDiagnosticInformation (CDTCI)

  • **服务标识 (SID)**:0x14

  • **肯定响应 (PRSID)**:0x54

  • 功能摘述:客户端请求清除ECU内存中存储的诊断信息,这些信息主要指故障码 (DTC) 及与之关联的快照数据、扩展数据和各类统计信息。

  • 典型场景:软件更新后清除陈旧信息以避免干扰、生产线下线检测关闭时的故障记录初始化,以及维修保养结束或高级服务执行前重置历史数据。

二、消息格式与NRC 1. 请求格式

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 对应排放/动力总成组。

2. 肯定响应
  • 格式: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. 定义核心组件和类结构

#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;
}
}
};
2. 模拟通讯运行函数

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.

相关推荐
热点推荐
俄罗斯总统普京公开表示:爱沙尼亚防长声称要进攻俄罗斯,纯属胡说八道,马戏团走了,小丑留下了,爱沙尼亚全国人口还没俄军人数多

俄罗斯总统普京公开表示:爱沙尼亚防长声称要进攻俄罗斯,纯属胡说八道,马戏团走了,小丑留下了,爱沙尼亚全国人口还没俄军人数多

吉刻新闻
2026-09-28 12:32:49
刘青云携妻子郭蔼明现身卡定沟游玩,模样越来越像萨达姆,一个黑脸一个笑脸对比鲜明

刘青云携妻子郭蔼明现身卡定沟游玩,模样越来越像萨达姆,一个黑脸一个笑脸对比鲜明

裕丰娱间说
2026-09-27 13:57:53
涉案金额过亿 刘应成(原法名释永信)一审被判有期徒刑24年

涉案金额过亿 刘应成(原法名释永信)一审被判有期徒刑24年

每日经济新闻
2026-05-30 00:42:59
权贵们绕开高考走捷径:北理工裴轶和协会 4+4 一个路数

权贵们绕开高考走捷径:北理工裴轶和协会 4+4 一个路数

放开他让wo来
2026-09-27 13:45:46
亚运会最新奖牌榜:日本157枚,韩国83枚,中国健儿太让国人自豪

亚运会最新奖牌榜:日本157枚,韩国83枚,中国健儿太让国人自豪

锅锅爱历史
2026-09-28 06:23:47
被质疑放水输球!混双丢冠,孙颖莎王楚钦开心互动,谁注意王楚钦表态

被质疑放水输球!混双丢冠,孙颖莎王楚钦开心互动,谁注意王楚钦表态

懂球社
2026-09-27 11:25:19
日本:引进中国人,韩国人,甚至越南人都可以,但绝对不引进印度人和穆斯林!

日本:引进中国人,韩国人,甚至越南人都可以,但绝对不引进印度人和穆斯林!

步论天下事
2026-09-28 10:50:23
“没想到一枪就‘下班’了”,18岁严子怡只投了一枪,拿下金牌,大比分碾压日本名将!她曾放话:未来,开启一个属于我的新时代吧

“没想到一枪就‘下班’了”,18岁严子怡只投了一枪,拿下金牌,大比分碾压日本名将!她曾放话:未来,开启一个属于我的新时代吧

南方都市报
2026-09-28 11:58:41
天彻底塌了!亚运全线溃败零金收官,中国篮球已跌至谷底!

天彻底塌了!亚运全线溃败零金收官,中国篮球已跌至谷底!

田先生篮球
2026-09-25 17:24:52
女友在亚马尔社媒评论:我还是觉得你也太帅了,太不真实了

女友在亚马尔社媒评论:我还是觉得你也太帅了,太不真实了

懂球帝
2026-09-27 21:29:20
金卡戴珊全家逛上海野生动物园,紧身裤配高跟鞋,这打扮真够精致

金卡戴珊全家逛上海野生动物园,紧身裤配高跟鞋,这打扮真够精致

悦君兮君不知
2026-09-28 11:21:46
三毛说我去非洲是为了帮助黑人,李敖反问:你为什么不帮助黄人?

三毛说我去非洲是为了帮助黑人,李敖反问:你为什么不帮助黄人?

言过于诚
2026-09-27 22:31:29
骗走50亿!用小鲜肉的血抗衰,被央视曝光的“捞金女王”,真栽了

骗走50亿!用小鲜肉的血抗衰,被央视曝光的“捞金女王”,真栽了

深析古今
2026-04-08 10:09:38
张本智和:阿拉米扬以往发球就算不上完全合规,现在又肆无忌惮

张本智和:阿拉米扬以往发球就算不上完全合规,现在又肆无忌惮

懂球帝
2026-09-27 15:40:00
“反华妖女”许可馨,回国后曾叫嚣没人敢动她,六年后下场如何?

“反华妖女”许可馨,回国后曾叫嚣没人敢动她,六年后下场如何?

锅锅爱历史
2026-07-26 08:50:12
你做过最龌龊,最下流的事是什么?

你做过最龌龊,最下流的事是什么?

那年秋天
2026-08-16 11:50:09
仔细看,这张拍于2016年的合影照,当时樊振东19岁,那时的樊振东确实还满是青涩感!就不知左边的美女是谁?

仔细看,这张拍于2016年的合影照,当时樊振东19岁,那时的樊振东确实还满是青涩感!就不知左边的美女是谁?

小琦聊生活
2026-09-25 13:24:02
《繁花》里最狠的一条生意经:嘴甜是下等人的本事,忠心是中等人的筹码,能被大人物拉上桌的分蛋糕者,手里攥着这两种教人离不开的硬通货

《繁花》里最狠的一条生意经:嘴甜是下等人的本事,忠心是中等人的筹码,能被大人物拉上桌的分蛋糕者,手里攥着这两种教人离不开的硬通货

心理观察局
2026-08-04 06:38:04
河南一技校101名毕业生入职北大,所涉专业系全国唯一,该校曾入职北大的毕业生:有和北大人才中心签约的,也有劳务派遣

河南一技校101名毕业生入职北大,所涉专业系全国唯一,该校曾入职北大的毕业生:有和北大人才中心签约的,也有劳务派遣

极目新闻
2026-09-27 19:00:11
微信上基本不发朋友圈的人,未必低调,十有八九是这三种人:1、生活过于丰富,不便展示;2、看透人性,藏锋守拙;3、自给自足,太充实

微信上基本不发朋友圈的人,未必低调,十有八九是这三种人:1、生活过于丰富,不便展示;2、看透人性,藏锋守拙;3、自给自足,太充实

品读时刻
2026-09-12 09:06:58
2026-09-28 13:11:00
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
1015文章数 348关注度
往期回顾 全部

科技要闻

智能体惹了多少祸,OpenAI自己没查清!

头条要闻

供销社职工以46600元参与拐卖外籍妇女 获刑5年9个月

头条要闻

供销社职工以46600元参与拐卖外籍妇女 获刑5年9个月

体育要闻

114项指控成立,曼城已经完蛋了吗?

娱乐要闻

好汉刘欢:一副好嗓子,一颗赤子心

财经要闻

标价298元核桃油, 实为大豆油冒充

汽车要闻

神龙科技与Momenta达成全球战略合作 2027年起推新车

态度原创

家居
手机
健康
艺术
公开课

家居要闻

2026建博会(广州) 公装联探展交流活动

手机要闻

首批搭载第六代骁龙8超级至尊版!荣耀Magic9 Pro Max安兔兔跑分超552万

鼻子三角区的痘,千万别乱挤!

艺术要闻

12张效果图,抖音深圳第二总部显真容

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版