第三章 UDS服务分类:强制服务与可选服务、功能寻址与物理寻址、诊断会话控制
好,咱们继续往下走。第三章的内容,说白了就是UDS协议里最核心的骨架。你搞懂了这一章,后面看什么服务都不会觉得乱。我个人习惯把这一章叫做“UDS的交通规则”——什么车能上路,走哪条道,什么时候能跑,全在这儿了。
3.1 强制服务与可选服务:哪些是必须有的?
UDS协议里定义了一大堆服务,但并不是所有服务ECU都得支持。ISO 14229-1里把服务分成了两类:强制服务和可选服务。
强制服务,就是ECU必须实现的。你不实现,就不符合UDS规范。我在项目中遇到过一家供应商,他们做的BCM(车身控制器)居然不支持TesterPresent服务,结果产线刷写时总是超时断开。嗯,这就是典型的“该有的没有”。
强制服务其实不多,我列个表给你看:
| 服务ID | 服务名称 | 说明 |
|---|---|---|
| 0x10 | DiagnosticSessionControl | 诊断会话控制,必须支持 |
| 0x11 | ECUReset | ECU复位,必须支持 |
| 0x27 | SecurityAccess | 安全访问,必须支持(如果ECU有安全锁) |
| 0x28 | CommunicationControl | 通信控制,必须支持 |
| 0x3E | TesterPresent | 测试仪在线,必须支持 |
| 0x83 | AccessTimingParameter | 访问时序参数,必须支持 |
| 0x84 | SecuredDataTransmission | 安全数据传输,有条件必须 |
| 0x85 | ControlDTCSetting | 控制DTC设置,必须支持 |
| 0x86 | ResponseOnEvent | 事件响应,必须支持 |
| 0x87 | LinkControl | 链路控制,必须支持 |
重点来了:强制服务不是说你所有会话都得支持。比如0x10服务,你至少得支持默认会话(DefaultSession)和扩展会话(ExtendedSession)。编程会话(ProgrammingSession)可以没有,但默认会话必须有。
可选服务就多了去了。像0x22(ReadDataByIdentifier)、0x2E(WriteDataByIdentifier)、0x19(ReadDTCInformation)这些,都是可选的。但话说回来,虽然叫“可选”,实际项目中基本都会用。你想想看,一个ECU连DTC都读不了,那还诊断个啥?
我个人建议:做ECU开发时,先把强制服务列个清单,一条一条过。确保每个强制服务都实现了,再去做可选服务。我曾经吃过这个亏——先做了0x22和0x2E,结果发现0x3E没做,产线那边死活连不上。后来加班补的,教训深刻。
3.2 功能寻址与物理寻址:你是在跟谁说话?
这个知识点,很多新手容易搞混。我换个角度给你讲——你想想看,你在诊断仪上发一条指令,这条指令是发给一个ECU,还是发给一群ECU?
物理寻址,就是点对点通信。诊断仪发一条请求,只有一个ECU会响应。CAN总线上,物理寻址的CAN ID通常是唯一的。比如你发0x7DF,那是功能寻址;你发0x7E0,那就是物理寻址(假设ECU的物理请求ID是0x7E0)。
功能寻址,就是一对多通信。诊断仪发一条请求,总线上所有支持该功能的ECU都会响应。功能寻址的CAN ID通常是0x7DF(11位ID)或0x18DB33F1(29位ID)。
为什么要区分这两种?我给你讲个真实场景:
产线刷写时,需要同时给多个ECU发送编程会话请求。如果用物理寻址,你得一个一个发,效率极低。用功能寻址,一条0x10 02(请求编程会话)发出去,所有ECU同时响应,速度飞快。
但功能寻址也有坑。我记得有一次,我在测试台上发了一条功能寻址的0x11 01(硬复位),结果整个台架上的ECU全复位了。嗯,那场面,所有灯全灭,然后慢慢亮起来。从那以后,我发复位指令时都会再三确认是物理寻址还是功能寻址。
避坑指南:功能寻址的响应处理要特别小心。如果多个ECU同时响应,CAN总线可能会发生冲突。所以UDS规定:功能寻址的请求,ECU可以不应答(抑制正响应位SBS=1)。如果你需要所有ECU都应答,那就得做好冲突处理的准备。
我一般这样用:
- 物理寻址:用于读写数据、执行例程、刷写单个ECU
- 功能寻址:用于广播会话切换、全局复位、产线批量操作
你想想看,如果每次刷写都要一个一个ECU去切会话,那产线得慢成什么样?所以功能寻址在产线端用得特别多。
3.3 诊断会话控制:ECU的三种工作模式
诊断会话控制(0x10服务),是UDS里最基础的服务之一。它定义了ECU在不同诊断场景下的工作模式。
ISO 14229-1定义了三种标准会话:
| 会话ID | 会话名称 | 子功能 | 典型用途 |
|---|---|---|---|
| 0x01 | DefaultSession | 默认会话 | 正常运行时,只支持少量诊断服务 |
| 0x02 | ProgrammingSession | 编程会话 | 刷写固件,支持0x34/0x36/0x37等 |
| 0x03 | ExtendedDiagnosticSession | 扩展诊断会话 | 读写数据、例程控制等高级诊断 |
为什么要有会话控制?说白了,就是安全考虑。ECU在正常运行时,不希望被随便读写数据。你想想看,如果谁都能在行车过程中改你的标定参数,那还得了?
所以UDS规定:默认会话下,只支持强制服务和少量安全服务。你想做更高级的操作,必须先切换到扩展会话或编程会话。
切换会话的流程很简单:
诊断仪发送:0x10 03(请求切换到扩展会话)
ECU响应: 0x50 03 00 32 01 F4(肯定响应,附带P2和P2*时间参数)
这里有个细节:ECU在响应0x10服务时,会返回两个时间参数——P2和P2*。P2是默认响应时间,P2*是扩展响应时间。这两个参数决定了诊断仪等待ECU响应的超时时间。
个人经验:我建议你在做ECU开发时,把P2时间设得宽松一点。比如默认会话设50ms,扩展会话设5000ms。为什么?因为扩展会话下可能要执行耗时操作(比如擦除Flash),时间太短容易超时。我曾经把P2*设成2000ms,结果刷写时总是超时重试,后来改成5000ms就好了。
会话切换还有一些规则:
- 从默认会话可以切换到任何会话
- 从扩展会话可以切换到默认会话或编程会话
- 从编程会话只能切换到默认会话(不能直接切到扩展会话)
- 切换会话时,ECU会重置一些状态(比如安全访问锁、DTC设置状态等)
嗯,这里要注意:会话切换时,ECU会清空安全访问的状态。也就是说,你切了会话,就得重新做安全解锁。这是安全设计,防止有人通过会话切换绕过安全验证。
最后说一个我踩过的坑:有一次我在做产线刷写工具,发现刷写过程中总是莫名其妙失败。查了半天,发现是TesterPresent(0x3E服务)没发。原来ECU在编程会话下有个会话超时时间(S3),如果超过S3时间没收到任何诊断请求,ECU会自动切回默认会话。而默认会话下不支持刷写服务,所以刷写就失败了。
从那以后,我写诊断工具时都会加一个定时器,每隔500ms发一次0x3E服务,保持会话活跃。这个习惯一直保留到现在。
好了,第三章的内容就这些。强制服务与可选服务让你知道ECU必须实现什么;功能寻址与物理寻址让你知道怎么跟ECU说话;诊断会话控制让你知道ECU在什么状态下能做什么事。这三块搞明白了,UDS的大门就算正式打开了。