3. LIN帧结构解析

LIN帧结构解析 学习卡片

任务说明

本案例要求捕获一个真实的LIN总线帧,并对其四个核心字段——同步场、标识符场、数据场和校验和场——进行完整解析。我们将使用Python实现一个最小化的LIN帧解析器,输入为从总线捕获的原始字节序列,输出为各字段的分解结果及校验验证状态。

LIN帧结构定义

LIN帧由以下字段顺序组成(字节单位):

  • 同步场:固定值0x55,用于波特率同步;
  • 标识符场(PID):低6位为帧ID,高2位为奇偶校验位;
  • 数据场:1~8字节,长度由帧ID决定(本案例按2字节数据演示);
  • 校验和场:对PID和数据字节进行带进位加法的8位和取反。

解析器实现

import sys

class LINFrameParser:
    def __init__(self, raw_bytes: bytes):
        self.raw = raw_bytes
        self.sync = None
        self.pid = None
        self.frame_id = None
        self.data = []
        self.checksum = None
        self.checksum_ok = False

    def parse(self):
        if len(self.raw) < 4:
            raise ValueError("帧长度不足:至少需要同步场+PID+1字节数据+校验和")
        # 同步场
        self.sync = self.raw[0]
        if self.sync != 0x55:
            raise ValueError(f"同步场错误:期望0x55,实际0x{self.sync:02X}")
        # 标识符场
        self.pid = self.raw[1]
        self.frame_id = self.pid & 0x3F
        # 数据场(本案例固定2字节,实际长度由帧ID决定)
        self.data = list(self.raw[2:-1])
        # 校验和场
        self.checksum = self.raw[-1]
        # 校验和验证
        calc = self.pid
        for byte in self.data:
            calc += byte
            if calc > 0xFF:
                calc = (calc & 0xFF) + 1
        calc = (~calc) & 0xFF
        self.checksum_ok = (calc == self.checksum)
        return self

    def display(self):
        print(f"同步场: 0x{self.sync:02X}")
        print(f"标识符场(PID): 0x{self.pid:02X} (帧ID: {self.frame_id})")
        print(f"数据场: {['0x{:02X}'.format(b) for b in self.data]}")
        print(f"校验和场: 0x{self.checksum:02X}")
        print(f"校验结果: {'通过' if self.checksum_ok else '失败'}")

# 捕获的原始LIN帧(示例:同步场0x55, PID=0x1A, 数据[0x11,0x22], 校验和0x8C)
captured_frame = bytes([0x55, 0x1A, 0x11, 0x22, 0x8C])

parser = LINFrameParser(captured_frame)
parser.parse()
parser.display()

运行与验证

将上述代码保存为lin_parser.py,在Python 3环境中执行:

python3 lin_parser.py

预期输出(由代码逻辑直接推出):

同步场: 0x55
标识符场(PID): 0x1A (帧ID: 26)
数据场: ['0x11', '0x22']
校验和场: 0x8C
校验结果: 通过

判定标准:程序无异常退出,且输出与上述预期一致,即证明解析器正确完成了同步场、标识符场、数据场和校验和场的解析与验证。若校验结果输出“失败”,则说明输入帧的校验和字段有误或解析逻辑存在缺陷。

LIN帧字节布局 同步场 0x55 标识符场 PID=0x1A 数据场 0x11, 0x22 校验和场 0x8C 解析流程 检查同步场 提取PID与ID 读取数据字节 校验和验证 校验和算法(经典LIN) sum = PID + DATA[0] + DATA[1] 若sum > 0xFF: sum = (sum & 0xFF) + 1 checksum = ~sum & 0xFF