如何将小端序24位采样的二进制电压原始文件转换为可绘图数值?
24位小端电压采样二进制文件解析方案
核心错误原因
你解析出的数值远超合理电压范围,本质是三个常见错误:
- 未做24位有符号整数的符号扩展,直接按无符号数拼接字节
- 未做ADC码值到实际电压的量程换算,把原始采样码直接当成电压值
- 部分场景下会搞错文件头截断位置,把XML头、换行符当成采样数据解析,进一步放大数值错误
从你提供的hex转储片段可直接验证:文件头到</DataInfo>标签结束,后续4个字节是0D 0A 0D 0A换行符,真正的采样数据起始偏移为0x804,首个采样点三字节为F2 08 00。
正确解析逻辑
- 字节序处理:3字节小端序的拼接规则为低字节在前,三个字节
b0(低8位)、b1(中8位)、b2(高8位)拼接为整数的公式为raw = b0 | (b1 << 8) | (b2 << 16) - 符号扩展:Python原生不支持24位整数,若拼接后的值最高位(bit23,对应掩码
0x800000)为1,说明是负数,需执行raw = raw - 0x1000000得到正确的有符号值 - 电压换算:解析得到的raw是ADC原始码,需先取静态采样段的平均值作为零点偏移,再结合设备量程换算:
实际电压 = (原始码值 - 零点偏移) * 满量程电压范围 / 2^23。以常见的±10V双极性量程为例,满量程范围为20V,24位有符号数的正满度码值为2^23-1,负满度为-2^23,换算后单LSB对应电压约2.38μV,符合高精度采集卡的分辨率特征。
可直接运行的Python代码
import numpy as np # 配置项,根据实际设备参数修改 FILE_PATH = "你的原始采样文件路径" # 从hex片段确认的数据起始位置,也可自动匹配</DataInfo>标签定位 DATA_START_OFFSET = 0x804 # 示例为±10V双极性量程,单极性5V就填5,以此类推 FULL_SCALE_RANGE = 20 # 二进制模式读取文件 with open(FILE_PATH, "rb") as f: f.seek(DATA_START_OFFSET) raw_stream = f.read() # 逐3字节解析采样点 raw_codes = [] for i in range(0, len(raw_stream), 3): chunk = raw_stream[i:i+3] if len(chunk) < 3: break # 跳过末尾不完整字节 b0, b1, b2 = chunk raw = b0 | (b1 << 8) | (b2 << 16) # 24位有符号数符号扩展 if raw & 0x800000: raw -= 0x1000000 raw_codes.append(raw) raw_codes = np.array(raw_codes) # 计算零点偏移(取前1000个静态采样点平均,无静态段可换用全量中位数) zero_offset = np.mean(raw_codes[:1000]) # 转换为实际电压值 voltages = (raw_codes - zero_offset) * FULL_SCALE_RANGE / (2 ** 23) # 保存为CSV格式,可直接导入Origin、Matplotlib、Excel绘图 np.savetxt("parsed_voltage.csv", voltages, delimiter=",", header="voltage(V)", comments="")
排查清单
- 若数值跳变完全无规律,先检查数据起始偏移是否正确:优先通过匹配
</DataInfo>标签+后续4字节换行的规则自动定位,不要硬编码偏移量 - 若电压幅度不符合预期,核对设备说明书的ADC量程、增益参数,不要直接套用示例中的±10V配置
- 不要通过文本编辑器复制二进制内容做解析,必须用Python的
rb二进制模式直接读文件,避免编码转换篡改原始字节
内容的提问来源于stack exchange,提问作者Dane Padley
相关产品推荐
相关产品推荐

