3、会话切换流程:非默认会话的进入与退出、会话超时处理、Tester Present机制
好,咱们接着聊会话切换。上一节讲了三种会话的基本概念,这一节咱们深入进去,看看实际开发中怎么切、怎么退、怎么保活。说白了,就是会话的“生命周期管理”。
我个人习惯把会话切换比作“进房间”。默认会话是客厅,谁都能待。编程会话是书房,得敲门才能进。扩展会话呢,是地下室的工作间,进去得拿钥匙。嗯,这个比喻你记着,后面好理解。
3.1 非默认会话的进入流程
进入非默认会话,核心就一条:发对诊断请求,收对响应。
举个例子,从默认会话切到编程会话:
请求: 10 02
响应: 50 02 00 32 01 F4
这里 10 02 里的 02 就是编程会话的SID。响应里的 50 02 表示成功,后面跟着的 00 32 01 F4 是P2和P2*的定时参数。
这里有个坑,我踩过。 响应里的定时参数不是随便填的。我曾经在一个项目里,把P2*设得太短,结果ECU在刷写过程中频繁超时,搞得测试同事以为ECU死机了。后来查了半天,才发现是定时参数没算对。
进入非默认会话的关键点:
- 请求必须带正确的子功能(02、03)
- ECU返回肯定响应后,会话才算切换成功
- 响应里的P2/P2*参数,是ECU告诉Tester的“我处理请求的最长时间”
3.2 非默认会话的退出流程
退出非默认会话,有两种方式:
- 主动退出: 发
10 01回到默认会话 - 被动退出: 超时或者收到
10 03切到扩展会话
你想想看,为什么要有主动退出?因为ECU的资源是有限的。编程会话里,ECU可能关闭了某些通信通道,或者占用了大量内存。你不主动退,ECU就一直处于“高功耗”状态。
我建议,在刷写完成后,一定要发 10 01 让ECU回到默认会话。这不仅是规范要求,也是对ECU的一种保护。
注意: 退出非默认会话时,ECU会清空当前会话下的安全状态。也就是说,如果你在编程会话里解锁了安全访问,退出后锁就自动挂上了。下次再进,得重新解锁。
3.3 会话超时处理
这是最容易出问题的地方。每个非默认会话都有一个超时计时器,叫S3。S3的时间值,就是ECU在响应里返回的P2*参数。
举个例子,ECU返回的P2*是 01 F4(500ms)。那么,如果Tester在500ms内没有发任何诊断请求,ECU就会认为会话超时,自动切回默认会话。
为什么会这样? 因为ECU要防止“死锁”。假设Tester突然掉电了,或者通信断了,ECU不能一直卡在非默认会话里。超时机制就是最后的保险。
我曾经在一个项目中,遇到一个奇怪的问题:刷写过程中,ECU总是莫名其妙地退出编程会话。查了很久,发现是Tester发送请求的间隔太长了,超过了S3时间。嗯,后来把Tester的发送间隔调短,问题就解决了。
避坑指南: 我曾经在调试时,把S3时间设成了10秒,想着这样Tester有足够时间处理。结果ECU在刷写过程中,因为其他任务阻塞,导致超时处理不及时,反而出了问题。后来我学乖了,S3时间一般设在2-5秒之间,既保证Tester有足够时间,又不会让ECU等太久。
3.4 Tester Present机制
Tester Present,说白了就是“心跳包”。它的SID是 3E,子功能是 00(请求响应)或 80(无响应)。
它的作用很简单:告诉ECU“我还活着,别切回默认会话”。
你想想看,如果Tester要执行一个长时间的操作,比如刷写一个大的软件包,可能需要几分钟。如果中间不发任何请求,ECU的S3超时计时器就会溢出,会话就断了。这时候,Tester Present就派上用场了。
请求: 3E 00
响应: 7E 00
或者,如果Tester不想让ECU回复,可以发:
请求: 3E 80
// ECU不回复任何响应
我个人习惯用 3E 00。 为什么呢?因为如果ECU没收到心跳包,或者ECU内部出问题了,Tester能通过响应超时及时发现。用 3E 80 虽然省了带宽,但出了问题你都不知道。
Tester Present的发送策略:
- 发送间隔必须小于S3时间的一半。比如S3是500ms,那心跳包至少每250ms发一次
- 不要发得太频繁,否则浪费总线带宽
- 建议在长时间操作(如刷写、例程控制)期间,定期发送
3.5 实际项目中的经验总结
好了,说了这么多,我总结几条实战经验:
| 场景 | 建议做法 | 常见问题 |
|---|---|---|
| 进入编程会话 | 先发 10 02,再发 27 01 解锁 |
顺序搞反,导致解锁失败 |
| 长时间刷写 | 每200ms发一次 3E 00 |
心跳间隔太长,会话超时 |
| 刷写完成 | 发 10 01 回到默认会话 |
忘记退出,ECU一直高功耗 |
| 调试阶段 | 把S3时间设长一点(比如5秒) | 设太短,调试时频繁断连 |
嗯,会话切换这块,说白了就是“进、出、保活”三个动作。你只要把这三个动作的逻辑理清楚,再配合好定时参数,基本不会出大问题。
我记得有一次,一个新同事问我:“为什么我进了编程会话,发刷写请求ECU不理我?” 我一看,他进了会话没发Tester Present,ECU早就超时切回默认会话了。他还在那傻等呢。所以,记住:进了非默认会话,别忘了“保活”。