3、LIN协议层:帧结构详解
各位工程师朋友,咱们今天聊聊LIN总线最核心的东西——帧结构。说白了,LIN总线上的所有通信,都是靠一帧一帧的数据来完成的。你想想看,如果连帧结构都搞不清楚,那故障诊断根本无从下手。
我个人习惯把LIN帧比作一封信。信有信封、有正文、有落款。LIN帧也一样,有固定的格式。咱们今天就把这封信拆开,看看里面到底写了什么。
3.1 同步间隔场(Break Field)
这是帧的开始,也是最重要的一步。为什么?因为它告诉所有从节点:“注意,新的一帧要来了!”
同步间隔场,说白了就是一个持续13位或更多位时间的显性电平(逻辑0)。我刚开始做LIN项目时,总觉得这个场没什么技术含量,不就是拉低电平嘛。直到有一次,一个从节点老是丢帧,查了半天才发现是主节点发送的间隔场长度不够,只有11位。嗯,这里要注意,标准要求至少13位,但有些芯片要求更严格。
同步间隔场之后,还有一个同步间隔分隔符(Break Delimiter),至少1位的隐性电平。这个分隔符的作用是让总线从显性状态恢复到隐性状态,为后面的同步场做准备。
3.2 同步场(Sync Field)
同步场的格式是固定的:0x55,也就是二进制01010101。为什么是这个值?因为它的上升沿和下降沿交替出现,每个位的时间宽度都一样。从节点就是靠这个来校准自己的位时钟的。
我记得有一次调试,从节点总是报同步错误。用示波器一看,主节点发送的同步场波形畸变严重,上升沿和下降沿的时间不对称。后来发现是主节点的晶振精度不够,换了个高精度的晶振就解决了。
同步场的检测其实很简单:从节点检测到同步间隔场后,就开始等待同步场。它测量第一个下降沿到第二个下降沿的时间,然后除以2,就得到了一个位的时间。这样,从节点就能和主节点保持同步了。
3.3 标识符场(Identifier Field)
标识符场,也叫ID场,长度为8位。其中前6位是真正的标识符,范围0x00到0x3F,一共64个。后2位是奇偶校验位,用于检测ID传输过程中是否出错。
这里有个容易混淆的地方:标识符并不代表节点的地址,而是代表消息的类型。比如,ID=0x01可能表示“车门状态”,ID=0x02可能表示“车窗位置”。所有节点都会收到这个ID,但只有配置了该ID的节点才会响应。
奇偶校验位的计算方式是这样的:
// 假设ID的低6位为 ID5 ID4 ID3 ID2 ID1 ID0
// 则奇偶校验位 P0 和 P1 的计算公式为:
P0 = ID0 ⊕ ID1 ⊕ ID2 ⊕ ID4
P1 = !(ID1 ⊕ ID3 ⊕ ID4 ⊕ ID5)
嗯,这个公式看起来有点复杂,但实际用起来很简单。我建议你在代码里直接查表,或者用现成的库函数,省得自己算错。
3.4 数据场(Data Field)
数据场是帧的正文部分,长度可以是1到8个字节。具体长度由ID决定,在LDF(LIN描述文件)中定义。比如,ID=0x01可能定义数据长度为4字节,ID=0x02可能定义数据长度为2字节。
数据场的传输顺序是:先传低字节,再传高字节。每个字节内部,先传低位,再传高位。这个顺序和CAN总线是一样的,大家应该不陌生。
我在项目中遇到过一个问题:某个从节点发送的数据总是比预期少一个字节。查了半天,发现是LDF文件中定义的数据长度和从节点实际发送的长度不一致。所以,我建议大家在调试时,一定要先核对LDF文件,确保定义和实现一致。
3.5 校验和场(Checksum Field)
校验和场用于检测数据传输过程中是否出错。LIN总线有两种校验和方式:经典校验和(Classic Checksum)和增强校验和(Enhanced Checksum)。
经典校验和只对数据场进行校验,而增强校验和还对标识符场进行校验。LIN 2.0及以上版本默认使用增强校验和,但为了兼容旧设备,也可以使用经典校验和。
校验和的计算方法如下:
// 经典校验和:只对数据字节求和
checksum = 0
for each data byte:
checksum += data_byte
if checksum > 0xFF:
checksum -= 0xFF
checksum = 0xFF - checksum
// 增强校验和:对ID和数据字节求和
checksum = 0
checksum += ID_byte
for each data byte:
checksum += data_byte
if checksum > 0xFF:
checksum -= 0xFF
checksum = 0xFF - checksum
说白了,校验和就是所有字节的和取反。接收节点收到数据后,也会计算一遍校验和,如果和自己收到的校验和一致,就说明数据没出错。
3.6 报文滤波(Message Filtering)
报文滤波是LIN总线的一个核心机制。每个从节点都有一个或多个ID过滤器。当主节点发送一个帧时,所有从节点都会收到这个帧的ID。然后,每个从节点会检查这个ID是否在自己的过滤器列表中。
如果匹配,从节点就继续接收后面的数据场和校验和场。如果不匹配,从节点就直接忽略这个帧,不参与后续处理。
报文滤波的好处是:减少了从节点的处理负担,也避免了不必要的总线冲突。你想想看,如果每个从节点都要处理所有帧,那CPU的负担得多重啊。
我个人的习惯是:在LDF文件中明确定义每个从节点的ID列表,然后在代码中实现对应的过滤器。调试时,我会用LIN分析仪抓取总线上的所有帧,然后检查每个从节点是否正确过滤了ID。
好了,关于LIN帧结构的详解就到这里。下一章咱们聊聊LIN总线的错误检测和故障诊断方法。到时候我会分享一些实战中的案例,希望对大家有帮助。