第2章:UDS物理层与数据链路层

2.1 CAN总线基础——诊断的“高速公路”

做UDS诊断,说白了就是在车上跑数据。数据怎么跑?绝大多数情况下,靠的就是CAN总线。我个人习惯把CAN总线想象成一条高速公路,ECU就是路上的车,诊断仪就是调度中心。车和调度中心之间怎么通信?靠的就是CAN帧。

我记得刚入行那会儿,有个老工程师跟我说:“搞UDS,先搞懂CAN。CAN搞不懂,诊断就是空中楼阁。”这话一点不假。CAN总线是差分信号传输,两根线——CAN_H和CAN_L,电压差决定逻辑0和1。逻辑0叫显性位,逻辑1叫隐性位。显性位能覆盖隐性位,这就是总线仲裁的基础。

你想想看,为什么CAN能抗干扰?因为差分信号。两根线绞在一起,外界噪声同时作用在两根线上,电压差不变。嗯,这个设计确实聪明。

2.2 CAN帧结构——数据怎么装车

CAN帧有几种类型?数据帧、远程帧、错误帧、过载帧。我们做诊断,最关心的是数据帧。数据帧又分标准帧和扩展帧,区别在于ID长度。标准帧11位ID,扩展帧29位ID。

来看一个标准数据帧的结构:

SOF | 11位ID | RTR | IDE | r0 | DLC | 数据段(0-8字节) | CRC | ACK | EOF

这里有几个关键点:

  • SOF(帧起始):一个显性位,告诉总线“我要发数据了”。
  • ID(标识符):决定优先级。ID越小,优先级越高。我在项目中遇到过,两个ECU同时发数据,ID小的那个抢到总线,另一个自动退让。
  • DLC(数据长度码):表示数据段有几个字节。诊断报文通常用8字节,但DLC可以设成0到8。
  • 数据段:0到8字节。UDS诊断报文就塞在这里面。
小技巧: 我个人习惯把CAN帧的数据段叫做“信封”,UDS报文就是信。信封大小固定8字节,信的内容可能只有3个字节,剩下的填0或者填充字节。别小看这个填充,有些工具会检查填充值,不规范会被拒收。

2.3 CAN-ID分配策略——谁是谁的“门牌号”

CAN-ID就像门牌号。诊断仪发请求,ECU回响应,门牌号不能乱。怎么分配?行业里有几种常见做法:

ID范围 用途 例子
0x700 - 0x7FF 诊断报文(标准帧) 0x7DF(功能寻址)
0x18DA00F1 - 0x18DA00FF 诊断报文(扩展帧) 0x18DA00F1(物理寻址)
其他ID 普通CAN报文 车速、转速等

为什么诊断ID要单独划一个范围?说白了,就是为了让诊断报文和普通报文互不干扰。我曾经见过一个项目,诊断ID和普通ID混在一起,结果诊断仪发个请求,好几个ECU都响应,乱成一锅粥。嗯,后来花了三天才把ID重新分配好。

避坑指南: 我曾经犯过一个错——把诊断ID设得太小,结果和优先级高的报文冲突。诊断请求发不出去,ECU死活没反应。后来查了半天,发现是ID被抢了。记住:诊断ID一般用0x700以上,别和动力系统报文抢道。

2.4 诊断物理寻址与功能寻址——点对点 vs 广播

物理寻址和功能寻址,是UDS诊断里最基础的概念。我刚开始学的时候,总觉得这两个词绕口。说白了:

  • 物理寻址:点对点。诊断仪发给某个特定的ECU。比如发到0x7E0(发动机ECU),只有发动机ECU会响应。
  • 功能寻址:广播。诊断仪发给一组ECU。比如发到0x7DF,所有支持功能寻址的ECU都会响应。

你想想看,什么时候用物理寻址?刷写单个ECU的时候。什么时候用功能寻址?做网络唤醒、读取所有ECU的故障码的时候。我记得有一次,客户要求用功能寻址同时读取10个ECU的版本号,结果总线负载瞬间飙升,差点把CAN总线搞崩。后来我建议分批次读,每次读3个,问题就解决了。

关键区别: 物理寻址的响应是“一对一”,功能寻址的响应是“一对多”。功能寻址的响应帧,ECU会用物理寻址回,避免总线冲突。这个设计很巧妙,你品,你细品。

2.5 实战中的ID分配策略

在实际项目中,ID分配不是随便写的。我一般遵循这几个原则:

  1. 诊断ID和普通ID分开:别混在一起,否则诊断工具解析报文时会疯掉。
  2. 物理寻址ID唯一:每个ECU一个物理请求ID和一个物理响应ID。比如发动机ECU,请求ID是0x7E0,响应ID是0x7E8。
  3. 功能寻址ID统一:所有ECU共享一个功能请求ID(0x7DF),但响应ID各自不同。
  4. 预留扩展空间:我习惯在ID表里留几个空位,万一以后加ECU,不用重新分配。

举个例子,一个典型的CAN诊断ID表:

ECU名称       物理请求ID   物理响应ID   功能请求ID
发动机ECU     0x7E0       0x7E8       0x7DF
变速箱ECU     0x7E1       0x7E9       0x7DF
ABS ECU       0x7E2       0x7EA       0x7DF
网关          0x7E3       0x7EB       0x7DF

注意看,功能请求ID全是0x7DF,但响应ID各不相同。为什么?因为功能寻址时,所有ECU同时响应,如果响应ID一样,总线就打架了。嗯,这个细节很多人会忽略。

个人经验: 我建议在项目初期就定好ID分配文档,让所有供应商遵守。否则后期联调时,你会发现A供应商的ECU用0x7E0,B供应商也用0x7E0,两个ECU抢同一个ID,诊断仪根本分不清谁是谁。别问我怎么知道的,都是泪。

2.6 总结

这一章我们聊了CAN总线基础、帧结构、ID分配策略,还有物理寻址和功能寻址的区别。说白了,物理层和数据链路层就是UDS诊断的“地基”。地基不稳,上层协议再牛也白搭。

我个人觉得,搞UDS诊断,先花一周时间把CAN总线吃透,后面会省很多事。下一章我们聊UDS的会话层——如何建立诊断会话、如何切换模式。到时候你会发现,物理层搞懂了,会话层就是水到渠成的事。

嗯,今天就到这儿。记住:CAN-ID别乱写,物理寻址和功能寻址别搞混。这是诊断的命根子。