2. LIN总线基础

好,咱们进入第二章。这一章我打算把 LIN 诊断的规范底牌给你翻一翻。说白了,就是搞清楚 ISO 17987 到底对诊断做了哪些规定,诊断服务怎么分类,以及主节点和从节点之间是怎么一问一答的。

我个人习惯,在动手写代码之前,一定先把规范里的“游戏规则”吃透。不然你写出来的诊断栈,很可能跟别人的工具对不上话。嗯,咱们开始。

2.1 ISO 17987 与 LIN 诊断的关系

很多人一提到 LIN 诊断,第一反应就是“哦,就是那个用 0x3C 和 0x3D 的协议”。这话对,但不全对。真正定义这些 ID 和流程的,是 ISO 17987 系列标准。

ISO 17987 是 LIN 总线在汽车领域的国际标准。它把诊断相关的部分单独拎了出来,放在了 ISO 17987-4 和 ISO 17987-5 里。我记得刚入行那会儿,拿着 LIN 2.1 的规范去对诊断,发现有些细节跟 ISO 17987 对不上,后来才知道 LIN 2.1 已经被 ISO 17987 取代了。

核心要点: ISO 17987 定义了 LIN 诊断的传输层(Transport Layer),也就是怎么把一包 UDS 诊断数据拆成多帧发出去,再拼回来。它不定义 UDS 服务本身(那是 ISO 14229 的事),只定义 LIN 总线上的“快递方式”。

简单来说,ISO 17987 负责“怎么传”,ISO 14229 负责“传什么”。两者配合,才能完成一次完整的 LIN 诊断。

2.2 LIN 诊断服务分类

在 LIN 总线上,诊断服务不是随便用的。ISO 17987 和 ISO 14229 一起,把 LIN 诊断服务分成了几类。我把它整理成了一张表,你一看就明白。

分类 服务示例 说明
诊断与通信管理 10(诊断会话控制)、28(通信控制)、3E(Tester Present) 控制诊断会话状态,保持连接
数据读取 22(读取数据标识符)、23(读取内存地址) 读取 ECU 内部参数、版本号、故障码
数据写入 2E(写入数据标识符)、3D(写入内存地址) 写入配置、标定参数
故障码相关 19(读取故障码信息)、14(清除故障码) 诊断的核心,读/清 DTC
远程例程 31(例程控制) 执行 ECU 内部功能,如自检、复位
上传/下载 34(请求下载)、36(传输数据)、37(请求传输退出) 刷写固件或数据块

我的经验: 在 LIN 节点上,最常用的其实是 10、22、2E、19、14 这几个。刷写类的服务(34/36/37)在 LIN 上用得少,因为 LIN 带宽太低,刷个几百 KB 的固件能等到你怀疑人生。

2.3 诊断请求与响应机制

LIN 诊断的请求和响应,跟 CAN 诊断有很大不同。CAN 诊断是“多主”的,谁都能发请求。但 LIN 是“主从”结构,只有主节点能发起诊断请求,从节点只能被动响应。

这就引出了 LIN 诊断的两个关键 ID:

  • 0x3C(60):主节点发往从节点的诊断请求帧。
  • 0x3D(61):从节点回复给主节点的诊断响应帧。

你想想看,整个 LIN 网络上,所有诊断通信都挤在这两个 ID 里。所以,一次只能跟一个从节点对话。这就是所谓的“点对点”诊断。

2.3.1 单帧与多帧传输

LIN 诊断帧的载荷只有 8 个字节。如果诊断请求或响应超过 8 个字节,就得拆成多帧发送。ISO 17987 定义了两种帧类型:

  • 单帧(SF):数据长度 ≤ 6 字节(因为第一个字节要放长度信息)。
  • 首帧(FF):多帧传输的第一帧,包含总长度信息。
  • 连续帧(CF):后续的帧,带序号。

这里有个坑,我当初踩过。LIN 的多帧传输,不像 CAN 那样有流控制帧(FC)。LIN 的连续帧是“一发到底”的,中间不停。所以接收方必须在收到首帧后,准备好缓冲区,然后一口气收完所有连续帧。

我曾经踩过的坑: 有一次,从节点的接收缓冲区只分配了 20 字节,结果诊断仪发了个 30 字节的请求。从节点收到首帧后,发现总长度是 30,但缓冲区不够,直接丢包了。后来我加了个“长度校验”,发现缓冲区不够就回复 NRC 0x78(请求正确接收,但响应待定),然后等主节点超时重发。嗯,这算是个临时补救方案。

2.3.2 诊断请求流程

一次完整的 LIN 诊断请求,大概是这样的:

  1. 主节点发送诊断请求:通过 0x3C 发送单帧或多帧。
  2. 从节点接收并处理:从节点解析请求,执行对应的 UDS 服务。
  3. 从节点发送诊断响应:通过 0x3D 回复单帧或多帧。
  4. 主节点接收响应:主节点解析响应,完成一次诊断事务。

这里要注意,LIN 诊断是“同步”的。主节点发完请求后,必须等待从节点的响应,才能发下一个请求。不能像 CAN 那样“发完就不管了”。

2.4 知识体系结构图

下面这张 SVG 图,把本章的核心逻辑串起来了。你可以把它当作一张“地图”,随时回来对照。

LIN诊断规范知识体系 LIN诊断规范知识体系 ISO 17987 传输层定义:单帧/多帧/流控制 诊断服务分类(UDS子集) 请求与响应机制(0x3C/0x3D) 10/22/2E/19/14/31等 主节点发请求 → 从节点响应 LIN诊断功能开发实战基础

2.5 诊断响应中的 NRC

说到响应,就不得不提 NRC(Negative Response Code,否定响应码)。当从节点无法执行请求时,它不会沉默,而是回复一个否定响应。

常见的 LIN 诊断 NRC 有:

  • 0x11:服务不支持。比如你发了个 31 服务,但节点没实现。
  • 0x12:子功能不支持。服务支持,但子功能不对。
  • 0x13:报文长度或格式错误。这个我遇到过,多帧传输时连续帧序号错了,就会报这个。
  • 0x22:条件不满足。比如不在正确的诊断会话里。
  • 0x31:请求超出范围。比如读一个不存在的 DID。
  • 0x78:请求正确接收,但响应待定。用于告诉主节点“我收到了,但处理需要时间,别急着超时”。

一个小技巧: 调试时,如果发现诊断仪一直超时,先抓一下 LIN 总线上的 0x3D 帧。看看从节点有没有回复 NRC。很多时候,问题出在从节点报了 0x22 或 0x31,但诊断仪没正确处理。

2.6 总结一下

这一章,我们把 LIN 诊断的规范骨架搭起来了。ISO 17987 定义了传输层,ISO 14229 定义了服务内容。诊断服务分成了六大类,最常用的是会话控制、数据读写和故障码相关。请求和响应通过 0x3C 和 0x3D 进行,支持单帧和多帧传输。

嗯,这些概念是后面所有开发工作的基础。你理解了这些,再看后面的代码和配置,就会觉得顺理成章了。