3、会话控制服务(0x10):请求格式、肯定响应、否定响应、会话切换规则

好,咱们今天来聊聊UDS里最基础、也最常用的一个服务——0x10会话控制。说实话,这个服务看起来简单,但坑不少。我见过不少新手工程师,上来就调0x10,结果被否定响应搞得一头雾水。别急,咱们一步步拆开看。

3.1 请求格式:就三个字节的事儿

0x10服务的请求帧,结构非常清晰。说白了,就是告诉ECU:「嘿,我想切换到某个会话模式」。格式如下:

请求格式:
| 字节0 (SID) | 字节1 (子功能) |
| 0x10        | 会话类型       |

这里的子功能,就是你要切换的目标会话。UDS标准定义了三种默认会话:

子功能值 会话名称 说明
0x01 默认会话 (Default Session) 上电后的初始状态,功能受限
0x02 编程会话 (Programming Session) 用于刷写软件,权限较高
0x03 扩展会话 (Extended Session) 用于诊断、标定等,比默认会话权限高

嗯,这里要注意,有些厂商会自定义会话,比如0x40、0x60之类的。但咱们做通用诊断开发,先把这三个标准会话吃透就行。

我的小习惯: 在项目初期,我会先确认ECU支持哪些会话。直接发一个0x10 0x01,看它回什么。如果连默认会话都切不进去,那后面啥都别谈了。

3.2 肯定响应:ECU说「好的,我切换了」

如果ECU同意切换,它会回一个肯定响应。格式也很简单:

肯定响应格式:
| 字节0 (响应SID) | 字节1 (子功能) |
| 0x50            | 会话类型       |

注意,响应SID是请求SID + 0x40。所以0x10的请求,肯定响应就是0x50。子功能字段会原样返回,告诉你当前切到了哪个会话。

举个例子,你发 10 03 请求切到扩展会话,ECU回 50 03,就表示切换成功。这时候你就可以开始做其他诊断操作了,比如读写数据、执行例程等。

我记得有一次,客户反馈说ECU切不到扩展会话。我抓了总线一看,ECU明明回了 50 03,但客户说还是不行。后来发现,是客户的上位机没正确处理肯定响应,以为没收到确认。所以啊,有时候问题不在ECU,而在工具链上。

3.3 否定响应:ECU说「不行,我拒绝」

ECU不是什么时候都听你的。如果它拒绝切换,就会回一个否定响应。格式如下:

否定响应格式:
| 字节0 (NRC SID) | 字节1 (SID) | 字节2 (NRC码) |
| 0x7F            | 0x10        | 错误原因       |

常见的否定响应码(NRC)有这些:

NRC码 含义 常见场景
0x12 子功能不支持 你发了个ECU不认识的会话类型
0x22 条件不满足 比如正在刷写时,不允许切到其他会话
0x13 消息长度错误 请求帧多了一个字节或少了一个字节
0x7F 服务不支持 ECU压根不支持0x10服务(极少见)
避坑指南: 我曾经遇到过一个ECU,在编程会话里收到扩展会话的请求,直接回了0x22。当时我查了半天手册,才发现厂商规定:编程会话是「独占」的,不允许切到其他会话,除非先回到默认会话。所以,切换前一定要搞清楚当前会话的约束。

3.4 会话切换规则:不是你想切就能切

会话切换不是随心所欲的。UDS标准定义了一套规则,我总结成三点:

  1. 只能从当前会话切到目标会话,不能跨会话跳转。比如从默认会话可以直接切到扩展会话,但不能从默认会话直接切到编程会话?嗯,其实标准允许直接切,但很多ECU会限制。具体看厂商实现。
  2. 会话有超时机制。默认会话通常没有超时,但扩展会话和编程会话一般有超时时间(比如5秒)。如果超时内没有收到任何诊断请求,ECU会自动切回默认会话。这是为了安全考虑,防止诊断会话一直占用总线。
  3. 某些服务只能在特定会话下执行。比如刷写相关的服务(0x34、0x36等)只能在编程会话下用。你如果在默认会话下发0x34,ECU会直接回否定响应。

我个人习惯,在写测试脚本时,会先发一个0x10 0x01切到默认会话,再切到目标会话。这样能确保ECU处于一个已知的初始状态,避免因为上一个测试残留的会话状态导致问题。

核心要点: 会话切换的本质,是ECU在管理自己的「权限等级」。默认会话是普通用户,扩展会话是管理员,编程会话是超级管理员。你想想看,没有权限管理,ECU的安全怎么保障?

3.5 实战中的小技巧

最后,分享几个我在项目中积累的经验:

  • 先确认ECU支持的会话列表。可以通过0x10服务的否定响应来试探,或者直接读ECU的配置参数。
  • 注意会话超时。如果ECU在扩展会话下长时间没收到请求,它会自动切回默认会话。这时候你发其他服务,可能会收到0x7F或0x22。所以,建议在测试循环里定期发一个0x3E(Tester Present)来保持会话。
  • 不要假设所有ECU行为一致。不同厂商、不同型号的ECU,对会话切换的实现可能有细微差别。比如有的ECU允许从编程会话切到扩展会话,有的则不允许。最好的办法是看对应的诊断规范文档。

好了,关于0x10会话控制服务,咱们就聊到这儿。下一节,我会讲讲安全访问服务(0x27),那可是个更刺激的话题。到时候见!