记一次处理上位机接收下位机数据的bug
记录上位机本应通过串口持续接收 1990 字节长度的数据,但出现不足 1990 字节。正确排查过程。
下位机使用正点原子接收如下
其中收到 20634310 个字节,每个包 1990 个字节。20634310 / 1990 是 10369,能整除,说明没有丢包
但是上位机发现丢包
具体排查步骤
排查上位机接收算法,使用的是先找包头,后找包尾。进一步判断原始数据下包头之间的距离和包尾之间的距离
其中包头是DE3A096631
,包尾是CEFF
查找包尾并写入对应的 CSV 文件
find_ceff.py
import argparse
import csv
def find_ceff_offsets(filename):
with open(filename, 'rb') as f:
data = f.read()
target = b'\xCE\xFF'
offset = 0
count = 0
offsets = []
while True:
idx = data.find(target, offset)
if idx == -1:
break
offsets.append(idx)
offset = idx + 1 # 继续查找下一个
count += 1
if count == 0:
print("未找到任何 CE FF 序列。")
return
print(f"总共找到 {count} 个 CE FF。正在写入 distance.csv...")
with open("distance.csv", "w", newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["index", "start_offset", "end_offset", "distance", "is_1990"])
for i in range(1, len(offsets)):
start = offsets[i - 1]
end = offsets[i]
distance = end - start
writer.writerow([
i,
f"0x{start:08X}",
f"0x{end:08X}",
distance,
"YES" if distance == 1990 else "NO"
])
print("写入完成:distance.csv")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="查找二进制文件中所有 CE FF 的偏移量,并输出间距到 CSV")
parser.add_argument("file", help="要分析的二进制文件路径")
args = parser.parse_args()
find_ceff_offsets(args.file)
运行
python find_ceff.py valid_test/helper/data.raw
绘制对应包尾的距离
find_ceff.py
import pandas as pd
import matplotlib.pyplot as plt
# 读取 CSV 文件
df = pd.read_csv("distance.csv")
# 提取 index 和 distance 列
index = df["index"]
distance = df["distance"]
# 计算常见帧距
expected = distance.mode()[0]
# 绘图
plt.figure(figsize=(12, 6))
plt.plot(index, distance, label='frame distance', marker='o', linewidth=1)
# 标出异常帧距
abnormal = df[distance != expected]
if not abnormal.empty:
plt.plot(abnormal["index"], abnormal["distance"], 'rx', label='abnormal', markersize=8)
# 添加图形信息
plt.xlabel("frame idx")
plt.ylabel("frame distance")
plt.title("CE FF distance")
plt.grid(True)
plt.legend()
plt.tight_layout()
# 显示或保存图像
plt.savefig("distance_plot.png", dpi=300) # 可选保存
plt.show()
发现很多异常距离点
进一步查看包头距离,只要将找包尾代码中的CEFF
换成包头的DE3A096631
,然后进行查找
发现一切正常
说明单纯根据包尾进行查找存在问题,额外增加条件:数据长度。即我找到了包尾,再判断是否满足 1990 长度,不满足继续查找下一个包尾。
我用 ESP32 写一个平移正弦波曲线,持续发送给上位机,上位机持续接收连续曲线,验证正常了。
comment:
- Valine
- LiveRe
- ChangYan