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

UDS 0x85和0x22服务原理及代码示例

0
分享至


1. 诊断故障码设置控制服务 (ControlDTCSetting, 0x85) 1.1 服务概述

诊断故障码设置控制服务(0x85)用于动态地启用或禁用ECU内部诊断故障码(DTC)的记录功能。该服务通常用于维修或测试场景,避免在特定操作(如刷写、标定)期间因非真实故障产生误报。

根据ISO 14229-1标准,本服务具备以下关键行为:

  • 抑制/恢复记录:通过子函数参数指示ECU停止或重新开始记录DTC。

  • 会话层时序影响:若当前会话模式下抑制了DTC记录,当会话层时序参数(如P2Server_max)超时导致ECU自动返回默认会话(Default Session,0x01),DTC记录应自动恢复。

  • 复位影响:ECU执行任何硬件复位(上电复位、外部复位等)后,DTC记录功能恢复为默认允许状态。

  • 与清除服务联动:当诊断仪发送ClearDiagnosticInformation(0x14)服务清除DTC时,ECU必须重新开启DTC记录(即使之前处于抑制状态)。

1.2 报文格式 1.2.1 请求报文

字节序号

参数名称

值(hex)

0

SID

0x85

服务标识符

1

sub-function

0x01–0x02

DTC设置类型:
0x01 = off(停止记录)
0x02 = on(开始记录)

2…n

可选参数(保留)

标准中通常无额外参数,部分OEM扩展使用


注意:子函数字节的高四位为suppressPosRspMsgIndicationBit(0x00表示需要正响应),低四位为实际控制类型。
1.2.2 正响应报文

字节序号

参数名称

值(hex)

0

SID + 0x40

0xC5

服务正响应标识符

1

sub-function

0x01或0x02

回显请求中的控制类型

2…n

可选参数

标准无后续数据


1.2.3 负响应报文

字节序号

参数名称

值(hex)

0

0x7F

0x7F

负响应标识符

1

SID

0x85

原始服务标识符

2

NRC

见下表

负响应码(Negative Response Code)

常用NRC:

NRC

含义

0x12

子函数不支持(sub-function无效)

0x13

请求报文长度错误

0x22

条件不满足(例如在非扩展会话下请求)

0x31

请求超出范围(参数错误)


2. 通过标识符读取数据服务 (ReadDataByIdentifier, 0x22) 2.1 服务概述

通过数据标识符(DID,Data Identifier)读取数据服务允许诊断仪从ECU的存储器中读取一个或多个指定DID对应的数据记录。DID为两个字节(0x0000–0xFFFF),由车厂定义。

标准支持单请求多DID,但多数实现仅支持单个DID。下文以单DID为例说明。

2.2 报文格式 2.2.1 请求报文

字节序号

参数名称

值(hex)

0

SID

0x22

服务标识符

1

DID 高字节

0x00–0xFF

数据标识符高位

2

DID 低字节

0x00–0xFF

数据标识符低位

3…n

后续DID(可选)

多DID时重复字节1-2


2.2.2 正响应报文

字节序号

参数名称

值(hex)

0

SID + 0x40

0x62

服务正响应标识符

1

DID 高字节

0x00–0xFF

回显请求中的DID高位

2

DID 低字节

0x00–0xFF

回显请求中的DID低位

3…m

数据记录

可变

该DID对应的数据值

m+1…n

下一个DID+数据

无(多DID时重复)

仅当请求多个DID时存在


2.2.3 负响应报文

字节序号

参数名称

值(hex)

0

0x7F

0x7F

负响应标识符

1

SID

0x22

原始服务标识符

2

NRC

见下表

负响应码

常用NRC:

NRC

含义

0x13

请求报文长度错误

0x14

数据标识符不支持

0x22

条件不满足

0x31

请求超出范围(DID有效但无法读取)


3. C++代码实现示例

以下代码模拟一个简化但符合UDS行为规范的ECU,实现了:

  • ControlDTCSetting(0x85) 服务。

  • ReadDataByIdentifier(0x22) 服务。

  • 与ClearDiagnosticInformation(0x14) 的联动。

  • 会话超时与复位后自动恢复DTC记录的逻辑(通过定时器和复位标志模拟)。

#include  

#include
#include
#include
#include
#include
#include

// ---------- 辅助工具函数 ----------
// 将字节向量打印为十六进制
void printHex(const std::vector& data, const std::string& prefix = "") {
std::cout << prefix;
for (uint8_t b : data) {
printf("%02X ", b);
}
std::cout << std::endl;
}

// ---------- UDS 服务定义 ----------
const uint8_t SID_CONTROL_DTC_SETTING = 0x85;
const uint8_t SID_READ_DATA_BY_IDENTIFIER = 0x22;
const uint8_t SID_CLEAR_DIAG_INFO = 0x14;

// 子函数定义 (ControlDTCSetting)
const uint8_t DTC_SETTING_OFF = 0x01;
const uint8_t DTC_SETTING_ON = 0x02;

// DID 定义(示例)
const uint16_t DID_VIN = 0xF190;
const uint16_t DID_SW_VERSION = 0xF187;
const uint16_t DID_ECU_SERIAL = 0xF1A0;

// 负响应码 (NRC)
const uint8_t NRC_SUB_FUNCTION_NOT_SUPPORTED = 0x12;
const uint8_t NRC_INCORRECT_MESSAGE_LEN = 0x13;
const uint8_t NRC_REQUEST_OUT_OF_RANGE = 0x31;
const uint8_t NRC_CONDITIONS_NOT_CORRECT = 0x22;
const uint8_t NRC_DATA_IDENTIFIER_NOT_SUPP = 0x14;

// 简单模拟ECU环境
class EcuSimulator {
public:
EcuSimulator() : dtcRecordingEnabled_(true), currentSession_(0x01) // 默认会话
{
// 初始化模拟数据
vin_ = "1HGCM82633A123456";
swVersion_ = "2.1.0";
ecuSerial_ = "ECU_ABC123";
}

// 接收诊断请求(完整CAN帧数据域),返回响应数据
std::vector handleRequest(const std::vector& request) {
if (request.empty()) return buildNegativeResponse(0x00, NRC_INCORRECT_MESSAGE_LEN);

uint8_t sid = request[0];
switch (sid) {
case SID_CONTROL_DTC_SETTING:
return handleControlDTCSetting(request);
case SID_READ_DATA_BY_IDENTIFIER:
return handleReadDataByIdentifier(request);
case SID_CLEAR_DIAG_INFO:
return handleClearDiagnosticInfo(request);
default:
return buildNegativeResponse(sid, NRC_REQUEST_OUT_OF_RANGE);
}
}

// 模拟ECU复位(例如调用此函数后恢复DTC记录)
void performReset() {
std::cout << "[ECU] Performing reset...\n";
dtcRecordingEnabled_ = true; // 复位后恢复DTC记录
// 可选:切换到默认会话
currentSession_ = 0x01;
}

// 模拟会话超时(例如长时间无请求自动调用此函数)
void sessionTimeout() {
if (currentSession_ != 0x01) {
std::cout << "[ECU] Session timeout, switching to default session (0x01)\n";
currentSession_ = 0x01;
dtcRecordingEnabled_ = true; // 根据标准,会话超时返回默认会话后应恢复DTC记录
}
}

// 获取当前DTC记录状态(供外部监控)
bool isDtcRecordingEnabled() const { return dtcRecordingEnabled_; }

private:
bool dtcRecordingEnabled_; // DTC记录使能标志
uint8_t currentSession_; // 当前会话(0x01=默认, 0x02=编程等)
// 模拟数据
std::string vin_;
std::string swVersion_;
std::string ecuSerial_;

// 构建负响应
std::vector buildNegativeResponse(uint8_t sid, uint8_t nrc) const {
return {0x7F, sid, nrc};
}

// 处理 0x85 ControlDTCSetting
std::vector handleControlDTCSetting(const std::vector& req) {
// 最小长度:SID(1) + sub-function(1) = 2
if (req.size() < 2) {
return buildNegativeResponse(SID_CONTROL_DTC_SETTING, NRC_INCORRECT_MESSAGE_LEN);
}

uint8_t subFunc = req[1];
// 低四位为控制类型,高四位为抑制正响应标志(本例忽略抑制标志)
uint8_t controlType = subFunc & 0x0F;

// 可选:检查会话条件(例如只在扩展会话下允许)
if (currentSession_ != 0x02) { // 假设0x02为扩展诊断会话
return buildNegativeResponse(SID_CONTROL_DTC_SETTING, NRC_CONDITIONS_NOT_CORRECT);
}

bool newState;
switch (controlType) {
case DTC_SETTING_OFF:
newState = false;
break;
case DTC_SETTING_ON:
newState = true;
break;
default:
return buildNegativeResponse(SID_CONTROL_DTC_SETTING, NRC_SUB_FUNCTION_NOT_SUPPORTED);
}

dtcRecordingEnabled_ = newState;
std::cout << "[ECU] DTC recording has been " << (dtcRecordingEnabled_ ? "ENABLED" : "DISABLED")
<< " via 0x85 service.\n";

// 正响应:0xC5 + sub-function(原样返回)
return {static_cast(SID_CONTROL_DTC_SETTING + 0x40), subFunc};
}

// 处理 0x22 ReadDataByIdentifier
std::vector handleReadDataByIdentifier(const std::vector& req) {
// 最小长度:SID(1) + DID(2) = 3
if (req.size() < 3) {
return buildNegativeResponse(SID_READ_DATA_BY_IDENTIFIER, NRC_INCORRECT_MESSAGE_LEN);
}

uint16_t did = (static_cast(req[1]) << 8) | req[2];
std::vector data;

// 根据DID获取数据
if (did == DID_VIN) {
data.assign(vin_.begin(), vin_.end());
} else if (did == DID_SW_VERSION) {
data.assign(swVersion_.begin(), swVersion_.end());
} else if (did == DID_ECU_SERIAL) {
data.assign(ecuSerial_.begin(), ecuSerial_.end());
} else {
return buildNegativeResponse(SID_READ_DATA_BY_IDENTIFIER, NRC_DATA_IDENTIFIER_NOT_SUPP);
}

// 正响应:0x62 + DID + 数据
std::vector response;
response.push_back(SID_READ_DATA_BY_IDENTIFIER + 0x40);
response.push_back(req[1]); // DID高字节
response.push_back(req[2]); // DID低字节
response.insert(response.end(), data.begin(), data.end());
return response;
}

// 处理 0x14 ClearDiagnosticInformation
std::vector handleClearDiagnosticInfo(const std::vector& req) {
// 标准中0x14可能携带清除范围参数,此处简化:清除所有DTC并重新开启记录
// 实际实现中应真正清除存储的DTC列表
std::cout << "[ECU] Clearing all DTCs and re-enabling DTC recording.\n";
dtcRecordingEnabled_ = true; // 清除后必须恢复记录
// 正响应:0x54 (SID+0x40)
return {static_cast(SID_CLEAR_DIAG_INFO + 0x40)};
}
};

// ---------- 演示示例 ----------
int main() {
EcuSimulator ecu;

// 初始化:DTC记录默认开启
std::cout << "Initial DTC recording state: " << (ecu.isDtcRecordingEnabled() ? "Enabled" : "Disabled") << "\n\n";

// 模拟诊断仪发送 0x85 请求(停止记录)
std::vector req85_off = {0x85, 0x01}; // sub-function 0x01 = off
std::cout << "Request 0x85 (stop DTC recording): ";
printHex(req85_off);
auto resp85_off = ecu.handleRequest(req85_off);
printHex(resp85_off, "Response: ");
std::cout << "DTC recording state after request: " << (ecu.isDtcRecordingEnabled() ? "Enabled" : "Disabled") << "\n\n";

// 尝试读取一个DID(VIN)
std::vector req22_vin = {0x22, 0xF1, 0x90};
std::cout << "Request 0x22 (read VIN): ";
printHex(req22_vin);
auto resp22_vin = ecu.handleRequest(req22_vin);
printHex(resp22_vin, "Response: ");
std::string vinStr(resp22_vin.begin() + 3, resp22_vin.end());
std::cout << "VIN: " << vinStr << "\n\n";

// 模拟会话超时(应自动恢复DTC记录)
std::cout << "Simulating session timeout...\n";
ecu.sessionTimeout();
std::cout << "DTC recording state after timeout: " << (ecu.isDtcRecordingEnabled() ? "Enabled" : "Disabled") << "\n\n";

// 模拟ECU复位
std::cout << "Simulating ECU reset...\n";
ecu.performReset();
std::cout << "DTC recording state after reset: " << (ecu.isDtcRecordingEnabled() ? "Enabled" : "Disabled") << "\n\n";

// 模拟发送 0x14 清除诊断信息
std::vector req14 = {0x14, 0xFF, 0xFF}; // 简化的清除所有DTC
std::cout << "Request 0x14 (clear DTCs): ";
printHex(req14);
auto resp14 = ecu.handleRequest(req14);
printHex(resp14, "Response: ");
std::cout << "DTC recording state after clear: " << (ecu.isDtcRecordingEnabled() ? "Enabled" : "Disabled") << "\n\n";

return 0;
}
3.1 代码说明
  1. EcuSimulator类:

  • dtcRecordingEnabled_标志位模拟DTC记录状态。

  • handleControlDTCSetting:检查会话条件(要求扩展会话0x02),修改标志位,返回0xC5+子函数。

  • handleReadDataByIdentifier:支持三个示例DID,返回ASCII字符串数据。

  • handleClearDiagnosticInfo:模拟清除所有DTC,并将dtcRecordingEnabled_强制置为true。

会话超时与复位:

  • sessionTimeout():将当前会话切回默认会话(0x01),同时恢复DTC记录。

  • performReset():模拟硬件复位,恢复DTC记录。

符合标准的行为:

  • 0x85请求中若子函数无效返回NRC 0x12。

  • 非扩展会话下执行0x85返回NRC 0x22(条件不满足)。

  • 0x14服务后自动使能记录。

3.2 运行输出示例

Initial DTC recording state: Enabled

Request 0x85 (stop DTC recording): 85 01
[ECU] DTC recording has been DISABLED via 0x85 service.
Response: C5 01
DTC recording state after request: Disabled

Request 0x22 (read VIN): 22 F1 90
Response: 62 F1 90 31 48 47 43 4D 38 32 36 33 33 41 31 32 33 34 35 36
VIN: 1HGCM82633A123456

Simulating session timeout...
[ECU] Session timeout, switching to default session (0x01)
DTC recording state after timeout: Enabled

Simulating ECU reset...
[ECU] Performing reset...
DTC recording state after reset: Enabled

Request 0x14 (clear DTCs): 14 FF FF
[ECU] Clearing all DTCs and re-enabling DTC recording.
Response: 54
DTC recording state after clear: Enabled
4. 总结

本文详细解析了UDS服务ControlDTCSetting(0x85) 和ReadDataByIdentifier(0x22) 的协议格式、行为约束,并通过C++代码给出了符合ISO 14229-1规范的实现示例。实际量产ECU中还需考虑多DID读取、安全访问、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.

相关推荐
热点推荐
差严子怡8米!日本奥运冠军痛哭:不甘心让她一枝独秀 明年要赢她

差严子怡8米!日本奥运冠军痛哭:不甘心让她一枝独秀 明年要赢她

风过乡
2026-09-28 09:06:08
洛夫顿离开上海得不偿失!发文开启勿扰模式,重返大鲨鱼障碍重重

洛夫顿离开上海得不偿失!发文开启勿扰模式,重返大鲨鱼障碍重重

体育见习官
2026-09-28 07:58:50
时隔两年半冲突视频曝光!斯图尔特挥拳尤班克斯 曾因此被禁赛3场

时隔两年半冲突视频曝光!斯图尔特挥拳尤班克斯 曾因此被禁赛3场

罗说NBA
2026-09-28 06:21:57
曼联无意让卡里克下课,重用拉什福德起作用!聘拉爵心仪主帅需1500万

曼联无意让卡里克下课,重用拉什福德起作用!聘拉爵心仪主帅需1500万

罗米的曼联博客
2026-09-28 10:14:03
CBA速递,上海大鲨鱼锁定麦基,六十万美元非常平价,三剑客浮现

CBA速递,上海大鲨鱼锁定麦基,六十万美元非常平价,三剑客浮现

体坛小快灵
2026-09-28 08:43:41
“升糖直接爆了”,家长晒儿子上学早餐,网友:吃完了倒头就睡

“升糖直接爆了”,家长晒儿子上学早餐,网友:吃完了倒头就睡

泽泽先生
2026-09-21 13:37:01
刘欢病逝2天,别墅、版权收入等资产曝光,遗产分配成焦点

刘欢病逝2天,别墅、版权收入等资产曝光,遗产分配成焦点

往史过眼云烟
2026-09-27 16:40:27
儿子作文里写:“我爸爸妈妈从来不吵架,但他们也不怎么说话”

儿子作文里写:“我爸爸妈妈从来不吵架,但他们也不怎么说话”

自由心向往之
2026-09-25 08:30:13
拒绝网红脸!央视秋晚四美火出圈,观众:这才是真审美

拒绝网红脸!央视秋晚四美火出圈,观众:这才是真审美

阿废冷眼观察所
2026-09-27 12:56:52
国家统计局:2026年1—8月份全国规模以上工业企业利润增长15.7%

国家统计局:2026年1—8月份全国规模以上工业企业利润增长15.7%

界面新闻
2026-09-28 09:31:49
台湾提出和统条件:一国三制,“外交权”和拥有军队?是痴心妄想

台湾提出和统条件:一国三制,“外交权”和拥有军队?是痴心妄想

老头的传奇色彩
2026-08-06 17:59:31
广州一工人误踩8层自建房楼顶绿色帆布坠入电梯井,连破两道安全网跌至一楼,调查报告披露:承包人无资质冒用他人名义,未设警示标志

广州一工人误踩8层自建房楼顶绿色帆布坠入电梯井,连破两道安全网跌至一楼,调查报告披露:承包人无资质冒用他人名义,未设警示标志

扬子晚报
2026-09-28 10:35:00
红薯正大量上市!研究发现:糖尿病吃一次红薯,等于给血糖添堵?

红薯正大量上市!研究发现:糖尿病吃一次红薯,等于给血糖添堵?

老李讲健康
2026-09-28 07:30:07
“磨膝大户”被揪出,是跑步的20倍,医生:不想软骨磨光,早扔掉

“磨膝大户”被揪出,是跑步的20倍,医生:不想软骨磨光,早扔掉

看世界的人
2026-09-20 22:04:47
王思聪坐香奈儿VIP贵宾室,懒懒旁边试包,消费降级传闻又被打脸

王思聪坐香奈儿VIP贵宾室,懒懒旁边试包,消费降级传闻又被打脸

梦醉为红颜一笑
2026-09-27 14:27:39
骁龙8EE6+11000mAh!荣耀新机官宣,9月28日发布

骁龙8EE6+11000mAh!荣耀新机官宣,9月28日发布

科技堡垒
2026-09-28 10:19:38
“抱歉,我们不喜欢肥头大耳的”,女孩公开追求体制内男,面相输了

“抱歉,我们不喜欢肥头大耳的”,女孩公开追求体制内男,面相输了

世界圈
2026-08-15 10:29:14
新央企首任董事长,未公布被调查就直接“双开”

新央企首任董事长,未公布被调查就直接“双开”

评论员岳连
2026-09-27 20:54:46
一个国家能蠢到什么程度?看看法国就明白了:法国黑人接近800万,巴黎新生儿里70%是黑人

一个国家能蠢到什么程度?看看法国就明白了:法国黑人接近800万,巴黎新生儿里70%是黑人

怪味历史连连看
2026-09-08 01:55:32
越老越妖,梅西30岁后罚进43粒直接任意球,比30岁前多10粒

越老越妖,梅西30岁后罚进43粒直接任意球,比30岁前多10粒

懂球帝
2026-09-28 10:05:05
2026-09-28 11:35:00
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
1015文章数 348关注度
往期回顾 全部

科技要闻

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

头条要闻

牛弹琴:内塔尼亚胡有大麻烦了 不是命硬就能扛过去的

头条要闻

牛弹琴:内塔尼亚胡有大麻烦了 不是命硬就能扛过去的

体育要闻

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

娱乐要闻

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

财经要闻

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

汽车要闻

MAZDA EZ-60激光版上市 焕新全系11.39万元起

态度原创

本地
艺术
亲子
教育
手机

本地新闻

中秋逛白塔寺,体验国医妙荟雅集

艺术要闻

致敬,刘欢硬笔书法欣赏

亲子要闻

江苏产妇产下5斤9两男宝,脐带刚剪断,宝宝突然刺耳尖叫

教育要闻

欧洲名校也缺钱修楼?柏林高校开始发愁“楼太破”!

手机要闻

涨价了照样买 iPhone 18 Pro系列国内销量上涨

无障碍浏览 进入关怀版