UDS诊断服务-22服务
一、22 服务到底是什么三句话讲完22 服务ReadDataByIdentifier做的事情用三句话就能概括你告诉 ECU 一个编号DIDECU 把那个编号对应的数据还给你。请求 22 DID。响应 62 DID 数据。没了。没有子功能字节没有保留字段没有DID 数量参数没有校验位。如果你看到的任何资料给 22 服务加了第四样东西——不管是可选参数、DID 数量、保留字节还是填充零——那份资料在编。二、请求格式只有 3 个字节单 DID正确的单 DID 请求22 DID_H DID_L读发动机转速假设 OEM 定义的 DID 0x010022 01 003 个字节。句号。不是 8 个字节。不需要后面补 5 个零。CAN 单帧能装8 字节不代表你必须填8 字节。报文长度就是有效字节数多一个都是格式错误。原文的错误原文写0x22 0x01 0x00 0x00 0x00 0x00 0x00 0x00后面 5 个零是什么原文说读取单个 DID 时填 0x00。标准里不存在这个规则。这 5 个零发出去严格的 ECU 实现会回你一个7F 22 13incorrectMessageLengthOrInvalidFormat。宽松的 ECU 可能忽略它们但你不能依赖ECU 脾气好。三、多 DID 读取直接拼接没有数量字节这是原文最大的格式错误。原文的多 DID 请求错22 02 01 00 01 01 00 00 ↑ ↑ │ └── 原文说这是DID 数量 2 └───── 原文说后面跟 DID 列表这个格式是虚构的。标准 22 服务没有DID 数量字段。正确的多 DID 请求直接拼接 DID一个接一个22 01 00 01 01 ───── ───── DID1 DID2读 3 个 DID继续拼22 01 00 01 01 01 02 ───── ───── ───── DID1 DID2 DID3没有数量字节。没有分隔符。没有终止符。ECU 通过报文总长度推断你请求了几个 DID(总长度 - 1) / 2。多 DID 响应响应也是直接拼接每个 DID 后面跟它的数据62 01 00 07 08 01 01 46 ───── ──── ───── ── DID1 数据1 DID2 数据262 肯定响应01 00 DID1转速07 08 DID1 的数据0x0708 1800rpm01 01 DID2水温46 DID2 的数据0x46 70℃注意响应里每个 DID 都会回显。不是只回数据不回 DID。这样诊断仪才能确认这段数据对应哪个 DID。四、响应格式没有保留字节没有填充单 DID 响应62 DID_H DID_L Data...读转速DID0x0100数据 2 字节62 01 00 07 085 个字节。结束。没有后面的00 00 00。读 VINDID0xF190数据 17 字节 ASCII请求22 F1 90 3 字节 响应62 F1 90 57 42 31 20 31 32 33 44 45 46 37 38 39 41 42 43 ───────────────────────────────────────────────────── 17 字节 ASCII WB1 123DEF789ABC20 字节响应。超过 CAN 单帧 8 字节限制传输层ISO 15765-2会自动用首帧 连续帧传输。但应用层报文就是这 20 字节没有填充没有截断。五、DID哪些是标准的哪些是 OEM 编的这是很多人搞混的地方。ISO 14229-1 标准定义的 DID部分DID含义长度备注0xF186Active Diagnostic Session1 字节当前会话编号0xF187Part Number可变ECU 零件号0xF188Software Version可变软件版本0xF189Hardware Version可变硬件版本0xF190VIN17 字节车辆识别码0xF191Vehicle Manufacturer ECU Software Number可变0xF193System Supplier Identifier可变OEM 自定义 DID举例非标准DID含义备注0x0100发动机转速某 OEM 定义换一个品牌可能是 0xF2000x0101水温同上0x0200故障灯状态同上关键认知标准只定义了 0xF1xx 范围内的一小撮 DID0x0100 转速、0x0200 故障灯——全是 OEM 自定义不同 OEM、不同 ECU 供应商DID 编号可以完全不同永远查诊断规范CDD/ODX不要记 DID 编号。DID 的访问权限原文说VIN 需要安全验证才能读——多数 OEM 不是这样的。读 VIN0xF190通常在默认会话就能读不需要安全访问。VIN 是车辆标识售后、年检都要读写 VIN2E F190这才需要编程会话 安全验证而且通常只允许写一次读实时数据转速、水温默认会话无安全要求读标定参数可能需要扩展会话是否需要安全验证取决于 OEM。具体权限由 OEM 在诊断规范中定义。标准不强制。六、NRC别望文生义原文的 NRC 表5 条里错了 4 条。原文的错误原文 NRC原文说法问题0x11子功能不支持不支持多 DID 读取22 服务没有子功能字节。0x11 serviceNotSupported整个服务不支持0x22请求参数不正确DID 无效0x22 conditionsNotCorrect前提条件不满足。DID 无效应报0x310x85当前状态不允许读取0x85 不是标准 NRC。标准里没有这个码0x78资源暂时不可用0x78 requestCorrectlyReceived-ResponsePending收到了等一下正确的 NRC 速查NRC标准名称什么时候会出现你该怎么做0x13incorrectMessageLengthOrInvalidFormat报文长度不对比如多塞了零检查报文长度0x22conditionsNotCorrectECU 当前状态不允许读极少见于 22检查前提条件0x31requestOutOfRangeDID 不存在、不支持读取查规范确认 DID 合法0x33securityAccessDenied需要安全验证但没做先做 27 服务0x7FserviceNotSupportedInActiveSession当前会话不允许 22切会话0x78requestCorrectlyReceived-ResponsePending在处理等一下别重发等最终响应22 服务最常遇到的 NRC 是 0x31DID 不存在和0x7F会话不对。七、完整实操读一个转速从头到尾不写步骤一二三了。直接上对话。场景台架上你想知道发动机现在多少转。你查规范转速的 DID 是 0x01002 字节大端序单位 rpm换算系数 1:1。默认会话可读无需安全验证。你发22 01 00ECU 回62 01 00 07 08你解析62→ 22 的肯定响应01 00→ DID 0x0100确认是转速07 08→ 数据大端序0x0708 1800结论发动机当前 1800 rpm。你等等我不确定是不是 1800。万一字节序反了呢你验证踩一脚油门再发一次22 01 00。如果数据变大比如变成09 60 2400说明解析方向对了。如果变小或乱跳检查字节序。场景 2你想同时读转速和水温。你发22 01 00 01 01ECU 回62 01 00 07 08 01 01 46你解析片段含义62肯定响应01 00DID1 转速07 08数据1 1800 rpm01 01DID2 水温46数据2 70℃注意响应里每个 DID 都回显了。你不需要按顺序猜哪段数据对应哪个 DID——ECU 告诉你了。八、数据解析三个真正会坑你的地方坑 1字节序多数汽车 ECU 用大端序Big-Endian高位字节在前。数据07 08 大端0x0708 1800 ✓ 小端0x0807 2055 ✗但多数不等于全部。有些 ECU尤其是某些日系供应商用小端序。查规范确认。坑 2换算系数和偏移不是所有 DID 都是原始值 物理量。常见的坑DID 定义原始值实际值转速系数 1:10x07081800 rpm水温偏移 -400x46 7070 - 40 30℃车速系数 0.10x0064 100100 × 0.1 10.0 km/h电压系数 0.010x0578 14001400 × 0.01 14.00 V不查规范直接读原始值你会把 30℃ 的水温当成 70℃把 10 km/h 当成 100 km/h。坑 3有符号 vs 无符号数据FF 无符号255 有符号-1温度、扭矩、角度等物理量经常是有符号的。查规范确认。九、传输层CAN 和 DoIP 对 22 有影响吗应用层格式零影响。22 01 00在 CAN 上是这 3 个字节在 DoIP 上还是这 3 个字节。响应62 01 00 07 08在哪儿都是 5 个字节。传输层差异只影响怎么搬运CANISO 15765-2DoIPISO 13400短响应≤ 8 字节单帧搞定TCP 一个报文搞定长响应如 VIN 20 字节首帧 连续帧TCP 自动处理应用层无感多 DID 请求受 8 字节限制一次大概拼 2~3 个短 DID一次可以拼更多 DID注意多 DID 读取效率的差异是传输层的不是 22 服务本身有CAN 版和以太网版。原文说以太网单帧可读取 10 个 DID——技术上 DoIP 确实允许更大的报文但 22 服务的格式不变只是能塞更多 DID 进去。不存在以太网专用格式。标准编号老生常谈标准号内容ISO 14229-1应用层22 服务定义在这ISO 14229-2会话层ISO 14229-3UDS on CANISO 14229-5UDS on IPISO 13400DoIPISO 15765-2CAN 传输层原文把CAN 总线标注为 ISO 14229-2、以太网标注为 ISO 14229-3——全错。十、22 服务在整个诊断流程里的位置22 不是孤立存在的。它和其他服务配合19 服务读故障码→ 发现 P0115水温传感器故障 ↓ 22 服务读水温 DID→ 看看水温到底报了多少 ↓ 2F 服务模拟水温信号→ 排除传感器硬件问题 ↓ 2E 服务写标定参数→ 如果需要调整阈值 ↓ 14 服务清除故障码→ 修完了清码22 在这个链条里是观察窗口——你不控制什么不修改什么只是看一眼。所以它的权限要求通常最低多数 DID 在默认会话就能读格式也最简单。十一、速查卡┌──────────────────────────────────────────────────────┐ │ 22 服务ReadDataByIdentifier速查 │ │ │ │ 请求22 DID_H DID_L │ │ 多DID22 DID1_H DID1_L DID2_H DID2_L ... │ │ │ │ 响应62 DID_H DID_L Data... │ │ 多DID响应62 DID1Data1 DID2Data2 ... │ │ │ │ 否定7F 22 NRC │ │ │ │ ✓ 没有子功能字节 │ │ ✓ 没有DID 数量字段 │ │ ✓ 没有保留字节 / 填充零 │ │ ✓ 响应里每个 DID 都回显 │ │ ✓ CAN 和 DoIP 格式完全一样 │ │ │ │ 高频 NRC │ │ 0x31 DID 不存在 │ │ 0x7F 会话不对 │ │ 0x33 没解锁 │ │ 0x13 报文长度不对你是不是多塞了零 │ │ 0x78 等一下别重发 │ │ │ │ 解析三查字节序 → 换算系数/偏移 → 有符号/无符号 │ └──────────────────────────────────────────────────────┘十二、最后说一句22 服务是 UDS 里最简单的服务。没有子功能没有控制模式没有掩码没有例程参数。请求 3 个字节响应 DID 数据。它之所以被写错不是因为复杂而是因为太简单了简单到写文章的人觉得就这于是给它加戏——加保留字节、加DID 数量、加可选校验位。别加。标准就这么多。你下次看到22 01 00 00 00 00 00 00 00直接把后面 5 个零删了。ECU 会感谢你的。评论区聊聊你第一次用 22 服务读数据时踩的是什么坑字节序反了换算系数没查还是 DID 编号记错了