使用 Python 串行库处理从串口读取的原始数据?

Posted

技术标签:

【中文标题】使用 Python 串行库处理从串口读取的原始数据?【英文标题】:Processing raw data read from serial port with Python serial library? 【发布时间】:2016-10-22 06:04:29 【问题描述】:

我不是 Python 程序员,而是电子电路设计师,但是这次我必须处理一些由微控制器通过 RS232 端口发送到 Python 脚本(由 php 脚本调用)的原始数据。

我花了好几个小时试图确定使用 Python 从串行 (RS232) 端口读取原始字节的最佳方法,我确实得到了结果 - 但我希望有人能澄清我在研究期间注意到的某些不一致之处他们在这里:

1: 我可以看到很多提出类似问题的人都被问到他们是否使用serialpySerial 模块以及他们是如何安装串行库的。我只能说我真的不知道我正在使用哪个模块,因为该模块是开箱即用的。我在某处读到serialpySerial 是同一件事,但我找不到这是否属实。我只知道我正在使用带有 Raspbian OS 的 Python 2.7.9。

2: 我读过有read()readline() 用于从串行端口读取的方法,但在pySerial API docs 中没有提到readline() 方法。此外,我发现“要读取的字节数”参数可以传递给 readline() 方法以及 read() 方法(并且工作方式相同,限制要读取的字节数)但我找不到记录下来。

3: 在搜索如何确定是否已读取 RS232 缓冲区中的 所有 数据时,here 找到了以下代码:

read_byte = ser.read()
while read_byte is not None:
    read_byte = ser.read()
    print '%x' % ord(read_byte)

但结果是:

Traceback (most recent call last):
  File "./testread.py", line 53, in <module>
    read_all()
  File "./testread.py", line 32, in read_all
    print '%x' % ord(read_byte)
TypeError: ord() expected a character, but string of length 0 found

从缓冲区读取最后一个字节后,我只能使用以下代码检测到空缓冲区:

while True:
    c = rs232.read()
    if len(c) == 0:
        break
    print int(c.encode("hex"), 16), " ",

所以我不确定对我不起作用的代码是否适用于我以外的某些串行库。我的 openinig 端口代码是 BTW:

rs232 = serial.Serial(
    port = '/dev/ttyUSB0',
    baudrate = 2400,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout = 1
)

4: 我从 µC 收到的数据格式如下:

0x16 0x02 0x0b 0xc9 ... 0x0d 0x0a

那是some raw bytes + \r\n。由于“原始字节”可以包含0x00,有人可以确认这不是将字节读入 Python 字符串变量的问题吗?据我了解,这应该可以正常工作,但不能 100% 确定。

【问题讨论】:

【参考方案1】:

PySerial 对我有用,虽然没有在 Pi 上使用过。

3:Read() 返回一个字符串 - 如果没有读取数据,这将是零长度,因此您的更高版本是正确的。由于字符串不是字符,您应该使用例如ord(read_byte[0]) 打印第一个字符对应的数字(如果字符串的长度>0) 你的功能:

while True:
    c = rs232.read()
    if len(c) == 0:
        break
    print int(c.encode("hex"), 16), " ",

需要添加一些东西来累积读取的数据,否则会被丢弃

rcvd = ""
while True:
    c = rs232.read()
    if len(c) == 0:
        break
    rcvd += c
    for ch in c:
        print ord(ch), " ",

4: 是的,您可以接收 nul (0x00) 字节并将其放入字符串中。例如:

a="\x00"
print len(a)

将打印长度 1

【讨论】:

“是的,你可以,但字符串中有 0 个字节。”,意思是:“是的,你可以,但没有字符串中有零字节。”?我想知道的是,例如0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a 从 RS232 接收并分配给字符串变量可能会导致问题。据我了解,内部字符串表示是以空值结尾的 C 字符串,但我无法找到零是否可以存储在内部表示的高级表示中。 我们在 Linux/Windows 上使用的常用 Python 中字符串的内部表示不是空终止的。您可以将任何值字符放入字符串中。 这意味着voted-up anwer 会说:'在内部,最流行的 Python 实现是用 C 编写的,所以可能在引擎盖下的某个地方有一个以 NULL 结尾的字符串。',错了吗? 顺便说一句,我不能编辑(在发布后的前 5 分钟内)或删除我自己的 cmets,因为鼠标悬停时没有 x 图标(或任何东西)。之前的功能可以正常工作,但现在不行了。问题与here 完全一样。不幸的是,我没有足够的声誉点来发表评论以确认问题。注意:我没有多少声望点,但我确实知道编辑/删除自己的 cmets 功能之前是如何工作的。 这个答案是正确的,因为它说字符串实现对 python 编写的开发人员是不透明的,并且使用 nul 终止的实现肯定是错误的,正如 Josiah Yoder 所评论的那样。

以上是关于使用 Python 串行库处理从串口读取的原始数据?的主要内容,如果未能解决你的问题,请参考以下文章

问题:关闭端口后,python 仍然读取来自 arduino 的串行数据。串口无法关闭

写入串口但只接收第一个字符?

c#从串口读取数据怎样读一个就清空缓存

从串口读取命令的响应

Python readlines Api从串口访问时需要很长时间

VC串口通信,从串口中读取串口摄像头图片,接收到的数据转换成JPG图片