2. OSI七层模型与UDS:物理层、数据链路层、网络层(DoCAN)、传输层、会话层、表示层、应用层

聊UDS诊断,绕不开OSI七层模型。

很多刚入行的工程师觉得这东西太理论,跟实际开发没啥关系。我当年也这么想,直到有一次在台架上调CAN通信,死活连不上诊断仪,查了三天才发现是物理层的一个终端电阻虚焊了。嗯,从那以后我再也不敢小看这七层了。

说白了,UDS诊断报文从你的诊断仪发出去,到ECU收到并响应,中间要经过这七层的“包装”和“拆包”。每一层都有自己的职责,少一层都不行。

2.1 物理层:信号的基础

物理层管的是最底层的东西——电压、电平、线束、连接器。在车载诊断里,最常见的就是CAN总线物理层。

我个人习惯,拿到一个新项目,先看物理层设计。为什么?因为物理层出问题,上层再牛也白搭。

  • 差分信号:CAN_H和CAN_L,电压差决定逻辑0和1。显性电平(逻辑0)约1.5V~3.5V,隐性电平(逻辑1)约2.5V。
  • 终端电阻:120Ω,必须加在总线两端。我遇到过一台车,诊断时断时续,最后发现是终端电阻焊在了中间位置,信号反射得一塌糊涂。
  • 波特率:UDS诊断常用250kbps或500kbps。别乱改,整车网络有统一要求。
⚠️ 避坑指南
我曾经在实验室里用一根过长的杜邦线代替CAN线,结果信号畸变严重,诊断报文根本发不出去。物理层的线束长度、双绞程度、屏蔽,都有讲究,别图省事。

2.2 数据链路层:帧的封装与仲裁

数据链路层在CAN协议里对应的是CAN控制器干的活。它负责把上层的数据打包成CAN帧,加上ID、控制位、CRC校验,然后发到总线上。

你想想看,总线上那么多ECU,为什么不会乱?靠的就是数据链路层的仲裁机制

  • CAN ID:诊断报文通常使用功能寻址(0x7DF)或物理寻址(如0x7E0、0x7E8)。ID越小,优先级越高。
  • 帧类型:UDS诊断主要用数据帧,远程帧用得少。
  • DLC:数据长度代码,标准CAN帧最多8字节。嗯,这里要注意,UDS诊断报文如果超过8字节,就得靠传输层来分包了。
💡 关键点
数据链路层只保证一帧数据在总线上的正确传输,不保证多个帧之间的顺序和完整性。这个任务要交给上层。

2.3 网络层(DoCAN):ISO 15765-2

网络层是UDS诊断在CAN总线上的核心。它解决了一个大问题:CAN帧一次只能发8字节,但UDS诊断报文可能很长(比如刷写程序,几千字节),怎么办?

答案就是多帧传输。ISO 15765-2(也叫DoCAN)定义了如何把长报文拆成多个CAN帧,再在接收端重组。

帧类型 PCI字节 说明
单帧(SF) 0x00~0x07 报文长度≤7字节,一帧搞定
首帧(FF) 0x10~0x1F 多帧传输的第一帧,包含总长度
连续帧(CF) 0x20~0x2F 后续数据帧,带序列号
流控帧(FC) 0x30~0x3F 接收方告诉发送方:继续发/等一等/别发了

我记得有一次做Bootloader刷写,连续帧的序列号总是对不上,查了半天发现是流控帧的BS(块大小)设成了0,导致发送方一股脑全发出来,接收方缓冲区溢出了。这个坑,踩过一次就记住了。

🔧 实用技巧
调试网络层问题时,用CAN工具抓一下总线报文,看PCI字节的前4位就能快速判断帧类型。0x1开头是首帧,0x2开头是连续帧,0x3开头是流控帧。记住这个,排查问题快一倍。

2.4 传输层:端到端的可靠传输

传输层在UDS诊断里,其实和网络层是紧密绑定的。ISO 15765-2既管网络层也管传输层。它的核心任务就是:确保整个诊断报文完整、有序地到达对端

说白了,网络层负责“怎么拆包”,传输层负责“怎么保证拆了之后还能拼回去”。

  • 分段与重组:发送方把长报文切成多个CAN帧,接收方按序列号重组。
  • 流控机制:接收方通过流控帧告诉发送方,我的缓冲区能收多少,你发慢点。
  • 超时重传:如果发送方没收到流控帧或连续帧的确认,会超时重发。

我建议你在做刷写功能时,特别关注传输层的超时参数。有些ECU处理慢,流控帧给得晚,发送方如果超时设得太短,就会反复重发,把总线搞乱。

2.5 会话层:建立与管理诊断会话

会话层管的是“对话”本身。在UDS里,它对应的是诊断会话控制(0x10服务)。

你想想看,ECU平时在跑正常功能,不能随便让人进来诊断。会话层就是那个“门卫”——你得先敲门,说“我要进诊断模式”,ECU才会开放诊断接口。

  • 默认会话(0x01):上电后的初始状态,只允许少量诊断服务。
  • 扩展会话(0x03):允许读写数据、执行例程。
  • 编程会话(0x02):用于刷写Bootloader或应用程序。

嗯,这里要注意:不同会话之间切换,ECU可能会复位某些状态。我遇到过在扩展会话里设了DTC,一切换到编程会话,DTC就被清了。这不是bug,是规范允许的。

2.6 表示层:数据的编码与解释

表示层在UDS诊断里经常被忽略,但它其实很重要。它负责把上层的数据“翻译”成网络能理解的格式。

说白了,就是数据格式的约定。比如一个车速信号,是用uint16还是uint32?单位是km/h还是mph?字节序是大端还是小端?

  • 字节序:CAN总线通常用Motorola格式(大端),但有些ECU用Intel格式(小端)。搞混了,读出来的数据就是错的。
  • 数据类型:UDS诊断数据通常用原始值(raw value),需要查DID定义才知道物理值是多少。
  • 负响应码:0x7F + SID + NRC,表示层要能正确解析这个结构。

我见过最离谱的一次,一个工程师把车速的字节序搞反了,读出来显示3000多km/h,客户差点以为这车能飞。

2.7 应用层:UDS服务的核心

终于到了应用层。这一层就是UDS协议本身——ISO 14229-1定义的那些服务。

应用层不管数据怎么传、怎么拆包、怎么编码,它只关心一件事:诊断请求是什么,响应应该是什么

  • 诊断和通信管理:0x10(会话控制)、0x11(ECU复位)、0x28(通信控制)等。
  • 数据传输:0x22(读取数据)、0x2E(写入数据)、0x23(读取内存)等。
  • 存储数据传输:0x14(清除DTC)、0x19(读取DTC信息)等。
  • 输入输出控制:0x2F(输入输出控制)等。
  • 例程:0x31(例程控制)等。
  • 上传下载:0x34(请求下载)、0x36(传输数据)、0x37(请求上传)等。
🎯 核心理解
应用层是UDS诊断的“业务逻辑”。你写诊断代码,90%的时间都在跟应用层打交道。但底层如果没搞好,应用层再对也没用——报文都发不出去,服务怎么执行?

好了,七层模型讲完了。你可能会问:我平时写代码,真的需要每一层都关心吗?

我的建议是:应用层必须精通,网络层和传输层必须理解,物理层和数据链路层要能排查问题。至于会话层和表示层,知道它们的存在和基本作用就够了。

下一章,我们会深入应用层,从最常用的0x22服务开始,手把手教你读写ECU数据。