2、LIN总线协议基础:帧结构与帧类型

好,咱们今天聊聊LIN总线的帧结构。说实话,刚接触LIN的时候,我觉得它比CAN简单太多了。但用久了才发现,简单归简单,坑也不少。

LIN总线上的通信,说白了就是主节点发号施令,从节点乖乖响应。每个消息就是一帧数据。那这一帧里到底装了些什么?我带你拆开看看。

2.1 帧结构:六个场,一个都不能少

一个完整的LIN帧,由六个部分组成。我习惯把它们分成“头”和“响应”两段。主节点负责发“头”,从节点负责发“响应”。

场名称 字节数 发送方 说明
同步间隔场 至少13位显性 主节点 唤醒总线,标识帧开始
同步场 1字节 (0x55) 主节点 从节点用它校准时钟
标识符场 1字节 主节点 决定谁来响应、数据长度
数据场 1~8字节 发送节点 真正的数据内容
校验和场 1字节 发送节点 检查数据是否传错

2.1.1 同步间隔场

这是帧的“起跑线”。主节点会把总线拉低至少13个位时间。为什么是13?因为正常的字节传输最多也就10个位(1起始+8数据+1停止),13个连续的显性位,从节点一看就知道:哦,新的一帧开始了。

我曾经遇到过一个坑:某个从节点的晶振偏差太大,13位的间隔它愣是没识别出来。后来我查了规范,建议间隔场至少18位才保险。嗯,从此我设计时都按18位来。

2.1.2 同步场

同步场固定是 0x55,也就是二进制 01010101。为什么选这个值?你想想看,它刚好是高低电平交替,从节点可以用它来测量主节点的位时间,校准自己的时钟。

说白了,这就是一个“时钟校准信号”。没有它,从节点可能因为晶振偏差而读错数据。我个人习惯在调试时先抓一下同步场的波形,看看从节点有没有正确同步。

2.1.3 标识符场

标识符场只有1个字节,但信息量不小。它包含:

  • 6位ID:取值范围0~63,决定消息的身份
  • 2位奇偶校验:保证ID传输正确

这里有个关键点:ID不仅决定了消息是谁的,还隐含了数据长度。比如ID 0x00~0x3F,每个ID都对应一个固定的数据字节数(2、4或8字节)。这个映射关系在LDF文件里定义好了。

重点:标识符场里的奇偶校验是硬件自动计算的,你不需要手动处理。但如果你用软件模拟LIN主节点,就得自己算一下。

2.1.4 数据场

数据场就是真正要传的信息了。1到8个字节,具体长度由ID决定。比如车门模块的ID可能只传2个字节(状态+校验),而车窗模块可能要传4个字节(位置、速度、电流、温度)。

我在项目中遇到过一个问题:某个从节点总是丢数据。查了半天,发现是数据场发送时,字节间的间隔太长了。LIN规范要求字节间间隔不能超过一个位时间。嗯,这个细节很容易被忽略。

2.1.5 校验和场

校验和分两种:经典校验和(Classic Checksum)和增强校验和(Enhanced Checksum)。

  • 经典校验和:只对数据场做校验
  • 增强校验和:对数据场+标识符场一起做校验

LIN 2.0以后,诊断帧必须用增强校验和。其他帧可以选。我建议统一用增强校验和,省得后面出问题还要排查。

小技巧:校验和的计算方法是:把所有字节加起来,取反,再取低8位。你可以用C语言写个函数,几行代码就搞定了。

2.2 帧类型:四种角色,各司其职

LIN总线定义了四种帧类型。说实话,日常开发中用得最多的就是无条件帧和诊断帧。事件触发帧和偶发帧,我做了这么多年项目,也就用过几次。

2.2.1 无条件帧

这是最基础的帧类型。主节点发出帧头,不管有没有从节点响应,它都会发。从节点根据ID判断:如果ID是自己的,就乖乖发响应。

举个例子:车门状态帧,ID=0x10,数据长度2字节。主节点每隔10ms发一次这个帧头,车门模块收到后,就把门锁状态、车窗位置发回来。

我习惯把所有周期性信号都用无条件帧实现。简单、可靠、好调试。

2.2.2 事件触发帧

这个就有点意思了。它用于多个从节点共享同一个ID的场景。平时主节点不发这个帧,只有当某个从节点有事件发生时,它才会主动请求。

但有个问题:如果两个从节点同时响应,就会冲突。所以事件触发帧的数据场里,第一个字节必须是发送节点的ID(从节点ID,不是消息ID)。主节点收到后,就知道是谁发的了。

注意:事件触发帧的冲突概率虽然低,但一旦发生,数据就丢了。所以关键信号别用事件触发帧,用无条件帧更稳妥。

2.2.3 偶发帧

偶发帧,说白了就是“有条件才发的无条件帧”。它有一个固定的调度表,但只有当数据发生变化时,才真正发送。

比如温度传感器,温度变化很慢,没必要每10ms发一次。用偶发帧,只有温度变化超过1度时才发。这样能节省总线带宽。

我记得有一次,客户要求降低总线负载率。我把几个周期性信号改成偶发帧,负载率直接从40%降到了15%。效果立竿见影。

2.2.4 诊断帧

诊断帧是LIN总线的“医生”。它使用固定的ID:

  • 主节点请求帧:ID=0x3C,主节点发
  • 从节点响应帧:ID=0x3D,从节点发

诊断帧的数据场固定8个字节,格式遵循ISO 15765-2(也就是UDS on LIN)。比如读取故障码、写入配置参数,都通过诊断帧完成。

我在项目中最常用诊断帧做两件事:一是产线终检时刷写配置参数,二是售后排查问题时读取故障码。嗯,诊断帧真的是开发调试的利器。

2.3 避坑指南

最后分享几个我踩过的坑:

  • 同步间隔场长度:别卡着13位的下限,留点余量,用18位以上
  • 校验和类型:统一用增强校验和,别混用
  • 事件触发帧:别用于关键信号,冲突丢数据是常态
  • 诊断帧:记得用增强校验和,否则从节点不认

好了,这一章的内容就到这里。下一章我们聊聊LIN的调度表,看看主节点是怎么安排这些帧的发送顺序的。