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