2. LIN协议基础:帧结构
各位好,我是老张。今天咱们聊聊LIN总线最核心的东西——帧结构。说实话,搞懂了这个,你调试LIN总线就成功了一半。我在项目里见过太多人,拿着调试工具对着波形发呆,其实就是没搞明白帧里装的是什么。
2.1 帧结构概览
一个完整的LIN帧,说白了就是一段有规矩的报文。它由主机节点发起,从机节点响应。我习惯把帧结构拆成六个部分来看:
- 同步间隔场(Break Field)—— 帧的起始标志
- 同步场(Sync Field)—— 时钟校准用
- 标识符场(Protected Identifier Field)—— 告诉总线“谁在说话”
- 数据场(Data Field)—— 真正要传的信息
- 校验和场(Checksum Field)—— 保证数据没被篡改
嗯,这里要注意,帧头和帧响应是分开的。主机发帧头,从机发响应。这个机制我刚开始学的时候老搞混,后来在调试一个车窗控制模块时,发现从机不响应,查了半天才发现是帧头里的标识符配错了。
核心要点:LIN帧 = 主机帧头 + 从机响应。帧头包含同步间隔场、同步场和标识符场;响应包含数据场和校验和场。
2.2 同步间隔场(Break Field)
同步间隔场是帧的“开场白”。它由两部分组成:
- 同步间隔(Sync Break):至少13个位的显性电平(低电平)
- 间隔分隔符(Break Delimiter):至少1个位的隐性电平(高电平)
为什么要有这个?你想想看,总线上的节点怎么知道一帧开始了?就是靠这个明显的低电平信号。我遇到过一个问题:某个从节点老是丢帧,用示波器一看,同步间隔只有12个位。标准要求至少13个位,差一点都不行。后来改了主节点的配置,问题就解决了。
避坑指南:我曾经因为同步间隔场长度不够,导致整个网络通信不稳定。记住:同步间隔至少13个位,间隔分隔符至少1个位。调试时优先检查这个。
2.3 同步场(Sync Field)
同步场的格式是固定的:0x55(二进制01010101)。说白了就是让从节点能校准自己的时钟。每个从节点内部都有一个波特率发生器,但总会有偏差。通过这个0x55的上升沿和下降沿,从节点可以计算出主节点的波特率。
我记得有一次,一个客户说他们的LIN通信时好时坏。我让他们抓了同步场的波形,发现从节点的时钟偏差超过了2%。标准要求从节点时钟偏差在±1.5%以内,主机在±0.5%以内。换了晶振后,通信就稳定了。
小技巧:调试时如果发现通信不稳定,先看同步场。用示波器测量0x55的位时间,算一下实际波特率。偏差超过1%就要警惕了。
2.4 标识符场(Protected Identifier Field)
标识符场是帧的“身份证”。它包含6个位的标识符(ID)和2个位的奇偶校验位。ID范围是0x00到0x3F,共64个。
标识符的分配是有讲究的:
- 0x00 - 0x3B:用于信号承载帧(无条件帧、事件触发帧、偶发帧)
- 0x3C - 0x3D:用于诊断帧(Master Request和Slave Response)
- 0x3E - 0x3F:保留,用于未来扩展
奇偶校验位的计算方式是这样的:
// 标识符ID的6个位:ID5 ID4 ID3 ID2 ID1 ID0
// 奇偶校验位P0和P1的计算:
P0 = ID0 ⊕ ID1 ⊕ ID2 ⊕ ID4
P1 = ¬(ID1 ⊕ ID3 ⊕ ID4 ⊕ ID5)
嗯,这个公式看着复杂,但实际用的时候,调试工具会自动帮你算好。我建议你理解原理就行,不用死记硬背。
注意:标识符场是受保护的,奇偶校验位能检测出单比特错误。如果从节点收到的标识符校验失败,它会忽略这帧。我曾经因为线束接触不良,导致标识符偶尔被误码,从节点就不响应了。
2.5 数据场(Data Field)
数据场就是真正要传的信息。每个数据场包含1到8个字节。具体传几个字节,由LDF(LIN描述文件)定义。
数据场的字节顺序是:最低有效字节先传(LSB first)。举个例子,如果数据是0x1234,那么先传0x34,再传0x12。
我在调试一个座椅控制模块时,发现数据总是反的。后来才意识到,LIN的数据传输顺序和CAN不一样。CAN是MSB first,LIN是LSB first。这个坑我踩过,你们要注意。
经验之谈:调试数据场时,建议先用调试工具发送固定数据(比如0x55, 0xAA),然后看从节点的响应。这样能快速确认数据字节顺序和位顺序是否正确。
2.6 校验和场(Checksum Field)
校验和场用来保证数据的完整性。LIN协议有两种校验和:
- 经典校验和(Classic Checksum):只对数据场做校验
- 增强校验和(Enhanced Checksum):对数据场和标识符场一起做校验
校验和的计算方法是:把所有字节加起来,取反,然后取低8位。说白了就是“和的反码”。
// 经典校验和示例(数据场为0x01, 0x02, 0x03)
sum = 0x01 + 0x02 + 0x03 = 0x06
checksum = ~0x06 & 0xFF = 0xF9
// 增强校验和示例(标识符0x12,数据场0x01, 0x02, 0x03)
sum = 0x12 + 0x01 + 0x02 + 0x03 = 0x18
checksum = ~0x18 & 0xFF = 0xE7
我建议新项目都用增强校验和,安全性更高。但要注意,如果网络中有老节点只支持经典校验和,那就得统一用经典校验和。
避坑指南:我曾经在一个项目中,新旧节点混用,结果校验和方式不一致,导致通信失败。后来在LDF文件中明确指定了校验和类型,才解决问题。记住:一个网络里所有节点必须用同一种校验和。
2.7 帧类型
LIN协议定义了四种帧类型。我按使用频率给大家讲讲:
2.7.1 无条件帧(Unconditional Frame)
这是最常用的帧类型。主机发帧头,从机必须响应。说白了就是“点名回答”。比如发动机转速信号,每次主机问,从机都得答。
无条件帧的标识符范围是0x00到0x3B。每个无条件帧只能有一个从节点响应。
2.7.2 事件触发帧(Event Triggered Frame)
这个有点意思。多个从节点共享同一个标识符,但只有数据变化时才响应。如果多个节点同时响应,就会发生冲突,然后主机再通过无条件帧逐个询问。
我做过一个车门模块的项目,四个车门的状态信号就用事件触发帧。平时没变化时,总线很安静。一旦有车门打开,对应的节点就发数据。这样能大大降低总线负载。
适用场景:事件触发帧适合那些变化不频繁的信号,比如开关状态、故障码等。如果信号变化频繁,建议用无条件帧。
2.7.3 偶发帧(Sporadic Frame)
偶发帧是主机节点专用的。主机可以在一个时隙里发送多个偶发帧,但只发送数据有变化的那个。说白了就是“主机主动汇报”。
我记得调试一个空调控制面板时,主机需要上报按键状态。用偶发帧就很合适——没按键时总线安静,有按键时才发数据。
2.7.4 诊断帧(Diagnostic Frame)
诊断帧用于诊断和配置。它有两个固定的标识符:
- 0x3C:主机请求帧(Master Request Frame)
- 0x3D:从机响应帧(Slave Response Frame)
诊断帧的数据场固定为8个字节。第一个字节是节点地址(NAD),后面是诊断服务ID和参数。
我在产线上经常用诊断帧来刷写从节点的固件。通过0x3C发请求,0x3D收响应,配合UDS协议,就能实现远程升级。
实用建议:调试诊断帧时,建议先用调试工具模拟主机发0x3C帧,看从机是否回复0x3D帧。如果不回复,先检查从机的NAD地址是否匹配。
2.8 帧类型对比
| 帧类型 | 发起方 | 响应方 | 标识符范围 | 典型应用 |
|---|---|---|---|---|
| 无条件帧 | 主机 | 单个从机 | 0x00 - 0x3B | 周期性信号(转速、温度) |
| 事件触发帧 | 主机 | 多个从机(冲突时回退) | 0x00 - 0x3B | 状态变化信号(开关、故障) |
| 偶发帧 | 主机 | 主机自身 | 0x00 - 0x3B | 主机主动上报(按键、诊断) |
| 诊断帧 | 主机/从机 | 从机/主机 | 0x3C - 0x3D | 诊断、配置、刷写 |
2.9 小结
好了,这一章的内容就这些。总结一下:
- LIN帧由同步间隔场、同步场、标识符场、数据场和校验和场组成
- 同步间隔场至少13个位,是帧的起始标志
- 同步场固定为0x55,用于时钟校准
- 标识符场包含6位ID和2位奇偶校验
- 数据场1-8个字节,LSB first传输
- 校验和场有经典和增强两种,一个网络必须统一
- 四种帧类型各有用途,选对了能事半功倍
下一章我会讲LIN的调度表,也就是怎么安排这些帧的发送顺序。到时候我会结合一个实际的车灯控制案例,带大家一步步配置调度表。咱们下章见。