#!/usr/bin/env python3
|
# -*- coding: utf-8 -*-
|
"""
|
校验和调试工具 - 详细分析STM32输出的原始数据帧
|
"""
|
|
import serial
|
import struct
|
import time
|
|
# 协议常量
|
FRAME_HEADER = bytes([0xAA, 0x55])
|
FRAME_FOOTER = bytes([0x0D, 0x0A])
|
TYPE_GPS = 0x01
|
TYPE_IMU = 0x02
|
|
def calculate_checksum(data):
|
"""计算16位累加和"""
|
return sum(data) & 0xFFFF
|
|
def main():
|
port = "COM28"
|
baudrate = 921600
|
|
print(f"打开串口 {port} @ {baudrate}")
|
|
try:
|
ser = serial.Serial(port, baudrate, timeout=1)
|
print("串口已打开,接收数据中...\n")
|
|
buffer = bytearray()
|
frame_count = 0
|
|
while frame_count < 5: # 只分析前5帧
|
if ser.in_waiting > 0:
|
data = ser.read(ser.in_waiting)
|
buffer.extend(data)
|
|
# 查找帧头
|
while len(buffer) >= 9:
|
idx = buffer.find(FRAME_HEADER)
|
if idx == -1:
|
buffer.clear()
|
break
|
|
if idx > 0:
|
buffer = buffer[idx:]
|
|
# 检查是否有足够的数据解析帧头
|
if len(buffer) < 5:
|
break
|
|
frame_type = buffer[2]
|
payload_len = struct.unpack('<H', buffer[3:5])[0]
|
expected_len = 2 + 1 + 2 + payload_len + 2 + 2
|
|
print(f"\n[调试] 发现帧头 @ buffer[{idx}], 类型=0x{frame_type:02X}, 载荷长度={payload_len}, 需要={expected_len}, 可用={len(buffer)}")
|
|
if len(buffer) < expected_len:
|
print(f"[调试] 数据不足,等待更多数据...")
|
break
|
|
# 提取完整帧
|
frame = buffer[:expected_len]
|
buffer = buffer[expected_len:]
|
|
frame_count += 1
|
|
# 详细分析这一帧
|
print(f"{'='*70}")
|
print(f"帧 #{frame_count} - 类型: 0x{frame_type:02X} ({'GPS' if frame_type == TYPE_GPS else 'IMU' if frame_type == TYPE_IMU else '未知'})")
|
print(f"{'='*70}")
|
|
# 打印原始十六进制
|
print(f"原始数据 ({len(frame)} 字节):")
|
hex_str = ' '.join(f'{b:02X}' for b in frame)
|
for i in range(0, len(hex_str), 72):
|
print(f" {hex_str[i:i+72]}")
|
|
# 解析各个部分
|
print(f"\n帧结构分析:")
|
print(f" 帧头: {frame[:2].hex().upper()} (应为 AA55)")
|
print(f" 类型: 0x{frame[2]:02X}")
|
print(f" 长度: {payload_len} (0x{frame[3]:02X}{frame[4]:02X})")
|
|
payload = frame[5:5+payload_len]
|
print(f" 载荷: {payload.hex().upper()} ({len(payload)} 字节)")
|
|
checksum_received = struct.unpack('<H', frame[5+payload_len:5+payload_len+2])[0]
|
print(f" 校验和(接收): 0x{checksum_received:04X}")
|
|
footer = frame[5+payload_len+2:5+payload_len+4]
|
print(f" 帧尾: {footer.hex().upper()} (应为 0D0A)")
|
|
# 计算校验和 - 三种方式
|
print(f"\n校验和验证:")
|
|
# 方式1: Type + Length + Payload (正确方式)
|
checksum_data1 = frame[2:5+payload_len]
|
checksum_calc1 = calculate_checksum(checksum_data1)
|
match1 = "✓" if checksum_calc1 == checksum_received else "✗"
|
print(f" 方式1 (Type+Len+Payload): 0x{checksum_calc1:04X} {match1}")
|
print(f" 计算范围: 字节[2:{5+payload_len}] = {checksum_data1.hex().upper()}")
|
|
# 方式2: 包含帧头 (错误方式)
|
checksum_data2 = frame[0:5+payload_len]
|
checksum_calc2 = calculate_checksum(checksum_data2)
|
match2 = "✓" if checksum_calc2 == checksum_received else "✗"
|
print(f" 方式2 (含帧头AA55): 0x{checksum_calc2:04X} {match2}")
|
|
# 方式3: 只有Payload (错误方式)
|
checksum_calc3 = calculate_checksum(payload)
|
match3 = "✓" if checksum_calc3 == checksum_received else "✗"
|
print(f" 方式3 (仅Payload): 0x{checksum_calc3:04X} {match3}")
|
|
# 计算差值
|
diff = checksum_received - checksum_calc1
|
print(f"\n 差值 (接收 - 方式1): {diff} (0x{diff & 0xFFFF:04X})")
|
|
print()
|
|
if frame_count >= 5:
|
break
|
|
time.sleep(0.01)
|
|
ser.close()
|
print("分析完成")
|
|
except Exception as e:
|
print(f"错误: {e}")
|
import traceback
|
traceback.print_exc()
|
|
if __name__ == "__main__":
|
main()
|