2. UDS协议栈架构:应用层、会话层、网络层、数据链路层、物理层详解

好,咱们进入第二章。这一章我打算把UDS的协议栈架构彻底拆开来讲。

很多工程师刚接触UDS时,总觉得它就是个发命令、收响应的东西。其实不然。UDS协议栈是分层的,每一层各司其职。你想想看,如果所有逻辑都揉在一起,出了问题你根本不知道是哪个环节的锅。

我个人习惯把UDS协议栈比作一个快递系统。应用层是寄件人写的快递单,会话层是快递员的沟通流程,网络层是分拣中心,数据链路层是运输车辆,物理层就是那条高速公路。嗯,这么一讲是不是清晰多了?

2.1 应用层(Application Layer)

应用层是离我们工程师最近的一层。说白了,你写的诊断服务代码,比如读取故障码、写入数据、执行例程,全都在这一层。

UDS的应用层定义了一套标准服务,也就是我们常说的SID(Service Identifier)。比如0x10(诊断会话控制)、0x22(读取数据)、0x2E(写入数据)、0x19(读取故障码)等等。每个SID后面跟着子功能(Sub-function)和具体参数。

我记得刚入行那会儿,有个同事死活搞不懂为什么发0x22读数据时,有时候返回的是肯定响应,有时候是否定响应。其实很简单——应用层只管你的请求格式对不对,至于能不能读到数据,那是下层的事。

应用层核心要点:

  • 定义诊断服务请求和响应的格式
  • 每个服务有唯一的SID
  • 响应分为肯定响应(Positive Response)和否定响应(Negative Response)
  • 否定响应码(NRC)是调试的关键线索

我的经验:调试应用层问题时,先确认你发的请求格式对不对。我曾经花了一整天查一个0x22读不到数据的bug,最后发现是数据长度多写了一个字节。应用层对格式要求非常严格,多一个字节都不行。

2.2 会话层(Session Layer)

会话层,很多人容易忽略它。但我要说,这一层是UDS协议栈的“交通警察”。

UDS定义了三种会话模式:默认会话(Default Session)、编程会话(Programming Session)和扩展会话(Extended Session)。为什么要有会话?因为ECU不能让你随便什么操作都做。比如刷写程序这种高危操作,必须在编程会话下才能执行。

会话层负责管理这些会话的切换、超时和保持。你发送0x10服务,就是在跟会话层打交道。会话层收到请求后,会检查当前会话是否允许切换到目标会话。如果不允许,直接给你扔一个否定响应。

这里有个坑,我必须要说。默认会话是有超时时间的。如果你在扩展会话里待着,超过一段时间没发任何请求,ECU会自动跳回默认会话。我曾经在测试时,一边打电话一边调试,结果回来发现会话已经超时了,所有诊断请求都被拒绝。嗯,从那以后我养成了习惯——长时间调试时,定时发个0x3E(Tester Present)保持会话。

注意事项:

  • 默认会话超时时间通常为5秒(具体看OEM定义)
  • 编程会话和扩展会话的超时时间可能更长
  • 0x3E服务是保持会话的“保命符”
  • 某些安全相关的服务只能在特定会话下执行

2.3 网络层(Network Layer)

网络层,在UDS协议里通常指的是ISO 15765-2(也叫CAN TP)。这一层负责把应用层的大数据包拆成CAN总线能传输的小帧,再在接收端拼回去。

为什么需要网络层?因为CAN总线的数据场最多只能传8个字节。如果你的诊断请求超过8个字节,比如要写入一段较长的数据,就必须拆包发送。网络层就是干这个活的。

网络层定义了四种帧类型:单帧(SF)、首帧(FF)、连续帧(CF)和流控帧(FC)。单帧用于不超过8字节的短消息。超过8字节的,先发一个首帧告诉对方“我要发这么多数据”,然后发连续帧,中间用流控帧控制节奏。

我记得有个项目,ECU的接收缓冲区设置得太小,导致连续帧发得太快时丢包了。查了好久才发现是流控帧里的块大小(Block Size)和最小间隔时间(STmin)没配好。后来我把STmin设成了10毫秒,问题就解决了。

网络层关键参数:

参数 说明 典型值
BS(Block Size) 连续帧的最大数量 0(无限制)或1-255
STmin(Separation Time minimum) 连续帧之间的最小间隔 0-127(毫秒)或0xF1-0xF9(微秒)
CAN ID 诊断请求和响应的标识符 通常为0x7DF(请求)和0x7E8(响应)

2.4 数据链路层(Data Link Layer)

数据链路层,说白了就是CAN控制器干的事。它负责把网络层传下来的数据帧,转换成CAN总线上的电平信号。

这一层主要处理CAN帧的格式:标准帧(11位ID)还是扩展帧(29位ID),数据场长度,CRC校验,应答位等等。UDS诊断通常使用标准帧,但有些OEM会用扩展帧,这个要看具体规范。

数据链路层还有一个重要功能——错误检测。CAN总线有很强的错误检测机制,比如位错误、填充错误、CRC错误、格式错误和应答错误。如果数据链路层检测到错误,会自动重发。但如果错误太多,总线会进入被动错误状态甚至总线关闭状态。

我曾经遇到过一辆车,诊断通信时断时续。用示波器抓了CAN总线波形,发现总线上有大量的错误帧。最后查出来是某个节点的CAN收发器坏了,导致总线电平异常。换了收发器后,一切恢复正常。

调试技巧:如果诊断通信不稳定,先别急着查应用层。用CAN分析仪看看总线上有没有错误帧。数据链路层的问题往往表现为“时好时坏”,非常隐蔽。

2.5 物理层(Physical Layer)

物理层,就是实实在在的硬件了。CAN收发器、线束、连接器、终端电阻,全都在这一层。

物理层决定了信号的电气特性:电压电平、位时序、传输速率。UDS诊断通常使用CAN总线,速率从125 kbps到1 Mbps不等。最常见的诊断速率是500 kbps。

物理层的问题往往是最难排查的。比如线束接触不良、终端电阻缺失、共模干扰等等。这些问题不会直接报错,但会导致通信不稳定、丢帧、甚至完全无法通信。

我记得有一次去现场支持,客户的诊断仪死活连不上ECU。我检查了所有软件配置,都没问题。最后拿万用表一量,发现CAN_H和CAN_L之间的电阻只有30欧姆——终端电阻应该是120欧姆才对。原来是客户在总线上并联了太多节点,导致等效电阻太小。去掉多余的终端电阻后,通信就正常了。

物理层常见问题:

  • 终端电阻缺失或错误(标准值为120欧姆)
  • CAN_H和CAN_L短路或对地短路
  • 线束过长导致信号衰减
  • 共模干扰导致位错误
  • 收发器供电异常

2.6 各层之间的协作

讲完了每一层,咱们来看看它们是怎么协作的。你发送一个诊断请求,流程是这样的:

  1. 应用层:组装请求报文,比如0x22 F1 90(读取VIN码)
  2. 会话层:检查当前会话是否允许这个操作
  3. 网络层:如果数据超过8字节,拆成多帧;否则直接打包
  4. 数据链路层:加上CAN帧头、CRC等,准备发送
  5. 物理层:把数字信号变成电平信号,发到总线上

接收端反过来:物理层收到电平信号,数据链路层解析出CAN帧,网络层拼回完整报文,会话层检查会话状态,应用层执行服务并生成响应。

你看,每一层各司其职,互不干扰。这就是分层设计的好处——哪一层出了问题,就只修哪一层,不用动其他层。

总结一下:UDS协议栈的五层架构,从应用层到物理层,每一层都有明确的职责。应用层管“做什么”,会话层管“什么时候能做”,网络层管“怎么传”,数据链路层管“传得对不对”,物理层管“传得通不通”。搞清楚了这五层,你就能快速定位诊断通信中的任何问题。

下一章,咱们会深入讲解应用层的具体服务。到时候我会结合项目中的实际案例,把每个服务的用法和坑都讲清楚。嗯,敬请期待。