首页 > 解决方案 > 如何从串行数据中提取特定序列

问题描述

我正在尝试使用 pyserial api 从 raspberry pi 3 读取一些串行数据,我需要特定序列中的数据,例如 3xxx7xxxBxxxExxx,但是,有时数据流从 Exxx3xxx7xxxBxxx 开始,我如何确保我始终读取正确的序列而不管数据如何流入。

这是为了从特殊泵应用中使用的控制卡读取数据。

import serial
import time

ser = serial.Serial(
    port = '/dev/ttyACM0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = seial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout = 1
)

time.sleep = 1

try:
    while 1:
        if ser.inWaiting() > 0:
            data = ser.read(8)
            print(data.hex())

这有时会给我 3xxx7xxxBxxxExxx 的结果,有时它从 7xxx 或 Exxx 开始,但是,我总是希望能够提取序列 3xxx7xxxBxxxExxx 而不管流从哪里开始。

标签: python-3.xpyserial

解决方案


假设您用来确定序列开始的标记是一个完整字节0x30,您可以尝试以下代码。它将一次读取一个字节,直到找到开始标记。然后它将读取另外 7 个字节并附加它们:

import serial
import time

ser = serial.Serial(
    port = '/dev/ttyACM0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = seial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout = 1
)

time.sleep = 1

start_marker = b'\xE0'

try:
    while 1:
        if ser.inWaiting() > 0:
            data = ser.read(1)
            if data != start_marker:
                continue
            data += ser.read(7)
            print(data.hex())

编辑

尝试使用此代码匹配每个字节对的最高有效 4 位:

import serial
import time

ser = serial.Serial(
    port = '/dev/ttyACM0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = seial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout = 1
)

time.sleep = 1
data = bytes()

try:
    while 1:
        if ser.inWaiting() > 0:
            data += ser.read(1)
            if len(data) < 8:
                continue
            if len(data) > 8:
                data = data[-8:]
            if not (
                data[0] >> 4 == 0x3 and
                data[2] >> 4 == 0x7 and
                data[4] >> 4 == 0xB and
                data[6] >> 4 == 0xE
            ):
                continue
            print(data.hex())

推荐阅读