4. 刷写流程设计:预编程-主编程-后编程三阶段、会话切换、DTC处理
刷写流程,说白了就是给域控“换脑子”的标准操作流程。我见过不少工程师,上来就怼数据,结果刷到一半域控“死”了,还得拆盒子用调试器救。嗯,这其实完全可以避免。
UDS 规范里把刷写拆成了三个阶段:预编程、主编程、后编程。每个阶段都有明确的任务,少一步都不行。今天我就把这三阶段的细节、会话怎么切、DTC 怎么处理,一次性讲清楚。
4.1 三阶段总览
先看整体流程。我习惯用一张图来记,你想想看,刷写就像做手术:术前准备、手术操作、术后恢复。
核心原则:预编程负责“清场”,主编程负责“换件”,后编程负责“验收”。任何一步出错,都要能回滚到安全状态。
4.2 预编程阶段:把环境打扫干净
预编程的目的只有一个:让域控进入可刷写的安静状态。我遇到过最坑的情况,就是刷写过程中网络管理报文还在乱飞,结果域控一边刷一边响应网络请求,直接超时失败。
4.2.1 会话切换:从默认到编程
第一步,把会话从 默认会话 (0x01) 切到 编程会话 (0x02)。注意,不是扩展会话 (0x03),是编程会话。
// 请求:10 02
// 响应:50 02 00 32 00 64
// 其中 00 32 = 50ms 是 P2_Server_max
// 00 64 = 100ms 是 P2*_Server_max
// 实际报文示例
Tx: 10 02
Rx: 50 02 00 32 00 64
我的经验:编程会话的 P2 时间通常比默认会话长。默认会话 P2 一般是 50ms,编程会话可以放宽到 500ms 甚至 1s。为什么?因为刷写时域控很忙,响应慢是正常的。我曾经在某个项目里把 P2 设成 200ms,结果域控在擦除 Flash 时超时了,后来改成 1s 就稳了。
4.2.2 禁用 DTC 存储
刷写过程中,域控会执行各种非常规操作。比如断电、复位、通信中断。这些操作在正常行驶时都是故障,但在刷写时是正常的。如果不关 DTC 存储,刷一次写能报几十个故障码。
| 步骤 | 服务 | 说明 |
|---|---|---|
| 1. 禁用 DTC 存储 | 85 02 | 告诉域控:接下来发生的异常不要存 DTC |
| 2. 停止非诊断通信 | 28 03 | 停止网络管理报文,避免总线干扰 |
| 3. 读取刷写条件 | 22 F1 00 | 检查电压、温度等是否满足刷写条件 |
| 4. 安全访问解锁 | 27 01/02 | 请求种子、发送密钥,解锁刷写权限 |
注意:85 服务禁用的是 DTC 的存储,不是 DTC 的检测。域控仍然会检测故障,只是不存。刷写完成后必须用 85 01 恢复存储功能。我曾经见过有人忘了恢复,结果客户跑了一个月才发现 DTC 一个都没存。
4.3 主编程阶段:核心操作
主编程阶段,说白了就是往 Flash 里写数据。但怎么写、写什么、写完怎么验证,这里面的门道不少。
4.3.1 数据写入流程
标准流程是:请求下载 (34) → 传输数据 (36) → 请求退出传输 (37)。每次传输的数据块大小由域控决定。
// 请求下载 - 告诉域控我要写数据了
// 34 00 44 00 00 00 10 00 00 00 00 00
// 参数:数据格式=00, 地址长度=4字节, 地址=0x00100000, 内存大小=4字节, 大小=0x00000000
// 传输数据 - 每次最多 4096 字节
// 36 01 [数据块]
// 请求退出传输
// 37
这里有个关键点:数据块大小。域控会在 34 服务的响应里告诉你它一次能收多少字节。
避坑指南:我曾经在某个项目里,域控返回的块大小是 1024 字节,但我们的刷写工具默认发 4096。结果域控每次收到数据都报错,刷写进度卡在 0%。后来查了三天才发现是块大小没对齐。所以,一定要解析 34 服务的响应,动态调整块大小。
4.3.2 完整性检查
数据写完后,必须做完整性检查。常用的方式有两种:
- CRC 校验:刷写工具计算整个文件的 CRC,写入后让域控自己算一遍,对比是否一致。
- 逐块校验:每写完一块数据,域控立即回读并校验。这种方式更安全,但速度慢。
我个人更推荐先写后验的方式。先快速写完所有数据,最后做一次整体 CRC 校验。这样既保证了速度,又保证了完整性。
4.3.3 编程验证与复位
校验通过后,执行 31 01 FF 00 服务,让域控做一次编程验证。这个服务会检查 Flash 里的数据是否完整、应用是否可启动。
验证通过后,发送 11 01 硬复位,让域控重启加载新程序。
4.4 后编程阶段:恢复与确认
后编程阶段,很多人觉得不重要,随便做做就行。其实不然。我见过刷写成功后,域控因为通信没恢复,导致整车网络瘫痪的案例。
4.4.1 恢复通信与 DTC 存储
复位后,域控会回到默认会话。这时候需要:
- 恢复通信:发送 28 01,让域控重新参与网络管理。
- 恢复 DTC 存储:发送 85 01,恢复故障码存储功能。
- 清除历史 DTC:发送 14 FF FF FF,把刷写过程中产生的临时故障码清掉。
我的习惯:清除 DTC 时,不要只清特定的 DTC,直接清所有 DTC (14 FF FF FF)。因为刷写过程中可能产生各种意想不到的故障码,一次性清干净最省事。当然,前提是你已经恢复了 DTC 存储功能。
4.4.2 检查应用状态
最后一步,检查域控是否正常运行。我通常用 22 F1 00 读取域控的编程状态,确认应用已经激活。
// 读取编程状态
Tx: 22 F1 00
Rx: 62 F1 00 01 // 01 表示编程成功,应用已激活
如果返回的是 02 或 03,说明编程失败或应用未激活。这时候需要进入故障处理流程,比如回滚到备份区。
4.5 会话切换的细节
会话切换看起来简单,就是发一条 10 服务。但实际项目中,我踩过不少坑。
| 会话 | ID | 用途 | 超时时间 |
|---|---|---|---|
| 默认会话 | 01 | 正常行驶时的会话 | 无超时 |
| 编程会话 | 02 | 刷写专用会话 | 通常 5s |
| 扩展会话 | 03 | 诊断、标定、调试 | 通常 5s |
注意:编程会话有超时机制。如果 5 秒内没有收到任何诊断请求,域控会自动切回默认会话。这意味着,如果你在刷写过程中停顿太久(比如等待用户确认),域控可能已经切回默认会话了。这时候再发 36 传输数据,域控会回复 NRC 0x22(条件错误)。
解决办法有两个:
- 发送 3E 80 保持会话:每 2-3 秒发一次,告诉域控“我还活着”。
- 调整超时时间:在预编程阶段,通过 10 02 的响应参数,把 P2 时间设长一些。
4.6 DTC 处理策略
DTC 处理是刷写流程里最容易出问题的环节。我总结了几条原则:
- 刷写前禁用存储:85 02 必须在所有操作之前执行。
- 刷写后恢复存储:85 01 必须在所有操作之后执行。
- 刷写后清除 DTC:14 FF FF FF 清除所有历史故障码。
- 不要清除正在发生的故障:如果域控当前有故障(比如电压低),清除 DTC 后它会立即重新报出。所以要先排除故障,再清 DTC。
我曾经踩过的坑:有一次刷写完成后,我忘了发 85 01 恢复 DTC 存储。结果客户反馈说车辆报“通信故障”,但读不出任何 DTC。查了两天,才发现 DTC 存储功能还关着。从那以后,我把恢复 DTC 存储写进了刷写脚本的强制步骤里,少一步就报错。
4.7 总结
刷写流程设计,说白了就是三个字:稳、准、狠。
- 稳:预编程把环境打扫干净,避免干扰。
- 准:主编程按部就班,数据块大小对齐,校验到位。
- 狠:后编程恢复彻底,不留隐患。
会话切换和 DTC 处理是细节中的细节。你想想看,一个 85 服务没恢复,可能导致整个售后诊断系统瘫痪。一个会话超时没处理,可能导致刷写失败需要拆盒子救。这些坑,我替你们踩过了,希望你们别再踩。