4、LIN主节点架构:主节点功能框图、主任务与从任务、调度表概念、主节点硬件选型(MCU+收发器)

好,咱们进入正题。这一章讲的是主节点的骨架——架构。

很多人一上来就写代码,结果发现总线跑不起来。为什么?因为没搞明白主节点到底在干什么。说白了,主节点就是整个LIN网络的“指挥官”。它不发话,从节点只能干等着。

4.1 主节点功能框图

先看一张图,我脑子里已经画好了。主节点内部其实就两大块:MCULIN收发器

MCU负责跑协议栈、处理调度表、生成报文头。收发器负责把MCU的UART信号转成总线上的电平信号。中间连着一根线,叫TXD和RXD。

嗯,这里要注意:收发器不是可选项,是必需品。MCU的UART引脚直接怼到总线上?不行,电平不匹配,而且没有总线唤醒、故障保护这些功能。

主节点功能框图(文字描述)

+-------------------+      TXD/RXD      +-------------------+
|      MCU          | <----------------> |   LIN收发器       |
|  - 调度表引擎     |                    |  - 电平转换       |
|  - 主任务/从任务  |                    |  - 总线唤醒       |
|  - UART外设       |                    |  - 故障检测       |
+-------------------+                    +-------------------+
                          |
                          | LIN总线(单线)
                          v
                    +-----------+
                    | 从节点1   |
                    +-----------+
                    +-----------+
                    | 从节点2   |
                    +-----------+

我在项目中遇到过有人把收发器省了,直接用MCU的IO口模拟。结果呢?通信距离超过1米就丢包,抗干扰能力几乎为零。所以,别省这个钱。

4.2 主任务与从任务

一个主节点内部,其实跑着两个“角色”:主任务从任务

你想想看,主节点既要发调度表,又要响应自己的从任务。这两个任务怎么共存?

主任务负责:

  • 按照调度表,定时发送报文头(同步间隔+同步场+标识符场)
  • 监控总线状态,处理错误
  • 管理唤醒和休眠

从任务负责:

  • 接收主任务发来的报文头
  • 根据标识符判断:是自己要发的,还是自己要收的
  • 如果是自己发,就填充数据场和校验场
  • 如果是自己收,就读取数据

我个人习惯把主任务放在定时器中断里跑,从任务放在主循环里轮询。为什么?因为主任务对时间精度要求高,中断里跑最稳。从任务可以慢一点,没关系。

避坑指南: 我曾经在一个项目里把主任务和从任务都放在中断里,结果中断嵌套导致调度表乱了。后来改成主任务中断+从任务轮询,问题解决。记住:中断里只做最紧急的事

4.3 调度表概念

调度表,说白了就是一张“时间表”。它告诉主节点:什么时间该发哪个报文头。

举个例子,一个简单的调度表:

// 调度表条目结构
typedef struct {
    uint8_t  frame_id;    // 报文标识符(0x00-0x3F)
    uint16_t slot_time;   // 时隙长度(单位:位时间)
} schedule_entry_t;

// 调度表定义
const schedule_entry_t schedule_table[] = {
    {0x01, 1000},   // 先发ID=0x01的报文,时隙1000位时间
    {0x02, 1000},   // 再发ID=0x02
    {0x03, 500},    // ID=0x03,时隙500位时间
    {0x01, 1000},   // 循环回来,再发ID=0x01
};

调度表可以循环执行,也可以有条件跳转。比如:

  • 无条件循环:一直按顺序发,适合周期性数据
  • 条件跳转:比如检测到某个事件,跳到另一个调度表
  • 单次执行:发完就停,适合诊断或配置

我记得有一次调试,发现某个从节点总是丢数据。查了半天,原来是调度表的时隙设得太短,从节点来不及处理。后来把时隙从500位时间改成800位时间,问题消失。

注意: 调度表的时隙长度,必须大于报文传输时间 + 从节点处理时间。否则总线会乱套。一般建议留20%的余量。

4.4 主节点硬件选型(MCU+收发器)

选型这件事,我踩过不少坑。直接说结论:

MCU选型要点

  • UART数量:至少1个,最好带LIN硬件支持(自动生成同步间隔)
  • 定时器:至少1个16位定时器,用于调度表计时
  • Flash/RAM:调度表不大,8KB Flash + 1KB RAM足够
  • 工作电压:3.3V或5V,看收发器匹配

我个人常用的MCU:

型号 内核 UART LIN硬件支持 价格(批量)
STM32F042 Cortex-M0 2个 约$0.8
NXP S32K116 Cortex-M0+ 3个 约$1.2
Microchip PIC18F 8位 1个 否(需软件模拟) 约$0.5

收发器选型要点

  • 兼容标准:必须符合LIN 2.x或ISO 17987
  • 工作电压:通常12V(车载),也有5V版本
  • 唤醒功能:支持本地唤醒和总线唤醒
  • 保护功能:过温保护、短路保护、地偏移保护

常用的收发器:

型号 电压 速率 特点
TJA1020 12V 20kbps 经典款,稳定
MCP2003 12V 20kbps 带休眠模式
SN65HVDA100 5V/12V 20kbps 宽电压,抗干扰强

我的经验: 选收发器时,一定要看它的地偏移范围。车载环境地电位可能差好几伏,如果收发器不支持±5V地偏移,通信就会出错。我曾经用过一个便宜的收发器,地偏移只有±2V,结果在实车上频繁丢帧。后来换成TJA1020,再没出过问题。

嗯,这一章的内容就这些。下一章我们讲主节点的软件架构——调度表引擎的实现。到时候我会贴出完整的代码,手把手教你写一个调度表管理器。