2、诊断协议入门:诊断协议概述、UDS on LIN、诊断请求与响应、诊断会话控制

好,咱们正式开始聊诊断协议。说实话,很多刚入行的工程师一听到「诊断」两个字,就觉得是搞CAN、搞UDS那帮人的事。LIN这边嘛,不就是控制个车窗、调个后视镜?能有什么诊断好做的?

嗯,我以前也这么想。直到有一次,我在一个项目里遇到个怪问题——LIN从节点偶尔不响应,但重新上电又好了。查了三天,最后发现是诊断会话没切对,节点卡在某个状态里出不来。从那以后,我再也不敢小看LIN诊断了。

2.1 诊断协议到底是个啥?

说白了,诊断协议就是一套「车规级」的沟通规则。它让ECU(电子控制单元)之间、或者诊断仪和ECU之间,能互相问问题、下指令。

你想想看,一辆车上有几十个ECU。哪个出了毛病,总不能拆下来用万用表一个个量吧?诊断协议就是干这个的——通过总线发几个报文,就能知道这个节点的工作状态、故障码、甚至能远程刷写软件。

我个人习惯把诊断协议分成两类:

  • 基于CAN的UDS:这是主流,功能强大,但协议栈复杂,资源开销大。
  • 基于LIN的UDS:这是简化版,针对低速、低成本节点,但核心思想是一样的。

咱们这门课,重点就是后者。

2.2 UDS on LIN——瘦身版的诊断

UDS(统一诊断服务)原本是为CAN总线设计的。但LIN总线带宽低、节点成本敏感,直接照搬肯定不行。所以ISO 17987(LIN协议标准)里专门定义了一套针对LIN的诊断规范。

我给大家总结几个关键点:

  • 主从架构不变:诊断请求只能由主节点发起,从节点只能响应。这一点和CAN不一样,CAN是任意节点都能发诊断请求。
  • 传输层简化:CAN的UDS有复杂的传输层(比如多帧传输),LIN这边就简单多了——单帧搞定大部分诊断服务。实在需要多帧的,也有,但用得少。
  • 诊断ID固定:LIN的诊断请求和响应,使用固定的NAD(节点地址)和诊断ID。具体来说,主节点发请求用0x3C,从节点响应用0x3D。这个大家记住就行,项目里天天见。

重要提醒:LIN诊断报文和普通LIN报文走的是同一个总线,但帧ID不同。千万别搞混了。我见过有人把诊断报文当成普通信号发出去,结果从节点直接不理你。

2.3 诊断请求与响应——一问一答的艺术

诊断通信的基本模式,就是「请求-响应」。主节点发一个请求帧,从节点回一个响应帧。就这么简单。

但这里有个坑:响应不是必须的。比如主节点发了一个「诊断会话控制」请求,从节点如果没收到,或者收到了但处理不了,它可以选择不响应。那主节点怎么办?等超时呗。

来看一个典型的诊断请求报文结构:

// 诊断请求(主节点发送,ID=0x3C)
Byte 0: 保护ID (PCI) + 从节点地址 (NAD)
Byte 1: 服务标识符 (SID),比如 0x10 表示诊断会话控制
Byte 2...N: 服务参数

// 诊断响应(从节点发送,ID=0x3D)
Byte 0: 保护ID (PCI) + 主节点地址 (NAD)
Byte 1: 响应服务标识符 (RSID) = SID + 0x40
Byte 2...N: 响应数据

嗯,这里要注意:响应的SID是请求SID加上0x40。比如请求是0x10,响应就是0x50。这是UDS的通用规则,LIN也不例外。

我曾经在一个项目里,从节点死活不回响应。查了半天,发现是从节点固件里把RSID算错了,加成了0x20。你说冤不冤?

2.4 诊断会话控制——节点的「工作模式」

诊断会话控制(服务ID 0x10)是诊断协议里最基础、也最重要的服务。它决定了ECU当前处于什么工作模式。

LIN节点通常支持以下几种会话:

会话类型 SID 说明
默认会话 0x01 上电后的默认状态,只响应基本诊断服务
编程会话 0x02 用于刷写软件,允许更高级的访问
扩展诊断会话 0x03 用于更详细的诊断,比如读取特定数据

为什么要有会话控制?说白了,就是安全考虑。你想想看,如果随便一个诊断仪都能刷写ECU的软件,那车还不得乱套?所以默认会话下,很多危险操作(比如写Flash)是被禁止的。只有切换到编程会话,并且通过了安全访问(服务0x27),才能执行这些操作。

避坑指南:我曾经遇到过一个案例,从节点在编程会话下刷写固件,刷到一半主节点突然发了个「默认会话」请求。结果从节点直接退出编程模式,固件刷了一半,节点变砖了。所以,在关键操作期间,一定要锁住会话状态,不允许切换。

会话切换的流程也很简单:

  1. 主节点发0x10请求,带上目标会话ID。
  2. 从节点收到后,检查是否支持该会话。
  3. 如果支持,切换会话,并回一个正响应(0x50 + 会话ID)。
  4. 如果不支持,回一个负响应(0x7F + 0x10 + 错误码)。

这里有个细节:会话是有超时时间的。比如扩展诊断会话,如果一段时间内没有收到任何诊断请求,节点会自动切回默认会话。这个超时时间,ISO标准里建议是5秒,但具体项目可以自己定义。我个人习惯设成10秒,给诊断仪留点操作余量。

2.5 小结一下

诊断协议入门,其实就三件事:

  • 知道诊断是干嘛的(问问题、下指令)
  • 知道LIN上的UDS长什么样(简化版,ID固定)
  • 知道会话控制怎么玩(切换模式,注意安全)

下一章,咱们会深入聊具体的诊断服务,比如读取故障码(0x19)、读取数据(0x22)这些。到时候我会拿实际项目里的报文,一条一条给大家拆解。嗯,敬请期待。