3、UDS服务分类:强制服务与可选服务、功能寻址与物理寻址、服务ID(SID)结构

各位工程师朋友,咱们今天聊点实在的。UDS协议里服务那么多,到底哪些是必须实现的?哪些是看心情加的?还有那个寻址方式,物理寻址和功能寻址到底怎么用?别急,我一个一个给你掰扯清楚。

3.1 强制服务与可选服务:哪些是硬骨头?

UDS协议里定义了26个服务(ISO 14229-1),但并不是所有服务都得实现。我个人习惯把服务分成三类:

  • 强制服务(Mandatory):必须实现,没得商量
  • 条件服务(Conditional):如果支持某功能,就必须实现
  • 可选服务(Optional):看需求,想加就加

嗯,这里要注意:强制服务其实只有两个——诊断会话控制(0x10)安全访问(0x27)。为什么?你想想看,没有会话控制,ECU都不知道该用哪种诊断模式;没有安全访问,谁都能改你的标定数据,那不乱套了?

强制服务清单:

  • 0x10 - 诊断会话控制(必须)
  • 0x27 - 安全访问(必须)

条件服务就多了。比如你支持了写入功能,那0x2E(写入数据标识符)就必须实现;你支持了例程控制,那0x31(例程控制)就得有。说白了,功能是成对出现的。

我在项目中遇到过一件事:有个供应商说他们实现了UDS,结果一测试,发现连0x22(读取数据标识符)都没做。你说这诊断工具连数据都读不了,还诊断个啥?所以啊,0x22和0x2E虽然名义上是可选,但实际项目中基本都会实现。

避坑指南:

我曾经见过一个项目,客户要求支持UDS,但只实现了强制服务。结果产线测试时发现无法读取VIN码,最后紧急补了0x22服务。所以建议你在项目初期就和客户确认好服务清单,别等测试了才发现缺胳膊少腿。

3.2 功能寻址与物理寻址:一对好兄弟

这两个概念,说白了就是「找谁说话」的问题。

  • 物理寻址(Physical Addressing):一对一,指定某个ECU
  • 功能寻址(Functional Addressing):一对多,喊一嗓子,所有ECU都响应

你想想看,在CAN总线上,每个ECU都有自己的物理地址(比如0x701)。你用物理寻址发请求,只有那个地址的ECU会响应。但功能寻址就不一样了,它用一个特殊的地址(比如0x7DF),所有支持该功能的ECU都会响应。

我记得有一次做网关测试,需要同时唤醒所有ECU。如果用物理寻址,得一个一个发请求,累死个人。用功能寻址,一条0x10 03(扩展诊断会话)发出去,所有ECU都醒了。这就是功能寻址的魅力。

注意:

功能寻址虽然方便,但有个坑:多个ECU同时响应,总线可能会冲突。所以功能寻址通常只用于「不需要响应」或「只有部分ECU响应」的场景。比如刷写时用功能寻址发预编程请求,但读取数据时还是老老实实用物理寻址。

实际项目中,我建议你这样用:

场景 推荐寻址方式 原因
读取单个ECU数据 物理寻址 避免总线冲突
广播唤醒所有ECU 功能寻址 效率高
刷写多个ECU 功能寻址(预编程) 一次性通知所有ECU
安全访问 物理寻址 需要一对一验证

3.3 服务ID(SID)结构:看懂这个,你就入门了

服务ID,就是UDS请求的第一个字节。比如0x22代表读取数据,0x2E代表写入数据。但你知道吗?SID的结构其实有规律可循。

ISO 14229把SID分成了几个大类:

  • 0x10-0x3E:诊断和通信管理类(会话控制、安全访问、Tester Present等)
  • 0x22-0x2E:数据读取和写入类(读数据、写数据、动态定义标识符等)
  • 0x31-0x3D:输入输出控制类(例程控制、IO控制等)
  • 0x34-0x37:上传下载类(请求下载、传输数据、请求退出传输等)

嗯,这里有个小技巧:响应ID = 请求ID + 0x40。比如你发了0x22请求,ECU的肯定响应就是0x62。这个规律对所有服务都适用,除了否定响应(0x7F)。

SID结构速记表:

请求SID范围:0x10 - 0x7E
肯定响应SID = 请求SID + 0x40
否定响应SID:0x7F(固定)

我曾经在测试时遇到一个奇怪的问题:发0x22请求,ECU返回0x62,但数据格式不对。查了半天,发现是SID解析错了。原来ECU把0x22当成了0x62的请求,直接跳过了响应处理。所以啊,SID的对应关系一定要搞清楚,别搞混了。

个人经验:

我习惯在测试脚本里写一个SID映射表,把请求SID和响应SID一一对应。这样调试时一眼就能看出问题。比如:

# 伪代码示例
sid_map = {
    0x10: 0x50,  # 诊断会话控制
    0x22: 0x62,  # 读取数据标识符
    0x2E: 0x6E,  # 写入数据标识符
    0x27: 0x67,  # 安全访问
    0x31: 0x71,  # 例程控制
}

最后说一句:UDS服务分类看似简单,但实际项目中很容易踩坑。强制服务别漏了,功能寻址别滥用,SID结构要记牢。做到这三点,你的UDS测试就成功了一半。