如何解析Nonin 3231血氧仪USB串口数据获取SpO2与心率?
解析Nonin Pulse Oximeter 3231的串口血氧/心率数据
协议核心说明
Nonin 3231采用9位串口传输,第9位作为帧标志:1表示帧起始/结束,0表示有效数据。数据帧以0x14(ENQ,第9位为1)开头,随后是两个8位数据字节(第9位为0,分别对应SpO2和心率),最后以0x03(ETX,第9位为1)结束。
解析步骤
- 识别帧起始标志:筛选出第9位为1且字节值为
0x14的单元; - 读取后续两个数据单元:直接取低8位数值作为SpO2(有效范围70-100)和心率(有效范围20-250);
- 验证帧尾:确认后续单元为第9位1且字节值
0x03的ETX,确保帧完整。
修改后的Python解析代码
import serial # 初始化串口,严格匹配设备参数 s = serial.Serial( port="/dev/cu.usbmodem5055968061", baudrate=9600, bytesize=serial.NINEBITS, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_NONE ) try: while True: # 读取单个9位数据单元(返回字节,需转换为整数) raw_unit = s.read() if not raw_unit: continue data_val = ord(raw_unit) ninth_bit = (data_val >> 8) & 1 byte_data = data_val & 0xFF # 检测帧起始(ENQ标志) if ninth_bit == 1 and byte_data == 0x14: # 读取SpO2数据 spo2_raw = s.read() spo2 = ord(spo2_raw) & 0xFF # 读取心率数据 hr_raw = s.read() hr = ord(hr_raw) & 0xFF # 读取并验证帧尾(ETX标志) etx_raw = s.read() etx_val = ord(etx_raw) if (etx_val >> 8) & 1 == 1 and (etx_val & 0xFF) == 0x03: # 输出有效数据(过滤异常值) if 70 <= spo2 <= 100 and 20 <= hr <= 250: print(f"SpO2: {spo2}%, 心率: {hr} bpm") except KeyboardInterrupt: s.close() print("串口已关闭")
常见问题处理
- 若未读取到有效数据:尝试在串口初始化后发送
s.write(b'\x15')(ACK命令),触发设备输出实时数据; - 数值异常:大概率是帧同步错误,可增加帧起始的重试逻辑,跳过无效字节直到找到正确的ENQ标志;
- 串口连接失败:检查设备路径是否正确,确保无其他进程占用串口。
内容的提问来源于stack exchange,提问作者Sylvia M
相关产品推荐
相关产品推荐

