2. ECU基础

各位工程师,大家好。今天我们聊聊刷写协议。很多人一听到UDS、ISO 14229这些术语,就觉得头大。其实说白了,它就是ECU和诊断仪之间沟通的“共同语言”。没有这套语言,你发指令ECU听不懂,ECU报故障你也看不懂。

我个人习惯把UDS理解成一套“标准化的对话规则”。它规定了什么时候该说话、说什么、怎么说。今天我们就把这套规则拆开来看。

UDS协议与ISO 14229标准

UDS的全称是Unified Diagnostic Services,统一诊断服务。它定义在ISO 14229标准里。这个标准覆盖了从物理层到应用层的全套规范。

我刚开始接触UDS时,最困惑的是它和KWP2000的区别。KWP2000是早期的标准,UDS是它的升级版。UDS更灵活,支持的诊断功能更多,现在几乎所有新车都用UDS。

特性 KWP2000 (ISO 14230) UDS (ISO 14229)
物理层 K-Line CAN / DoIP / LIN
会话模型 5种会话 4种会话(更精简)
安全访问 基于种子-密钥 基于种子-密钥(算法更复杂)
传输层 单帧/多帧 单帧/多帧(支持更大数据块)
应用层 服务ID范围窄 服务ID范围宽(0x00-0x3E)

UDS的核心是“请求-响应”模式。诊断仪发一个请求,ECU回一个响应。请求和响应都遵循固定的报文格式。

// UDS报文结构(CAN总线为例)
// 字节0:PCI(协议控制信息)
// 字节1:SID(服务标识符)
// 字节2-N:数据参数

// 请求示例:读取ECU软件版本(0x22 读取数据标识符)
// 请求:02 22 F1 00
// 02 = 单帧,2字节数据
// 22 = 读取数据标识符服务
// F1 00 = 数据标识符(软件版本号)

// 响应示例
// 响应:06 62 F1 00 01 02 03 04
// 06 = 单帧,6字节数据
// 62 = 读取数据标识符响应
// F1 00 = 数据标识符
// 01 02 03 04 = 软件版本号(V1.2.3.4)

关键点:UDS报文中的第一个字节是PCI,它告诉ECU这是单帧还是多帧。刷写时经常遇到大文件传输,多帧传输是必须掌握的技能。

诊断会话控制(0x10服务)

ECU不会一直处于“可刷写”状态。它有不同的工作模式,UDS把这些模式叫做“诊断会话”。

ISO 14229定义了4种标准会话:

  • 默认会话(Default Session):ECU上电后的初始状态。只能执行基本的诊断服务,比如读取故障码。不能刷写。
  • 编程会话(Programming Session):刷写专用的会话。在这个会话下,ECU允许执行内存写入、擦除等操作。
  • 扩展诊断会话(Extended Diagnostic Session):比默认会话权限更高,可以执行一些标定、配置类的服务。不能刷写。
  • 安全系统诊断会话(Safety System Diagnostic Session):用于安全相关系统的诊断,比如安全气囊。一般刷写用不到。

刷写时,我们需要从默认会话切换到编程会话。切换指令是0x10 02。

// 切换到编程会话
// 请求:02 10 02
// 02 = 单帧,2字节数据
// 10 = 诊断会话控制服务
// 02 = 编程会话

// 响应:02 50 02
// 02 = 单帧,2字节数据
// 50 = 诊断会话控制响应(0x10 + 0x40)
// 02 = 编程会话

实战经验:切换会话后,ECU可能会复位某些模块。我遇到过切换编程会话后,CAN通信中断了几百毫秒的情况。刷写工具需要处理这种“会话切换延迟”。

为什么会这样?因为ECU进入编程会话时,会停止一些非关键任务,释放资源给刷写流程。这个过程中通信会短暂中断。

安全访问机制(0x27服务)

刷写ECU就像给手机刷系统。你不能让任何人随便刷。安全访问机制就是ECU的“锁”。

安全访问的流程是“种子-密钥”验证:

  1. 诊断仪发送“请求种子”指令(0x27 01)
  2. ECU返回一个随机种子(通常是4字节)
  3. 诊断仪用特定算法计算密钥
  4. 诊断仪发送“发送密钥”指令(0x27 02)
  5. ECU验证密钥是否正确
// 安全访问流程示例
// 步骤1:请求种子
// 请求:02 27 01
// 响应:06 67 01 12 34 56 78
// 种子 = 0x12345678

// 步骤2:计算密钥(假设算法:种子 + 0xA5A5A5A5)
// 密钥 = 0x12345678 + 0xA5A5A5A5 = 0xB7D9FC1D

// 步骤3:发送密钥
// 请求:06 27 02 B7 D9 FC 1D
// 响应:02 67 02 (成功)
// 或响应:02 67 03 (失败)

避坑指南:我曾经遇到一个项目,安全访问算法里包含了ECU的VIN码。刷写工具必须提前读取VIN,否则算出来的密钥永远是错的。这种“动态种子”设计很常见,刷写工具必须适配。

安全访问有几个关键参数需要关注:

参数 说明 典型值
种子长度 种子占用的字节数 4字节
密钥长度 密钥占用的字节数 4字节
尝试次数 允许连续失败的次数 3次
锁定时间 超过尝试次数后的锁定时间 10秒
算法类型 种子到密钥的转换算法 自定义算法

重要提醒:安全访问失败后,ECU会进入“锁定状态”。锁定期间不接受任何安全访问请求。刷写工具必须等待锁定时间结束,或者重新上电才能解锁。

嗯,这里要注意。有些ECU在锁定状态下,连诊断会话切换都不允许。所以刷写流程中,安全访问失败的处理逻辑一定要写对。

本章知识体系

下面这张图展示了UDS刷写协议的核心结构。你可以看到,从物理层到应用层,每一层都有对应的标准。

UDS刷写协议知识体系 应用层 - 诊断服务 0x10 诊断会话控制 | 0x27 安全访问 | 0x22 读取数据 | 0x2E 写入数据 | 0x34 请求下载 会话层 - 诊断会话管理 默认会话 → 编程会话 → 扩展诊断会话 → 安全系统诊断会话 传输层 - 多帧传输 单帧(SF) | 首帧(FF) | 连续帧(CF) | 流控制帧(FC) 物理层 - 总线类型 CAN | DoIP | LIN | FlexRay 刷写常用 CAN/DoIP

这张图把UDS协议栈分成了四层。刷写时,我们主要关注应用层和会话层。传输层处理大文件分包,物理层决定用什么总线。

我个人建议,刚开始学UDS时,先掌握三个核心服务:0x10(会话控制)、0x27(安全访问)、0x34/0x36(请求下载/传输数据)。这三个服务覆盖了刷写90%的流程。

学习建议:找一块开发板,用CAN工具实际抓一下UDS报文。看报文比看文档直观得多。我当年就是靠抓报文学会UDS的。