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名称我的理解
22ReadDataByIdentifier按ID读数据,比如读VIN码
2EWriteDataByIdentifier写数据,比如配置参数
19ReadDTCInformation读故障码,诊断的核心
14ClearDiagnosticInformation清故障码,修完车要清一下

我个人习惯把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开发,有几个坑我替你们踩过了:

  1. 会话超时:默认会话一般5秒超时,扩展和编程会话可能更长。一定要定时发3E服务保持会话。
  2. 会话切换失败:有些ECU在特定条件下不允许切换会话,比如正在执行例程时。这时候要先中止当前操作。
  3. 安全访问:编程会话通常需要先做27服务解锁。解锁算法各OEM不同,有的是种子密钥,有的是滚动码。
  4. NRC处理:ECU返回的否定响应码要仔细看。0x22(条件不满足)最常见,0x31(请求超出范围)也经常遇到。

嗯,UDS这部分内容确实不少,但掌握了分类和会话控制这两个核心,后面的路就好走了。下一章咱们聊聊具体的诊断服务实现,到时候我会拿实际代码来演示。