如何从串行数据中提取特定序列

Posted

技术标签:

【中文标题】如何从串行数据中提取特定序列【英文标题】:How can i extract a specific sequence from serial data 【发布时间】:2019-09-12 07:37:02 【问题描述】:

我正在尝试使用 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 而不管流从哪里开始。

【问题讨论】:

也许位掩码是要走的路,但我不熟悉它。请帮忙。 【参考方案1】:

假设您用来确定序列开始的标记是一个完整字节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())

【讨论】:

谢谢,但此解决方案找不到序列的开头。一个完整的字节可以从 exxx3xxx 等开始,也可以在序列中多次出现不一定代表正确序列的开始。

以上是关于如何从串行数据中提取特定序列的主要内容,如果未能解决你的问题,请参考以下文章

如何始终如一地从串行端口记录数据?

状态机实现对串行数据的检测的实验原理是啥

序列化与反序列化

如何在 omp 并行中使特定部件串行?

使用 SerialPort.ReadExisting() 从串行端口接收无效数据

在 Postgres 中的现有列中添加“串行”