4、LIN总线数据场与校验:数据场长度、数据场格式、校验和计算(经典校验与增强校验)、校验和错误处理
好,咱们接着聊。前面几章我们把帧头、同步场、标识符都讲透了。这一章,我重点说说数据场和校验场。
说实话,数据场和校验场是LIN总线里最容易出问题的地方。我见过太多工程师,明明协议栈写得没问题,但就是通信不稳定。最后查下来,十有八九是校验和算错了,或者数据场长度没对齐。
嗯,咱们一个一个来拆解。
4.1 数据场长度:不是你想发多少就发多少
LIN总线的数据场,长度是固定的——1到8个字节。为什么是8个?说白了,LIN总线就是CAN总线的低成本替代方案。CAN报文数据场最长8字节,LIN也沿用了这个设计。
但这里有个坑:数据场长度必须在调度表中显式声明。你不能像CAN那样,靠DLC(数据长度码)来动态决定。LIN的帧头里没有长度信息,长度是事先约定好的。
我个人习惯,在LDF(LIN描述文件)里这样定义:
Signal: EngineSpeed : 16, 0, 1, Master
Signal: CoolantTemp : 8, 16, 1, Slave
Frame: Frame_1 : 0x31, Master, 4
{
EngineSpeed, 0;
CoolantTemp, 16;
}
你看,Frame_1后面那个4,就是数据场长度。这里我声明了4个字节,但实际只用了3个字节(16位+8位)。多出来的1个字节怎么办?填充0。这是规范允许的。
4.2 数据场格式:LSB先行,别搞反了
LIN总线的数据场,遵循小端序(Little-Endian)。什么意思?就是低字节在前,高字节在后。
举个例子。假设你要发送一个16位的信号,数值是0x1234。在LIN总线上,先发0x34,再发0x12。
我刚开始做LIN开发时,就犯过这个错。当时用示波器抓波形,怎么看怎么不对。后来才发现,我把高低字节搞反了。嗯,从那以后,我每次写代码都会在注释里标清楚字节序。
数据场的位排列是这样的:
| 字节序号 | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|---|
| Byte 0 | 数据位(LSB) | |||||||
| Byte 1 | 数据位 | |||||||
| ... | ... | |||||||
| Byte N | 数据位(MSB) | |||||||
你想想看,如果信号跨字节了怎么办?比如一个12位的信号,从Byte 0的bit 4开始。那它就会占用Byte 0的bit 4-7,以及Byte 1的bit 0-7。嗯,这种跨字节的情况在LIN里很常见,处理起来要格外小心。
4.3 校验和计算:经典校验 vs 增强校验
校验和是LIN总线保证数据完整性的最后一道防线。LIN 2.0之后,引入了两种校验方式:经典校验(Classic Checksum)和增强校验(Enhanced Checksum)。
4.3.1 经典校验
经典校验只对数据场做校验。说白了,就是把数据场的所有字节加起来,取反,然后发出去。
计算公式:
Checksum = ~(DataByte0 + DataByte1 + ... + DataByteN) & 0xFF
举个例子。假设数据场是0x55, 0xAA, 0x01:
- 求和:0x55 + 0xAA + 0x01 = 0x100
- 取低8位:0x00
- 取反:0xFF
所以校验和就是0xFF。
4.3.2 增强校验
增强校验在经典校验的基础上,把标识符(Protected ID)也加了进来。为什么要这么做?因为经典校验只保护数据,不保护标识符。如果标识符在传输过程中被干扰,从节点可能收到错误的数据却浑然不知。
计算公式:
Checksum = ~(PID + DataByte0 + DataByte1 + ... + DataByteN) & 0xFF
注意,这里的PID是保护标识符,不是原始ID。保护标识符 = 原始ID + 奇偶校验位。这个我们在上一章讲过。
我个人建议,新项目一律用增强校验。为什么?安全性更高。LIN 2.0之后的规范也推荐使用增强校验。只有为了兼容老设备,才不得已用经典校验。
4.4 校验和错误处理:别让错误数据跑出去
校验和算完了,发出去,接收端怎么处理?
接收节点收到一帧数据后,会做两件事:
- 用同样的算法重新计算校验和
- 把计算结果和收到的校验和做比较
如果一致,说明数据没问题。如果不一致,说明传输过程中发生了错误。
那错误怎么处理?LIN规范里写得很清楚:
- 从节点:丢弃该帧数据,不更新信号值。等待下一帧。
- 主节点:同样丢弃数据。但主节点可以决定是否重发。
这里有个细节:校验和错误不会触发任何错误帧。LIN总线没有CAN那样的错误帧机制。校验和错了,就是默默地丢掉。所以,如果你的应用对数据可靠性要求很高,建议在应用层加一个超时重传机制。
另外,校验和错误率其实很低。LIN总线的物理层虽然简单,但抗干扰能力并不差。我测过很多项目,在正常环境下,校验和错误率基本在10^-6以下。只有在强电磁干扰环境下,才会明显升高。
好了,数据场和校验场就讲到这里。下一章,我们聊聊LIN总线的状态管理与休眠唤醒。这部分内容,嗯,也挺有意思的。