4、LIN总线调度表:调度表的概念、主任务与从任务、帧时隙分配、调度表的配置方法

好,咱们今天聊聊LIN总线里一个非常核心的概念——调度表。

说实话,很多刚接触LIN的朋友,总觉得它比CAN简单太多,不就是个低速串口嘛。但实际项目做多了你会发现,调度表才是LIN总线的灵魂。没有它,整个网络就是一团乱麻。

4.1 调度表的概念

什么叫调度表?说白了,就是一张时间表

它告诉总线上的每个节点:
什么时间该谁说话,说什么内容,说多久。

我打个比方。你想想看,一个班级里上课,老师(主节点)手里有张课程表。上午8点语文,8点45数学,9点30英语……每个时间段,只有一位老师在上面讲,其他人都听着。调度表就是LIN总线的“课程表”。

在LIN协议里,调度表是一个预定义的时间序列。它由一系列帧时隙组成,每个时隙指定了要发送哪一帧报文。整个总线就按照这个节奏,一帧一帧地跑下去。

核心要点:调度表是静态配置的,在系统设计阶段就定好了。运行时不会动态改变(除非切换到另一个调度表)。

4.2 主任务与从任务

LIN总线是主从架构。这个“主”和“从”,在调度表的执行过程中,扮演的角色完全不同。

主任务(Master Task)
只有主节点才有。它的职责是——发报头

报头包括:同步间隔场、同步场、标识符场。主任务按照调度表的时间安排,准时把报头发出去。然后呢?它就等着。

从任务(Slave Task)
所有节点(包括主节点自己)都有。它的职责是——响应报头

每个从任务收到报头后,解析标识符。如果发现自己被分配了发送这个帧,就发数据;如果发现自己被分配了接收,就默默收数据;如果跟自己无关,就忽略。

我个人的经验:很多新手会搞混一个点——主节点既做主任务,也做从任务。主任务发报头,从任务发数据。所以主节点发一帧数据,实际上是“主任务先发报头,然后从任务(主节点自己的从任务部分)再发数据”。这两个动作是分开的。

为什么会这样设计?因为LIN协议希望所有节点的行为统一。主节点发报头时,它并不知道谁会响应。它只是按照调度表,把报头发出去。至于谁响应,那是从任务根据标识符自己决定的。

4.3 帧时隙分配

帧时隙,就是调度表里的一个“格子”。每个格子包含:

  • 帧标识符:要发送哪一帧
  • 帧类型:无条件帧、事件触发帧、偶发帧、诊断帧
  • 时隙长度:这个时隙占多少时间

时隙长度怎么算?我一般用这个公式:

时隙长度 = 报头长度 + 响应长度 + 帧间空间

其中:

  • 报头长度:固定约13位(同步间隔+同步场+标识符场)
  • 响应长度:取决于数据场字节数(1~8字节)
  • 帧间空间:一般留1~2位的余量

举个例子。假设总线波特率是20kbps,一帧带4字节数据的报文:

报头:13位
响应:4字节数据 + 1字节校验和 = 50位
帧间空间:2位
总位数:13 + 50 + 2 = 65位
时隙长度:65 / 20000 = 3.25ms

嗯,这里要注意。实际项目中,我习惯把时隙长度向上取整到整数毫秒,再额外加1~2ms的余量。为什么?因为晶振有误差,从节点处理也有延迟。我曾经在一个项目里,时隙算得刚刚好,结果量产时发现部分节点偶尔丢帧。查了两天才发现,是时隙余量不够。

避坑指南:我曾经吃过一次亏——调度表里两个连续时隙之间没有留足间隔。结果从节点处理上一帧还没完成,下一帧的报头就来了。从节点直接忽略,导致丢帧。所以,时隙之间至少留1ms的间隔,这是血的教训。

4.4 调度表的配置方法

调度表的配置,通常在LDF(LIN Description File)里完成。LDF是LIN总线的“宪法”,所有节点都得遵守。

一个典型的调度表配置,长这样:

Schedule_tables {
  // 主调度表:正常运行时的调度
  MainSchedule {
    // 时隙1:发送车门状态帧
    LINFrameID = 0x01, Delay = 10ms;
    // 时隙2:发送车窗状态帧
    LINFrameID = 0x02, Delay = 10ms;
    // 时隙3:发送灯光状态帧
    LINFrameID = 0x03, Delay = 10ms;
    // 时隙4:发送传感器数据帧
    LINFrameID = 0x04, Delay = 20ms;
  }

  // 诊断调度表:诊断模式时使用
  DiagnosticSchedule {
    // 时隙1:诊断请求
    LINFrameID = 0x3C, Delay = 50ms;
    // 时隙2:诊断响应
    LINFrameID = 0x3D, Delay = 50ms;
  }
}

配置时,有几个关键点:

  1. 帧的顺序:重要帧放前面,次要帧放后面。比如安全相关的帧,优先级要高。
  2. 时隙的周期:有些帧需要10ms发一次,有些20ms,有些甚至100ms。根据实时性要求来定。
  3. 调度表的切换:正常运行用MainSchedule,进入诊断模式切换到DiagnosticSchedule。切换时机由主节点控制。

我建议:刚开始设计调度表时,先画一张时间轴图。把每个时隙画在时间轴上,看看有没有重叠,有没有空闲时间太长。我习惯用Excel画,简单直观。等确认没问题了,再写到LDF里。

最后说一句。调度表配置好了,不代表万事大吉。一定要在实车上跑一跑,用示波器抓一下总线波形,看看实际时序跟设计是否一致。我见过太多“纸上算得好好的,一跑就乱套”的案例了。

嗯,调度表这块,就先讲到这里。下一章咱们聊聊LIN的帧类型——无条件帧、事件触发帧、偶发帧,这些在实际项目中怎么选、怎么用。