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不难,难的是细节。咱们慢慢来。