2、汽车诊断协议概述:UDS协议基础、ISO 14229标准、诊断会话控制、诊断服务分类
好,咱们进入第二章。这一章聊的是诊断协议的基础,说白了就是UDS那点事儿。很多刚接触SOA的朋友会觉得诊断是传统ECU的活儿,跟SOA没关系。其实不然,在SOA架构下,诊断服务本身也被服务化了。所以,理解UDS是理解后续远程刷写、诊断路由的基础。
2.1 UDS协议基础与ISO 14229标准
UDS,全称是Unified Diagnostic Services,统一诊断服务。它定义在ISO 14229标准里。这个标准,我个人习惯把它看作是汽车诊断的“普通话”。为什么这么说?因为以前各家OEM都有自己的诊断协议,比如大众的KWP2000、福特的DCL,互不兼容。后来大家发现这样太累了,一个诊断仪要装好几套软件,于是ISO 14229应运而生。
ISO 14229标准的核心思想,是把诊断功能抽象成一系列的服务。你想想看,不管你是读故障码、读数据、还是执行例程,本质上都是客户端(诊断仪)向服务器(ECU)发一个请求,服务器回一个响应。这个请求和响应的格式,就是UDS协议规定的。
我记得有一次在项目中,一个同事问我:“为什么UDS报文里总是有那么多字节,看着像天书?”其实拆开来看很简单。一个UDS报文由三部分组成:
- 服务标识符(SID):1个字节,告诉ECU你要干什么。比如0x10是诊断会话控制,0x22是读取数据。
- 子功能(Sub-function):可选,1个字节,进一步细化操作。比如0x10服务下的0x01表示默认会话,0x02表示编程会话。
- 数据参数(Data):可变长度,携带具体的数据内容。
举个例子,一个简单的读取VIN码的请求:
请求:22 F1 90
- 22:SID,表示读取数据(ReadDataByIdentifier)
- F1 90:数据标识符(DID),表示VIN码
ECU收到后,会回复:
响应:62 F1 90 4C 53 56 38 30 30 30 30 30 30 30 30 30 30 30 30
- 62:肯定响应,等于请求SID + 0x40
- F1 90:回显DID
- 4C 53 56...:VIN码的ASCII码
嗯,这里要注意,如果ECU无法执行这个请求,它会回复一个否定响应,格式是:
否定响应:7F 22 31
- 7F:否定响应标识
- 22:回显请求的SID
- 31:否定响应码(NRC),表示请求超出范围
2.2 诊断会话控制
诊断会话控制,服务ID是0x10。这个服务是UDS的“门禁系统”。ECU不会让你一上来就为所欲为,你得先告诉它你要干什么,它才会开放对应的权限。
ISO 14229定义了三种标准会话:
| 子功能 | 会话名称 | 典型用途 | 权限 |
|---|---|---|---|
| 0x01 | 默认会话(Default Session) | 日常诊断,读故障码、读数据 | 最低,只能读,不能写 |
| 0x02 | 编程会话(Programming Session) | 刷写软件、配置参数 | 最高,可以写入Flash |
| 0x03 | 扩展诊断会话(Extended Diagnostic Session) | 执行例程、写入配置 | 中等,可以写RAM,不能写Flash |
你想想看,为什么要有会话控制?说白了就是安全。如果任何一个诊断仪都能随意刷写ECU,那车早就变砖了。编程会话通常还需要配合安全访问(0x27服务)才能进入,这是双重保险。
我个人习惯在SOA架构设计时,把会话控制设计成一个独立的服务。这样,上层应用(比如远程刷写客户端)只需要调用这个服务来切换会话,而不需要关心底层UDS协议的细节。这其实就是SOA的解耦思想。
2.3 诊断服务分类
UDS的服务很多,ISO 14229-1里定义了26个服务。但别怕,我们不需要全记住。按功能分,其实就三大类:读取、写入、控制。我按这个思路给你捋一遍。
2.3.1 读取类服务
这类服务只读不改,是诊断中最常用的。核心服务有:
- 0x22 - ReadDataByIdentifier(按标识符读取数据):最常用的读服务。可以读VIN、软件版本、硬件版本、传感器值等。每个数据都有一个唯一的DID(Data Identifier)。
- 0x19 - ReadDTCInformation(读取故障码信息):读DTC(Diagnostic Trouble Code)的。可以读当前故障、历史故障、冻结帧等。这个服务比较复杂,子功能很多。
- 0x21 - ReadDataByPeriodicIdentifier(按周期标识符读取数据):用于周期性读取数据,比如每100ms读一次车速。在SOA架构下,这个服务可以被事件驱动的订阅机制替代。
我记得在做一个OBD(车载诊断系统)项目时,客户要求读取发动机转速。我用了0x22服务,DID是0x010C。结果发现读回来的数据单位是rpm的4倍,需要除以4。这就是DID定义里的“转换公式”,一定要看OEM的诊断规范,不能想当然。
2.3.2 写入类服务
这类服务会修改ECU的数据,通常需要先进入扩展会话或编程会话,并且通过安全访问。核心服务有:
- 0x2E - WriteDataByIdentifier(按标识符写入数据):和0x22对应,用于写入配置参数、校准值等。比如写入VIN码、写入胎压监测阈值。
- 0x31 - RoutineControl(例程控制):这个服务有点特殊,它既可以读也可以写。它用于执行一个预定义的“例程”,比如擦除Flash、校验签名、执行自检。例程有三个子功能:开始(0x01)、停止(0x02)、请求结果(0x03)。
- 0x34 - RequestDownload(请求下载):刷写的第一步。告诉ECU我要下载数据了,数据有多大,存在哪个地址。ECU回复一个“最大允许长度”,双方协商好传输参数。
- 0x36 - TransferData(传输数据):刷写的第二步。把实际的数据块发给ECU。通常一次发4096字节,然后等ECU确认,再发下一块。
- 0x37 - RequestTransferExit(请求传输退出):刷写的第三步。告诉ECU数据发完了,ECU会做最后的校验和完整性检查。
2.3.3 控制类服务
这类服务用于控制ECU的行为,比如复位、开启/关闭某个功能。核心服务有:
- 0x11 - ECUReset(ECU复位):让ECU重启。有硬复位(0x01)、软复位(0x02)、快速上电复位(0x03)等。刷写完成后,通常需要发一个复位命令让ECU加载新软件。
- 0x28 - CommunicationControl(通信控制):控制ECU的通信行为。比如关闭非诊断报文、开启/关闭特定网络。在刷写时,为了减少总线负载,通常会关闭应用报文。
- 0x85 - ControlDTCSetting(控制DTC设置):开启或关闭故障码记录。刷写时,为了避免误报故障,通常先关闭DTC记录,刷完再打开。
- 0x3E - TesterPresent(测试器存在):俗称“心跳”。告诉ECU诊断仪还在线,不要超时退出会话。
你想想看,控制类服务在SOA架构下怎么用?举个例子,0x11服务(ECU复位)可以封装成一个“复位服务”,上层应用(比如OTA管理器)调用这个服务时,不需要知道底层是CAN还是DoIP,也不需要知道复位后ECU要等多久才能重新上线。这些细节都由服务实现者去处理。
好了,这一章的内容就到这里。UDS协议是诊断的基石,理解它,你才能理解后续的远程刷写、诊断路由、SOA服务化设计。下一章,我们会深入聊一聊SOA架构下诊断服务的具体设计方法。