4、LIN数据链路层:字节域与帧格式、校验和计算、响应与超时机制、错误检测与处理
好,我们进入数据链路层。这一层,说白了就是LIN总线上“帧”的规矩。你想想看,一堆节点挂在一条线上,谁什么时候说话,说什么,说错了怎么办?这些都得定死。我刚开始接触LIN时,总觉得它比CAN简单太多,但实际调起来,坑也不少。今天咱们就把这些规矩掰开揉碎讲清楚。
4.1 字节域与帧格式
先看最基本的单元——字节域。LIN的字节域和UART基本一样,10个位:1个起始位(显性‘0’),8个数据位(LSB先发),1个停止位(隐性‘1’)。嗯,这里要注意,没有奇偶校验位。为什么?为了简化,校验交给更高层的协议去处理。
帧格式呢,我习惯把它分成两部分:报头(Header)和响应(Response)。
- 报头:由主节点发出,包含同步间隔场、同步场、标识符场。
- 响应:由某个从节点(或主节点自己)发出,包含数据场和校验和场。
整个帧的结构,我用个表格给你看,更清楚:
| 场名称 | 字节数 | 说明 |
|---|---|---|
| 同步间隔场 | 1+ | 至少13个显性位,用于唤醒和帧同步 |
| 同步场 | 1 | 固定为0x55,用于位速率校准 |
| 标识符场 | 1 | 包含6位ID和2位奇偶校验 |
| 数据场 | 1~8 | 实际传输的数据,由信号打包而成 |
| 校验和场 | 1 | 经典校验和或增强型校验和 |
这里有个细节:同步间隔场至少13个显性位,后面还要跟一个间隔分隔符(至少1个隐性位)。我见过有人把间隔场长度设成10位,结果从节点死活不同步。记住,13位是底线,不是建议值。
4.2 校验和计算
校验和是LIN帧的“防伪标签”。分两种:经典校验和(Classic Checksum)和增强型校验和(Enhanced Checksum)。
经典校验和:只对数据场做校验。计算范围是数据场的所有字节。
增强型校验和:对数据场 + 标识符场一起做校验。这是LIN 2.0以后引入的,更安全。
怎么算?说白了就是带进位加法的反码。我举个例子:
// 假设数据场为 0x55, 0xAA
// 计算过程:
// 0x55 + 0xAA = 0xFF
// 进位为0,所以和 = 0xFF
// 取反码:~0xFF = 0x00
// 所以校验和 = 0x00
实际项目中,我建议直接用Vector工具链里的LDF解析器,它会自动帮你算好。但如果你要手写从节点代码,记得把进位加进去。我曾经在某个项目中,因为忘了处理进位,导致校验和一直算不对,查了整整一个下午。
重要提醒:LIN 2.0及以上版本,建议统一使用增强型校验和。除非你明确知道所有节点都只支持经典校验和,否则别混用。混用的后果就是——有些帧能过,有些帧过不了,排查起来非常痛苦。
4.3 响应与超时机制
LIN的通信是主从模式。主节点发出报头,然后等待某个从节点来响应。如果从节点没响应呢?这就涉及到超时机制了。
我把它分成两种场景:
- 无响应超时:主节点发出报头后,在规定时间内没收到响应。这个时间一般是帧传输时间的1.5倍左右。如果超时,主节点可以重发报头,或者记录一个错误。
- 帧间超时:两个连续帧之间的间隔不能太长。LIN规范里叫“帧间空间”,至少是0个位时间,但也不能无限长。我一般设成帧长度的2倍作为警戒线。
你可能会问:超时时间设多少合适?嗯,这取决于波特率。以20kbps为例,一个字节域是10位,传输时间就是500μs。如果数据场有8个字节,整个响应时间大约是4ms。我习惯把超时设成6ms,留点余量。
个人经验:在Vector CANoe里配置LIN超时时,别忘了加上同步间隔场的时间。那个13位显性位,在20kbps下就是650μs。很多人只算了数据场,结果超时设得太紧,导致误报。
4.4 错误检测与处理
LIN的错误检测,说实话不如CAN那么严密。但它也有自己的一套机制。我归纳为以下几类:
- 位错误:发送节点在发送位的同时,监控总线电平。如果发现不一致,就报位错误。比如你发隐性位,但总线上是显性,那肯定有问题。
- 校验和错误:接收节点自己算一遍校验和,和收到的值对比。不一致就报错。
- 标识符奇偶校验错误:标识符场里有2位奇偶校验位。如果算出来不对,说明标识符被干扰了。
- 从节点无响应错误:前面说的超时,也算一种错误。
- 总线冲突错误:两个节点同时发数据,总线被拉成显性。这种情况在LIN里很少见,因为主从模式决定了只有一个节点能响应。
处理方式呢?LIN规范里没有像CAN那样的自动重传机制。我一般这样处理:
- 对于校验和错误:丢弃该帧,记录错误计数器。
- 对于位错误:如果发生在报头,主节点可以重发报头。如果发生在响应,从节点可以重发响应(但需要主节点再次发起报头)。
- 对于连续错误:比如连续3次校验和错误,我建议把该从节点标记为“故障”,并触发诊断流程。
避坑指南:我曾经在一个项目中,从节点因为晶振偏差太大,导致位采样点偏移,频繁出现位错误。后来发现是晶振精度只有±2%,而LIN要求±1.5%。所以,硬件选型时,晶振精度一定要留够余量。别省那几毛钱,省下来的钱最后都花在调试时间上了。
最后说一句,LIN的错误处理,很大程度上依赖于应用层的策略。数据链路层只负责检测和上报,怎么恢复,得看你的网络管理策略。我个人习惯在Vector CANoe里写CAPL脚本,模拟各种错误场景,提前验证从节点的容错能力。这样到了实车测试阶段,能省不少事。