3、诊断通信协议(UDS):UDS服务分类与会话控制
好,咱们今天聊聊UDS。说实话,UDS这套协议在车载领域,就像TCP/IP在互联网的地位一样——绕不开,躲不掉。我最早接触UDS是在做T-Box项目的时候,那时候被各种服务ID搞得晕头转向,后来慢慢摸清了门道,才发现它其实挺有章法的。
3.1 UDS服务分类:三大类,各司其职
UDS把诊断服务分成了三大类。你想想看,一辆车上的ECU少说几十个,每个都要能诊断,如果没有一个清晰的分类,那代码维护起来就是灾难。
3.1.1 诊断与通信管理
这一类服务,说白了就是管「连接」和「状态」的。比如:
- 10 服务(DiagnosticSessionControl):会话控制,后面细讲
- 11 服务(ECUReset):复位ECU,我遇到过客户要求用这个服务做OTA后的软复位
- 27 服务(SecurityAccess):安全访问,解锁ECU的「管理员权限」
- 28 服务(CommunicationControl):通信控制,可以关掉某些报文
- 3E 服务(TesterPresent):保持会话活跃,防止超时退出
重点提醒:3E服务特别容易被忽略。我曾经调试一个项目,发现诊断会话总是莫名其妙退出,查了半天才发现是测试工具没有定时发3E报文。ECU默认会话超时是5秒,你不喂它,它就走了。
3.1.2 数据传输
这一类是干活的主力。你要读故障码、读数据、写参数,都靠它们。
| 服务ID | 名称 | 我的理解 |
|---|---|---|
| 22 | ReadDataByIdentifier | 按ID读数据,比如读VIN码 |
| 2E | WriteDataByIdentifier | 写数据,比如配置参数 |
| 19 | ReadDTCInformation | 读故障码,诊断的核心 |
| 14 | ClearDiagnosticInformation | 清故障码,修完车要清一下 |
我个人习惯把22服务和2E服务放在一起记——一个读一个写,成对出现。19服务就复杂了,它有很多子功能,比如读当前故障、读历史故障、读故障快照等。嗯,这里要注意,不同OEM对19服务的子功能支持程度不一样,做兼容性测试时要特别小心。
3.1.3 存储数据传输
这一类主要管ECU内部的数据上传和下载。典型的就是:
- 34 服务(RequestDownload):请求下载,ECU准备好接收数据
- 36 服务(TransferData):传输数据,真正搬砖的
- 37 服务(RequestTransferExit):结束传输
刷写固件就是靠这三个服务配合完成的。我做过一个项目,刷写过程中36服务的数据块大小没协商好,导致刷写速度慢得像蜗牛。后来我把块大小从64字节调到了4096字节,速度直接翻了十几倍。
3.2 会话控制:默认/扩展/编程会话
会话控制是UDS里一个非常基础但又容易踩坑的点。ECU有几种不同的「工作模式」,每种模式下能用的服务不一样。
3.2.1 默认会话(Default Session)
ECU上电后默认就在这个会话里。说白了,就是「普通模式」。在这个模式下:
- 只能做基本的诊断操作,比如读VIN、读故障码
- 不能写数据,不能刷写
- 安全等级最低
我刚开始做诊断时,以为默认会话就能干所有事,结果发了个2E写数据请求,ECU直接回了NRC 0x78(RequestCorrectlyReceived-ResponsePending),然后就没然后了。后来才发现,必须先切到扩展会话才能写。
3.2.2 扩展会话(Extended Session)
这个会话比默认会话权限高一些。你可以理解为「工程师模式」。在扩展会话下:
- 可以读写大部分数据
- 可以做IO控制
- 可以做例程控制
- 但还不能刷写固件
小技巧:我一般会在诊断工具里默认先发10 03(切换到扩展会话),省得后面因为会话不对而出错。当然,有些ECU对会话切换有次数限制,不能频繁切来切去。
3.2.3 编程会话(Programming Session)
这是最高权限的会话,专门用来刷写固件。进入编程会话后:
- ECU会关闭大部分通信功能
- 只响应诊断请求
- 可以执行34/36/37服务进行刷写
- 有些ECU还会关掉看门狗,防止刷写过程中被复位
警告:我曾经在编程会话里犯过一个低级错误——刷写完成后忘记切回默认会话。结果ECU一直停留在编程模式,导致车辆无法正常行驶。后来我养成了习惯,刷写完成后一定发10 01切回默认会话,再发11 01复位ECU。
3.3 会话切换的底层逻辑
会话切换是通过10服务实现的。格式很简单:
请求:10 01 // 切换到默认会话
请求:10 02 // 切换到扩展会话(部分OEM用10 03)
请求:10 03 // 切换到编程会话
ECU收到后会回复:
响应:50 01 XX XX XX // XX XX XX是P2和P2*定时器值
这个P2和P2*是什么意思?P2是ECU处理单个请求的最大时间,P2*是ECU处理连续请求的最大时间。我遇到过一台ECU,P2设成了50ms,但实际处理一个22服务需要80ms,结果一直超时。后来发现是OEM的规范写错了,实际应该是150ms。
3.4 避坑指南
做UDS开发,有几个坑我替你们踩过了:
- 会话超时:默认会话一般5秒超时,扩展和编程会话可能更长。一定要定时发3E服务保持会话。
- 会话切换失败:有些ECU在特定条件下不允许切换会话,比如正在执行例程时。这时候要先中止当前操作。
- 安全访问:编程会话通常需要先做27服务解锁。解锁算法各OEM不同,有的是种子密钥,有的是滚动码。
- NRC处理:ECU返回的否定响应码要仔细看。0x22(条件不满足)最常见,0x31(请求超出范围)也经常遇到。
嗯,UDS这部分内容确实不少,但掌握了分类和会话控制这两个核心,后面的路就好走了。下一章咱们聊聊具体的诊断服务实现,到时候我会拿实际代码来演示。