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

UDS 诊断服务之 0x22 – 通过标识符读取数据

0
分享至


1. 服务概述

在统一诊断服务(UDS,ISO 14229)中,0x22 – ReadDataByIdentifier是一个最常用的读取服务。它允许诊断工具(Tester)向电子控制单元(ECU)请求一个或几个特定标识符(DID,Data Identifier)对应的数据。这些数据可以是 ECU 的硬/软件版本、车辆识别码(VIN)、序列号、当前会话类型、标定参数,甚至是实时采集的里程、电压、车窗位置等动态信号。

主要特点:

  • 支持读取一个或多个 DID(最多由底层传输协议决定)。

  • DID 占 2 个字节(0x0000 – 0xFFFF),由 ECU 供应商定义。

  • 响应返回 DID 及其对应的原始字节数据。

2. 报文格式 2.1 请求报文

字节偏移

参数名

值(hex)

描述

0

Service ID

0x22

请求服务标识符

1

DID high byte

0xF1

DID 高字节

2

DID low byte

0x8C

DID 低字节

更多 DID(可选)

0xF1 0x90

连续提供多个 DID(2字节/个)

示例请求:22 F1 8C
含义:读取 DID = 0xF18C(ECU 序列号)。

2.2 肯定响应

字节偏移

参数名

值(hex)

描述

0

Response ID

0x62

肯定响应标识符(=0x22+0x40)

1

DID high byte

0xF1

原请求中的 DID 高字节

2

DID low byte

0x8C

原请求中的 DID 低字节

3..n

Data Record

12 34 56 78

该 DID 对应的数据(长度可变)

示例响应:62 F1 8C 12 34 56 78
含义:DID 0xF18C 的数据是 4 个字节0x12,0x34,0x56,0x78。

2.3 否定响应(NRC)

当请求不符合规范或 ECU 无法处理时,返回7F+ SID + NRC:

NRC 代码

含义

0x13

消息长度/格式错误

0x14

数据太长

0x22

条件不满足(如安全等级不足)

0x31

请求超出范围(DID 不支持)


3. 常用 DID 示例(非标准,厂家自定)

DID

描述

数据长度示例

数据内容示意

0xF18C

ECU 序列号

8 字节

"SN123456"

0xF190

VIN码

17 字节

"LFV3A23K9P3123456"

0xF186

当前会话

1 字节

0x01

(默认会话)

0xF187

软件版本

4 字节

0x01 0x02 0x03 0x00

0x1000

当前里程(km)

4 字节

0x00 0x00 0x12 0x34

(4660km)

0x1001

蓄电池电压(mV)

2 字节

0x0D 0x48

(3400mV)


注意:DID 及其含义完全由 ECU 供应商决定。ISO 14229 中仅保留 0x0000–0x00FF 为标准 DID(如 0xF190 常用作 VIN,但不是强制标准)。
4. C++ 代码实现举例

下面给出一个简化但完整的 C++ 示例,模拟 ECU 中的0x22 服务处理逻辑。
代码包含:

  • 一个 DID 数据表(std::map存储 DID 与其字节数据)

  • 解析请求、查找 DID、构造响应

  • 支持单个 DID 读取

  • 处理不支持 DID 的错误(返回 NRC 0x31)

4.1 环境说明
  • C++17 及以上(使用std::vector、std::map)

  • 假设底层 CAN/DoCAN 已剥离传输协议,仅处理应用层消息(完整 UDS 长度 ≤ 8 字节)

4.2 完整代码

#include  

#include
#include
#include
#include

// 模拟 ECU 内部的 DID 数据存储器
class DidStorage {
public:
DidStorage() {
// 初始化一些示例 DID 数据
// DID 0xF18C : ECU 序列号 (8字节)
store[0xF18C] = {0x53, 0x4E, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34}; // "SN001234"
// DID 0xF190 : VIN码 (17字节)
store[0xF190] = {0x4C, 0x46, 0x56, 0x33, 0x41, 0x32, 0x33, 0x4B,
0x39, 0x50, 0x33, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36}; // "LFV3A23K9P3123456"
// DID 0xF186 : 当前会话 (1字节)
store[0xF186] = {0x01}; // 默认会话
// DID 0x1000 : 里程,单位 km (4字节,小端)
store[0x1000] = {0x34, 0x12, 0x00, 0x00}; // 0x1234 = 4660 km
}

// 根据 DID 获取数据,若不存在返回 nullptr
const std::vector* getData(uint16_t did) const {
auto it = store.find(did);
if (it != store.end()) {
return &(it->second);
}
return nullptr;
}

private:
std::map> store;
};

// 处理 0x22 服务请求
// 输入: 完整的 UDS 请求报文 (已剥离传输层,仅应用层数据)
// 输出: 响应报文 (肯定或否定)
std::vector handleReadDataByIdentifier(const std::vector& request, const DidStorage& storage) {
// 最小请求长度: 1字节SID + 2字节DID = 3
if (request.size() < 3 || request[0] != 0x22) {
// 格式错误或非0x22服务 -> 返回 NRC 0x13 (消息长度/格式错误)
return {0x7F, 0x22, 0x13};
}

// 目前仅实现单个 DID 读取 (多DID处理原理相同,可循环)
if (request.size() == 3) {
uint16_t did = (static_cast(request[1]) << 8) | request[2];
const auto* data = storage.getData(did);
if (data == nullptr) {
// DID 不支持 -> NRC 0x31 (请求超出范围)
return {0x7F, 0x22, 0x31};
}
// 构造肯定响应: 0x62 + DID(2B) + data
std::vector response;
response.reserve(3 + data->size());
response.push_back(0x62);
response.push_back(static_cast((did >> 8) & 0xFF));
response.push_back(static_cast(did & 0xFF));
response.insert(response.end(), data->begin(), data->end());
return response;
}
else {
// 请求报文长度 >3 意味着多个 DID,本例简化处理,返回 NRC 0x14 (数据太长)
// 实际产品应解析多个 DID 并按顺序拼接数据
return {0x7F, 0x22, 0x14};
}
}

// 辅助打印函数
void printHex(const std::vector& data, const std::string& desc) {
std::cout << desc << " [";
for (size_t i = 0; i < data.size(); ++i) {
std::cout << std::hex << std::uppercase << static_cast(data[i]);
if (i != data.size() - 1) std::cout << " ";
}
std::cout << std::dec << "]" << std::endl;
}

int main() {
// 初始化 ECU 数据存储区
DidStorage ecuStorage;

// 测试场景1: 有效单个 DID (0xF18C)
std::vector request1 = {0x22, 0xF1, 0x8C};
auto response1 = handleReadDataByIdentifier(request1, ecuStorage);
printHex(response1, "Request: 22 F1 8C -> Response");

// 测试场景2: 有效单个 DID (0x1000 里程)
std::vector request2 = {0x22, 0x10, 0x00};
auto response2 = handleReadDataByIdentifier(request2, ecuStorage);
printHex(response2, "Request: 22 10 00 -> Response");

// 测试场景3: 不支持的 DID (0x9999)
std::vector request3 = {0x22, 0x99, 0x99};
auto response3 = handleReadDataByIdentifier(request3, ecuStorage);
printHex(response3, "Request: 22 99 99 -> Response");

// 测试场景4: 格式错误 (长度不足)
std::vector request4 = {0x22, 0xF1};
auto response4 = handleReadDataByIdentifier(request4, ecuStorage);
printHex(response4, "Request: 22 F1 (too short) -> Response");

return 0;
}
4.3 代码运行结果

Request: 22 F1 8C -> Response [62 F1 8C 53 4E 30 30 31 32 33 34]
Request: 22 10 00 -> Response [62 10 00 34 12 0 0]
Request: 22 99 99 -> Response [7F 22 31]
Request: 22 F1 (too short) -> Response [7F 22 13]
4.4 代码说明
  1. DidStorage 类:模拟 ECU 内部的非易失/易失数据字典,使用std::map > 存储。

  2. handleReadDataByIdentifier:

  • 首先校验请求长度及 SID。

  • 提取第一个 DID(本例为简化,只处理单 DID)。

  • 调用storage.getData查询数据。

  • 若找到则构造0x62 + DID + Data的肯定响应。

  • 若找不到返回 NRC 0x31。

多 DID 支持:标准 UDS 允许一次请求多个 DID,响应应顺序返回每个 DID 及其数据。本示例为简洁未实现,但可以扩展:循环解析每个 DID,依次查表,将结果拼接进响应;若任何一个 DID 无效,则中止并返回 NRC 0x31。

传输层:实际车辆中,UDS 报文可能大于 8 字节(如 VIN 的 17 字节),需要底层协议如 ISO 15765-2 (CAN-TP) 进行拆包。本例假设请求/响应长度均 ≤ 8 字节,聚焦服务逻辑。

5. 实际开发注意事项

  • 安全性:某些 DID 读取需要先通过安全访问(0x27 服务),否则应返回 NRC 0x22。

  • 动态数据:里程、电压等 DID 应在读取时实时从硬件获取,而不是返回静态缓存值。

  • 字节序:多字节数值(如 int32)在 CAN 总线通常采用大端(Motorola)或小端(Intel)。需与 OEM 保持一致,本示例中里程按小端存储。

  • 扩展多 DID:请求22 F1 8C F1 90,响应应为62 F1 8C F1 90 。

  • NRC 优先级:若同时存在多个错误(如长度错误且 DID 不支持),应优先返回格式类 NRC(0x13)。

6. 总结

UDS 0x22 服务是诊断交互中最基础也最实用的服务之一,让外部工具轻松读取出 ECU 内部的各种标识数据。通过合理设计 DID 表,可以覆盖从静态标定信息到实时物理量的全部读取需求。开发者实现时需注意:

  • 正确解析 DID

  • 处理不支持 DID 情况

  • 考虑数据长度和传输协议

  • 必要时加入安全访问保护敏感数据

以上代码示例可以直接集成到 ECU 诊断栈的对应服务回调中,作为开发参考。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

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-06-25 22:12:10
昔日国乒名将陈龙灿发声!张本宇留日另有原因,当年选择不简单

昔日国乒名将陈龙灿发声!张本宇留日另有原因,当年选择不简单

潋滟晴方DAY
2026-08-13 13:06:45
反转!中国男篮被爆出内幕,郭士强这次可能被冤枉,真错怪他了

反转!中国男篮被爆出内幕,郭士强这次可能被冤枉,真错怪他了

宗介说体育
2026-09-27 07:59:37
贷款中介,这几天集体变安静了

贷款中介,这几天集体变安静了

21世纪经济报道
2026-09-27 22:07:57
王曼昱头号贵人,不是刘国梁也不是王励勤,竟是已离开国家队的他

王曼昱头号贵人,不是刘国梁也不是王励勤,竟是已离开国家队的他

完善法
2026-09-09 04:59:50
国产显卡撞上性能墙!砺算LX 7G100号称对标RTX 4060:实测勉强赢过AMD九年前的RX 580

国产显卡撞上性能墙!砺算LX 7G100号称对标RTX 4060:实测勉强赢过AMD九年前的RX 580

快科技
2026-09-26 14:11:07
太瘆人了!日本男子潜入单身女子家100多次,打扫卫生、补充饮料,甚至偷走内衣后再买新的换回去。

太瘆人了!日本男子潜入单身女子家100多次,打扫卫生、补充饮料,甚至偷走内衣后再买新的换回去。

日本物语
2026-09-27 20:34:09
一座1亿瓦的核反应堆,只有洗衣机大小,运行63年却没发一度电,专门生产一些造出来就快速消失的东西,已帮助了数亿生命

一座1亿瓦的核反应堆,只有洗衣机大小,运行63年却没发一度电,专门生产一些造出来就快速消失的东西,已帮助了数亿生命

徐德文科学频道
2026-09-27 14:20:48
刘欢离世爆出真实家底,不拍戏不代言,不靠综艺为何坐拥上亿身家

刘欢离世爆出真实家底,不拍戏不代言,不靠综艺为何坐拥上亿身家

东方不败然多多
2026-09-27 16:17:04
刘欢临终细节:妻子卢璐和女儿刘一丝守在床边,母女俩哭到站不住

刘欢临终细节:妻子卢璐和女儿刘一丝守在床边,母女俩哭到站不住

情感大头说说
2026-09-28 05:34:17
刚拿冠军就退役,当晚直接打包行李走人,这姑娘的操作把全网看傻

刚拿冠军就退役,当晚直接打包行李走人,这姑娘的操作把全网看傻

静若梨花
2026-08-29 10:42:55
嫁错人太可怕!被前夫公开骂“性欲太强”的她,活成张柏芝对照组

嫁错人太可怕!被前夫公开骂“性欲太强”的她,活成张柏芝对照组

阿讯说天下
2026-08-02 04:31:47
19岁松岛辉空,正式公布退役计划

19岁松岛辉空,正式公布退役计划

乒乓乐园
2026-08-13 12:18:37
索尼低价区试水?《战神劳菲》能成为PS首个试金石吗

索尼低价区试水?《战神劳菲》能成为PS首个试金石吗

游民星空
2026-09-27 19:13:07
港媒:大陆高铁已被“粪便淹没”!再不解决后果严重,真的假的?

港媒:大陆高铁已被“粪便淹没”!再不解决后果严重,真的假的?

铭记历史呀
2026-09-02 02:21:33
电影院的至暗时刻:174亿票房、场均不到6人、五大公司全亏

电影院的至暗时刻:174亿票房、场均不到6人、五大公司全亏

草莓解说体育
2026-09-27 17:07:15
人活多久,看起夜就知道?寿命短的人,起夜一般有这3个特征

人活多久,看起夜就知道?寿命短的人,起夜一般有这3个特征

芹姐说生活
2026-09-10 23:50:29
20岁德国天才后卫闪耀德甲,开价3500万欧,良心价,皇马情有独钟

20岁德国天才后卫闪耀德甲,开价3500万欧,良心价,皇马情有独钟

零度眼看球
2026-09-28 07:36:21
日本人怒斥高市,非要硬刚中国,这下全世界都知道敌国条款了

日本人怒斥高市,非要硬刚中国,这下全世界都知道敌国条款了

爱看剧的阿峰
2026-09-27 13:15:55
人大代表建议机关事业单位双休调整为“大周休3天,小周休2天”

人大代表建议机关事业单位双休调整为“大周休3天,小周休2天”

职场资深秘书
2026-09-27 19:40:23
2026-09-28 07:52:49
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
1015文章数 348关注度
往期回顾 全部

科技要闻

星舰第14飞,为什么准备绕地球六圈?

头条要闻

小伙汽车电瓶被偷刚报完案车又被砸 强忍蚊虫蹲守一宿

头条要闻

小伙汽车电瓶被偷刚报完案车又被砸 强忍蚊虫蹲守一宿

体育要闻

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

娱乐要闻

刘欢去世后谣言四起,韩磊被翻旧账

财经要闻

“为了看短剧,我妈两年花了22万 ”

汽车要闻

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

态度原创

健康
旅游
艺术
家居
本地

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

旅游要闻

打开草原天路的四种方式

艺术要闻

致敬,刘欢硬笔书法欣赏

家居要闻

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

本地新闻

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

无障碍浏览 进入关怀版