刷写协议概览:UDS协议简介、ISO 14229标准、诊断会话控制、安全访问机制
各位工程师,大家好。今天我们聊聊刷写协议。很多人一听到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的“锁”。
安全访问的流程是“种子-密钥”验证:
- 诊断仪发送“请求种子”指令(0x27 01)
- ECU返回一个随机种子(通常是4字节)
- 诊断仪用特定算法计算密钥
- 诊断仪发送“发送密钥”指令(0x27 02)
- 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协议栈分成了四层。刷写时,我们主要关注应用层和会话层。传输层处理大文件分包,物理层决定用什么总线。
我个人建议,刚开始学UDS时,先掌握三个核心服务:0x10(会话控制)、0x27(安全访问)、0x34/0x36(请求下载/传输数据)。这三个服务覆盖了刷写90%的流程。
学习建议:找一块开发板,用CAN工具实际抓一下UDS报文。看报文比看文档直观得多。我当年就是靠抓报文学会UDS的。