第1章:UDS服务分类与寻址机制

大家好,我是老张。做汽车嵌入式这行十几年了,UDS诊断协议几乎天天打交道。今天咱们聊聊UDS服务的基础框架——服务分类、寻址方式,还有SID和RSID的结构。

说实话,刚入行那会儿,我也被这些概念搞得晕头转向。后来踩过几次坑,才真正理解这些设计背后的逻辑。嗯,咱们一步步来。

1.1 强制服务与可选服务

UDS协议里,服务不是你想用哪个就用哪个。它分两类:强制服务可选服务

强制服务,说白了就是ECU必须支持的。你想想看,如果连最基本的诊断会话控制都不支持,那这ECU压根没法做诊断。ISO 14229里明确规定了哪些是强制服务。

我列个表,大家看得更清楚:

服务类别 服务ID (SID) 服务名称 强制/可选
诊断和通信管理 0x10 诊断会话控制 强制
诊断和通信管理 0x11 ECU复位 强制
诊断和通信管理 0x27 安全访问 可选
数据传输 0x22 读取数据标识符 强制
数据传输 0x2E 写入数据标识符 可选
存储数据传输 0x14 清除诊断信息 强制
存储数据传输 0x19 读取故障码信息 强制

我个人习惯,在项目初期就会把强制服务列表拉出来,挨个确认ECU是否支持。有一次项目赶进度,有个同事漏了0x11(ECU复位)的实现,结果在整车测试时死活过不了。嗯,这个坑我记忆犹新。

重要提醒:强制服务是UDS合规性的底线。如果你的ECU声称支持UDS,那强制服务一个都不能少。

可选服务呢?比如0x27安全访问、0x2E写入数据标识符。这些看具体需求。但要注意,如果你实现了可选服务,那它的行为必须完全符合协议规范,不能自己瞎改。

1.2 功能寻址与物理寻址

这是UDS里一个非常关键的概念。我刚开始做诊断时,就搞混过这两个寻址方式,结果把整个总线上的ECU都复位了...那场面,尴尬得很。

物理寻址:一对一的通信。一个诊断请求只发给一个特定的ECU。每个ECU有自己唯一的物理地址。

功能寻址:一对多的通信。一个诊断请求可以发给一组ECU,甚至所有ECU。功能地址是广播式的。

举个例子:

  • 你想读取发动机ECU的故障码,用物理寻址,只发给发动机ECU。
  • 你想让所有ECU都进入扩展诊断会话,用功能寻址,一条消息搞定所有。

为什么要有这两种方式?你想想看,在整车生产线上,需要同时给所有ECU刷写软件。如果用物理寻址,得一个一个来,效率太低。功能寻址一条广播就搞定了。

我的经验:功能寻址虽然方便,但风险也大。我曾经在调试时不小心用功能寻址发了ECU复位指令,结果整个台架上的ECU全复位了,日志全丢了。从那以后,我写测试脚本时,功能寻址的指令都会加个确认弹窗。

在CAN总线上,物理寻址和功能寻址是通过CAN ID来区分的。一般来说:

  • 物理请求ID:0x7E0(诊断仪到ECU),0x7E8(ECU响应)
  • 功能请求ID:0x7DF(诊断仪到所有ECU)

当然,具体ID分配要看整车厂的定义,但原理是一样的。

1.3 服务ID(SID)与响应ID(RSID)结构

每个UDS服务都有自己唯一的ID,叫SID(Service ID)。比如0x10是诊断会话控制,0x22是读取数据标识符。

那响应ID呢?RSID(Response Service ID) = SID + 0x40。这是协议规定的。

举个例子:

  • 请求:0x22 0xF1 0x90(读取VIN码)
  • 响应:0x62 0xF1 0x90 0x31 0x32 0x33...(0x62 = 0x22 + 0x40)

为什么这么设计?说白了,就是让接收方能一眼区分这是请求还是响应。你收到一个报文,看第一个字节:

  • 如果小于0x40,那就是请求
  • 如果大于等于0x40,那就是响应

这个设计很巧妙,对吧?

注意:响应还有两种:肯定响应和否定响应。肯定响应的RSID = SID + 0x40。否定响应的第一个字节是0x7F,后面跟着SID和错误码。这个后面章节会详细讲。

我给大家看个实际报文例子:

// 诊断请求:读取VIN码
发送:22 F1 90
// 肯定响应:VIN码为"LSVA12345..."
接收:62 F1 90 4C 53 56 41 31 32 33 34 35 2E 2E 2E

// 否定响应:不支持该服务
接收:7F 22 11  // 0x11 = 服务不支持

嗯,这里要注意,否定响应的结构是固定的:0x7F + SID + NRC(否定响应码)。这个NRC后面会专门讲,常见的比如0x11(服务不支持)、0x12(子功能不支持)、0x13(报文长度错误)等等。

1.4 小结

今天咱们聊了三个核心概念:

  1. 服务分类:强制服务必须实现,可选服务按需实现
  2. 寻址方式:物理寻址一对一,功能寻址一对多,各有各的用途
  3. SID/RSID结构:RSID = SID + 0x40,否定响应以0x7F开头

这些是UDS诊断的基础中的基础。我个人觉得,理解这些概念比背协议更重要。因为实际项目中,你遇到的不会是教科书式的完美场景,而是各种边界情况和异常处理。

下一章,咱们聊聊诊断会话管理,这可是UDS的入口。没有会话,啥服务都跑不起来。

课后思考:如果你设计一个诊断协议,你会怎么区分请求和响应?为什么UDS选择用SID+0x40的方式,而不是用单独的标志位?

公众号:蓝海资料掘金营,微信deep3321