1. UDS协议概述:UDS协议简介、OSI七层模型与UDS、UDS服务分类、诊断会话控制

大家好,欢迎来到这门课。我是你们的老朋友,一个在嵌入式诊断领域摸爬滚打了十几年的工程师。

咱们今天聊UDS协议。说实话,我刚入行那会儿,UDS还没现在这么普及。那时候做诊断,各家有各家的玩法,兼容性差得要命。后来UDS一统江湖,我打心底里觉得——嗯,这行业终于有规矩了。

1.1 UDS协议简介

UDS,全称是 Unified Diagnostic Services,统一诊断服务。说白了,它就是一套汽车电子领域的“通用语言”。

你想想看,一辆车上几十个ECU(电子控制单元),发动机、变速箱、ABS、气囊……它们来自不同供应商。出了问题怎么查?总不能让每个厂家都用自己的协议吧?

UDS就是来解决这个问题的。它定义了一套标准化的诊断请求和响应机制。不管你是哪个厂家的ECU,只要它支持UDS,你用同一套诊断仪就能跟它“对话”。

核心要点:UDS是ISO 14229标准定义的诊断协议,广泛应用于汽车电子领域。它不依赖底层总线,可以跑在CAN、LIN、以太网等多种物理层上。

我个人习惯把UDS理解成“医生和病人”的关系。诊断仪是医生,ECU是病人。医生问“你哪里不舒服?”,ECU回答“我这儿报了个故障码”。就这么简单。

1.2 OSI七层模型与UDS

聊协议,绕不开OSI七层模型。很多初学者一听七层就头大,觉得太抽象。我当年也一样。

其实你不需要把每一层都背下来。咱们只看UDS在哪儿。

OSI层 UDS相关协议/标准 我的理解
应用层(第7层) ISO 14229-1 (UDS) 这就是咱们要学的核心,定义服务本身
表示层(第6层) ISO 14229-2 数据格式、编码规则,说白了就是“话怎么说”
会话层(第5层) ISO 15765-3 (CAN上的UDS) 建立、维持、结束诊断会话
传输层(第4层) ISO 15765-2 (CAN传输层) 数据分包、重组,保证大包能传过去
网络层(第3层) ISO 15765-2 (部分) 寻址、路由
数据链路层(第2层) CAN 2.0 / CAN FD 帧格式、错误检测
物理层(第1层) ISO 11898 (CAN物理层) 电平、线束、连接器

你看,UDS本身只占应用层。但实际工作中,我们经常把下面几层也打包在一起讲。我在项目里最常打交道的是CAN上的UDS,也就是ISO 15765系列。

我的建议:刚开始学,先抓住应用层。底层传输机制可以后面再补。别一上来就被七层模型吓住了。

1.3 UDS服务分类

UDS定义了很多服务,每个服务都有一个唯一的ID,叫SID(Service Identifier)。

这些服务可以分成六大类。我列个表,你一看就明白:

类别 典型服务 SID 干什么用的
诊断和通信管理 诊断会话控制 0x10 切换诊断模式
ECU复位 0x11 让ECU重启
安全访问 0x27 解锁受保护的功能
数据传输 读取数据 0x22 读DID(数据标识符)
写入数据 0x2E 写DID
存储数据传输 读取故障码 0x19 读DTC
清除故障码 0x14 清DTC
输入输出控制 输入输出控制 0x2F 强制控制某个引脚或执行器
远程激活 例程控制 0x31 启动/停止一段程序
请求下载/上传 0x34 / 0x35 刷写固件用
上传/下载 传输数据 0x36 实际传数据
请求传输退出 0x37 结束传输

这六大类,基本覆盖了诊断的所有场景。从最简单的“读个版本号”,到复杂的“刷写固件”,都离不开它们。

我记得刚带团队那会儿,有个新人问我:“这么多服务,我该先学哪个?”我的回答是——先学0x10和0x3E。为什么?因为它们是“门”。

1.4 诊断会话控制

诊断会话控制,服务ID是0x10。这是UDS里最基础、最重要的服务之一。

为什么说它是“门”?因为ECU平时不搭理诊断请求。你得先通过0x10服务,告诉ECU:“嘿,我要开始诊断了!”ECU才会进入诊断模式,响应你的其他请求。

UDS定义了三种默认会话:

  • 默认会话(Default Session):SID = 0x01。ECU上电后默认处于这个会话。功能受限,只能做最基本的诊断。
  • 编程会话(Programming Session):SID = 0x02。用于刷写固件。这个会话下,ECU会关闭一些非必要的通信,保证刷写稳定。
  • 扩展诊断会话(Extended Diagnostic Session):SID = 0x03。功能最全,可以读写数据、执行例程、控制输入输出等。

实际项目中,还有厂商自定义的会话。比如我做过的一个项目,客户要求加一个“产线测试会话”,SID = 0x40,专门用于出厂前的功能测试。

注意:会话切换是有条件的。比如从默认会话切换到编程会话,ECU可能会要求你先通过安全访问(0x27服务)。我曾经遇到过因为忘记先解锁,导致刷写失败,折腾了一整天才找到原因。

会话切换的请求格式很简单:

// 请求:切换到扩展诊断会话
// 0x10 是服务ID,0x03 是扩展诊断会话的SID
请求报文: 0x10 0x03

// 正常响应
// 0x50 = 0x10 + 0x40 (肯定响应标识)
// 0x03 表示当前会话是扩展诊断会话
响应报文: 0x50 0x03

如果ECU不支持切换,或者当前状态不允许,它会返回否定响应:

// 否定响应示例
// 0x7F 是否定响应标识
// 0x10 是请求的服务ID
// 0x12 是否定响应码,表示“子功能不支持”
响应报文: 0x7F 0x10 0x12

这里有个小细节。会话切换后,ECU会启动一个定时器。如果一段时间内没有收到任何诊断请求(包括0x3E服务,即“保持激活”),ECU会自动切回默认会话。这个超时时间通常是5秒左右,具体看厂商配置。

避坑指南:我曾经在调试时,发现诊断会话总是莫名其妙地退出。查了半天,原来是上位机发送请求的间隔超过了ECU的超时时间。解决方案很简单——定期发送0x3E服务,告诉ECU“我还活着”。

好了,这一章的内容就到这里。我们讲了UDS是什么、它在OSI模型中的位置、服务的六大分类,以及最基础的诊断会话控制。下一章,咱们会深入聊一聊“诊断请求和响应的格式”,以及那些让人头疼的否定响应码。

记住一句话:UDS不难,难的是细节。咱们慢慢来。