3. UDS协议核心

刷写流程,说白了就是ECU固件升级的完整操作规范。很多工程师刚接触UDS刷写时,总觉得不就是发几个34 36 37服务嘛,结果一上实车就出问题。我见过太多因为跳过预编程步骤,导致刷写后ECU锁死的案例。

UDS标准把刷写流程拆成三个阶段:预编程、主编程、后编程。每个阶段又包含若干步骤,加起来一共10个核心步骤。嗯,咱们一个一个来看。

核心要点:三个阶段缺一不可。预编程是准备工作,主编程是数据传输,后编程是收尾验证。跳过任何一步,都可能让ECU变砖。

UDS刷写三阶段十步骤流程图 UDS刷写三阶段十步骤流程图 阶段一:预编程 步骤1:诊断会话控制 (10 02) 步骤2:安全访问解锁 (27 03/04) 步骤3:通信控制 (28 03) 步骤4:DTC控制 (85 02) 阶段二:主编程 步骤5:请求下载 (34 00 44) 步骤6:数据传输 (36) 步骤7:请求退出传输 (37) 步骤8:检查编程依赖 (31 01 FF 00) 阶段三:后编程 步骤9:ECU复位 (11 01) 步骤10:重新连接验证 💡 提示:步骤8(检查编程依赖)常被忽略,但它是防止ECU刷死后无法启动的关键校验 步骤5-7需循环执行,每个数据块都要经过“请求下载→传输→退出”的完整流程

3.1 预编程阶段(步骤1-4)

预编程阶段,说白了就是让ECU进入可刷写的状态。ECU在正常运行时,有很多保护机制——比如禁止写入Flash、网络通信繁忙、DTC记录中。你得先把这些障碍清掉。

步骤1:诊断会话控制 (10 02)

发送 10 02 切换到编程会话。ECU收到后,会关闭一些非关键通信,释放资源。我遇到过一个问题:有些ECU从默认会话切到编程会话时,响应时间特别慢,超过500ms。后来发现是ECU内部在保存当前运行参数。嗯,这里建议超时设到1秒以上。

步骤2:安全访问解锁 (27 03/04)

刷写是高风险操作,ECU不会让随便谁都能写Flash。你得通过种子-密钥验证。发送 27 03 请求种子,ECU返回一串随机数;你用算法算出密钥,发 27 04 带密钥过去。

实战技巧:我个人习惯在安全访问失败后,等待至少100ms再重试。有些ECU有防暴力破解机制,连续失败3次会锁死30分钟。我曾经在测试时连续发请求,结果ECU直接罢工了半小时。

步骤3:通信控制 (28 03)

发送 28 03 关闭应用报文和网络管理报文。为什么?刷写时总线上一堆报文干扰,万一刷到一半网络管理报文要求休眠,那就麻烦了。关闭非诊断通信,让总线安静下来。

步骤4:DTC控制 (85 02)

发送 85 02 设置DTC存储为关闭状态。刷写过程中ECU会经历各种异常状态——电压波动、通信中断、内存操作繁忙。如果不关DTC记录,ECU会记一堆故障码,刷完还得清,麻烦。

警告:步骤3和步骤4的顺序不要搞反。先关通信,再关DTC。如果先关DTC再关通信,ECU在关闭通信的过程中可能产生新的DTC,而此时DTC记录还没关掉,就会把异常状态记下来。

3.2 主编程阶段(步骤5-8)

主编程阶段是真正的数据传输环节。这里有个关键概念:数据块。固件文件通常很大,几百KB甚至几MB,不能一次性发完。你得把固件切成小块,一块一块传。

步骤5:请求下载 (34 00 44)

发送 34 00 44 + 内存地址 + 数据长度。告诉ECU:我要往哪个地址写数据,写多少字节。ECU会返回一个最大数据块长度(MaxNumberOfBlockLength),告诉你每个数据块最多能传多少字节。

举个例子:

请求:34 00 44 00 10 00 00 00 10 00
      ↑  ↑  ↑  ↑     ↑        ↑
      34 00 44 地址高字节  数据长度

响应:74 00 44 00 10
      ↑  ↑  ↑  ↑
      74 00 44 最大块长度=16字节

步骤6:数据传输 (36)

发送 36 + 块序列号 + 数据。把固件数据按步骤5得到的最大块长度切分,一帧一帧发。注意:块序列号从01开始,每发一块加1。

关键点:步骤5和步骤6是循环执行的。每传完一个数据块,都要重新发一次34请求下载,再发36传数据。直到整个固件传完。

步骤7:请求退出传输 (37)

发送 37 结束当前数据块的传输。ECU收到后,会把刚才收到的数据写入Flash。注意:37服务只是结束当前块,不是结束整个刷写流程。下一个块还得从34开始。

步骤8:检查编程依赖 (31 01 FF 00)

这一步很多人会忽略。发送 31 01 FF 00 执行编程依赖检查。ECU会校验刚写入的固件完整性、版本兼容性、签名有效性。如果校验失败,ECU会返回NRC,告诉你刷写有问题。

我遇到过最坑的情况:固件刷完了,ECU也复位了,结果起不来。后来发现是刷写顺序错了——先刷了应用层,后刷了Bootloader,导致Bootloader覆盖了应用层的启动向量。嗯,从那以后我每次都在主编程最后加一步依赖检查。

3.3 后编程阶段(步骤9-10)

后编程阶段是收尾工作。固件写进去了,但ECU还在编程会话里,网络通信还关着,DTC记录也关着。你得让ECU恢复正常运行状态。

步骤9:ECU复位 (11 01)

发送 11 01 让ECU硬件复位。ECU重启后,会从新的固件启动。注意:复位后ECU会回到默认会话,之前设置的通信控制和DTC控制都会自动恢复。

经验之谈:复位后不要立即发诊断请求。ECU启动需要时间,Bootloader要初始化硬件、校验固件、跳转到应用。我一般等2-3秒再发连接请求。有些ECU启动慢,等5秒都正常。

步骤10:重新连接验证

ECU复位后,你需要重新建立诊断连接:

  1. 发送 10 01 进入默认会话
  2. 发送 22 F1 00 读取ECU的软件版本号,确认固件已更新
  3. 发送 19 02 0F 读取DTC,确认没有刷写相关的故障码

如果版本号正确,DTC为空,恭喜你,刷写成功。

3.4 10个步骤速查表

步骤 服务 请求示例 说明
1 诊断会话控制 10 02 切换到编程会话
2 安全访问 27 03/04 种子-密钥验证解锁
3 通信控制 28 03 关闭非诊断通信
4 DTC控制 85 02 关闭DTC存储
5 请求下载 34 00 44 声明写入地址和长度
6 数据传输 36 发送固件数据块
7 请求退出传输 37 结束当前数据块
8 检查编程依赖 31 01 FF 00 校验固件完整性
9 ECU复位 11 01 硬件复位启动新固件
10 重新连接验证 10 01 + 22 F1 00 确认版本号、检查DTC

常见坑点:

  • 步骤5-7循环时,块序列号不要重复,否则ECU会认为数据重复而拒绝写入
  • 步骤8的依赖检查必须在所有数据块传完之后执行,不能提前
  • 步骤9复位后,ECU可能进入Bootloader模式,需要重新走安全访问才能继续诊断

好了,三阶段十步骤就讲完了。你想想看,其实刷写流程并不复杂,关键是把每一步的时序和依赖关系搞清楚。我在实际项目中,经常看到工程师把步骤3和步骤4搞反,或者漏掉步骤8。嗯,这些细节决定了刷写是成功还是变砖。