2. ISO 14229标准解读:核心内容与UDS服务分类
好,咱们进入第二章。ISO 14229这个标准,说白了就是UDS诊断协议的“宪法”。你开发任何诊断功能,最终都得回到这份文档里找依据。我刚开始接触UDS那会儿,看着这好几百页的PDF头都大,后来才发现,只要抓住了它的骨架,剩下的都是血肉。
这一章,我带你把ISO 14229-1的核心内容捋一遍,重点看看UDS的服务分类和协议数据单元(PDU)结构。这些东西搞清楚了,后面写代码、搭测试环境,你心里就有底了。
2.1 ISO 14229-1核心内容概览
ISO 14229-1定义了诊断服务的通用需求,不依赖具体的通信总线(比如CAN、LIN、以太网)。它规定了客户端(通常是诊断仪)和服务器(ECU)之间怎么对话。
核心要点: 标准定义了26种诊断服务,分为6大类。每个服务都有一个唯一的SID(Service Identifier,服务标识符),占用1个字节。
举个例子,0x10就是“诊断会话控制”,0x22是“通过ID读取数据”。这些SID你以后会天天跟它们打交道。
2.2 UDS服务分类详解
ISO 14229-1把服务分成了6个功能单元。我习惯把这6类记成“诊、数、存、输、远、上”,对应下面这张表:
| 功能单元 | 服务列表(SID) | 一句话用途 |
|---|---|---|
| 诊断与通信管理 | 0x10, 0x11, 0x27, 0x28, 0x3E, 0x83, 0x84, 0x85 | 控制会话、复位、安全访问、通信控制 |
| 数据传输 | 0x22, 0x23, 0x24, 0x2A, 0x2C, 0x2E | 读写DID、内存地址、周期读取数据 |
| 存储数据传输 | 0x14, 0x19 | 清除/读取诊断故障码(DTC) |
| 输入输出控制 | 0x2F | 强制控制ECU的输入/输出信号 |
| 远程激活 | 0x31 | 启动ECU内部例程(如自学习、校准) |
| 上传下载 | 0x34, 0x35, 0x36, 0x37, 0x38 | 刷写软件、上传/下载数据块 |
咱们挑几个重点类说说。
2.2.1 诊断与通信管理
这是ECU的“看门人”。你发任何诊断请求之前,ECU得先知道你在哪个“会话”里。
- 0x10 诊断会话控制:ECU有默认会话、编程会话、扩展会话。我遇到过不少新手,上来就发0x22读数据,结果ECU回了个NRC 0x78(请求正确接收-响应待定),其实就是会话没切对。
- 0x11 ECU复位:硬件复位、钥匙关/开复位、快速启动复位。刷完软件后,这个服务用得最多。
- 0x27 安全访问:解锁受保护的功能。需要种子和密钥的“握手”流程。
- 0x3E 测试仪在线:俗称“心跳包”。防止ECU因为超时自动跳回默认会话。
我的习惯: 写测试脚本时,我会把0x3E放在一个独立线程里,每500ms发一次。这样主线程做其他操作时,会话不会掉。
2.2.2 数据传输
这是日常诊断最常用的功能。通过DID(Data Identifier,数据标识符)来读写ECU的内部数据。
- 0x22 通过ID读取数据:读电压、温度、版本号。DID是2个字节,比如0xF190代表“ECU硬件版本”。
- 0x2E 通过ID写入数据:写配置参数、标定值。注意,写操作通常需要先切到扩展会话,并且通过安全访问。
- 0x23 通过地址读取内存:直接访问物理内存地址。这个服务在Bootloader里很常见,用来读Flash内容。
2.2.3 存储数据传输
专门处理故障码(DTC)。
- 0x14 清除诊断信息:清除所有DTC和快照数据。修完车后,维修技师会用这个服务清故障灯。
- 0x19 读取DTC信息:这个服务有28个子功能,比如读当前故障、读历史故障、读故障发生时的环境数据(快照)。
我曾经踩过的坑: 0x19的子功能0x02(读取与DTC相关的快照记录)返回的数据长度是不固定的。如果你的解析代码写死了长度,遇到多帧响应时,很容易丢数据。一定要按ISO 15765-2的传输层协议来组包。
2.2.4 输入输出控制
只有一个服务:0x2F。它允许诊断仪临时接管ECU的某个输入或输出信号。比如强制让某个继电器吸合,或者模拟某个传感器值。
这个服务在产线测试和售后维修中非常有用。但要注意,操作完成后,一定要用“返回正常模式”的控制选项,否则ECU会一直处于“被控制”状态。
2.2.5 远程激活
0x31 例程控制。ECU内部预置了一些“小程序”,通过这个服务来启动、停止或查询结果。
举个例子:在Bootloader里,0x31可以用来擦除Flash扇区、检查应用程序的完整性(CRC校验)。
2.2.6 上传下载
这是刷写(Flash Programming)的核心服务组。
- 0x34 请求下载:告诉ECU“我要写数据了”,协商数据格式和长度。
- 0x36 传输数据:实际的数据块传输,一次最多传4095字节。
- 0x37 请求传输退出:结束本次传输。
这三个服务配合起来,就是完整的刷写流程。我后面会专门用一章来讲刷写协议栈的实现。
2.3 协议数据单元(PDU)结构
UDS的报文,在应用层叫PDU。它由三部分组成:
+----------------+----------------+------------------+
| A_Data (SID) | SubFunction | Data Parameters |
| (1 byte) | (0-1 byte) | (0-N bytes) |
+----------------+----------------+------------------+
- A_Data (SID):服务标识符,必选。比如0x22。
- SubFunction:子功能,可选。比如0x10服务的子功能0x01(默认会话)、0x02(编程会话)。
- Data Parameters:数据参数,可选。比如0x22服务后面跟着的2字节DID。
你想想看,一个完整的诊断请求,其实就是把这些字节拼起来,然后交给传输层(比如CAN的ISO 15765-2)去打包发送。
下面这张图,把UDS服务的分类和PDU结构串在了一起,方便你建立整体认知:
2.4 响应格式与NRC
UDS的响应分为肯定响应和否定响应。
- 肯定响应:格式是
SID + 0x40开头。比如请求0x22,肯定响应就是0x62。 - 否定响应:格式是
0x7F + 请求SID + NRC。NRC(Negative Response Code)告诉客户端为什么被拒。
常见的NRC有:
| NRC (Hex) | 含义 | 常见原因 |
|---|---|---|
| 0x10 | 一般拒绝 | 服务不支持或当前状态不允许 |
| 0x12 | 子功能不支持 | 比如0x19的子功能0x05没实现 |
| 0x22 | 条件错误 | 没切到正确会话就发写请求 |
| 0x31 | 请求超出范围 | DID不存在或数据长度不对 |
| 0x33 | 安全访问拒绝 | 没解锁就操作受保护功能 |
| 0x78 | 请求正确接收-响应待定 | ECU需要额外时间处理,稍后重试 |
注意: NRC 0x78比较特殊。它表示ECU收到了请求,但还没处理完。客户端收到0x78后,应该等待一段时间再发相同的请求,而不是立即重试。我曾经见过一个测试脚本,收到0x78后疯狂重发,结果把ECU的通信栈搞崩了。
2.5 小结
这一章我们把ISO 14229-1的骨架搭起来了。你记住了6大类服务、它们的典型SID,以及PDU的三段式结构,后面学具体服务实现时就不会迷路。
嗯,标准文档是死的,但应用是活的。我建议你手边常备一份ISO 14229-1的PDF,遇到不确定的NRC或服务行为时,直接翻原文档,比网上搜来的二手信息靠谱得多。