Pyserial格式化 - 超过127的字节返回为2个字节,而不是一个

4 投票
1 回答
3080 浏览
提问于 2025-04-17 13:20

我在Arduino上运行了一个程序,它可以接收串口输入,并把这些输入保存到一个变量里。这个功能非常好用。通过Arduino自带的串口监视器,我成功地发送和接收了0到255之间的字节。

但是,当我使用pyserial发送任何大于127的字节(比如0b01111111)时,pyserial会返回2。这意味着对于大于127的值,比如0b10000000,会发送2个字节,而不是1个。

所以我觉得问题出在pyserial上。

ser.write(chr(int('01000000', base=2)).encode('utf-8'))

这个发送是完全正常的,并且在Arduino那边也能正确接收到。

ser.write(chr(int('10000000', base=2)).encode('utf-8')) 

但是返回的是2,并且在Arduino上显示为0b110000100b10000000

1 个回答

2

正如NPE所说,这里讲的是UTF-8的编码方式。简单来说,128到2047之间的字节(也就是8到11位的二进制数)会被转换成两个字节。如果原来的11位是abcdefghijk,那么在UTF-8中就变成了110abcde 10fghijk。在你的例子中(为了凑成11位,左边补了0),00010000000会被转换成11000010 10000000,也就是\xc2\x80,这正是你看到的结果。想了解更多,可以查看维基百科关于UTF-8的文章

你可以用下面的代码在Python中看到这个效果(我把int('10000000', base=2)替换成了128):

>>> unichr(128).encode('utf-8')
'\xc2\x80' 

让我感到困惑的是,你可以用chr(int('10000000', base=2)).encode('utf-8'),或者直接用chr(128).encode('utf-8')。当我这样做时,我得到了:

>>> chr(int('10000000', base=2)).encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

你有没有改变默认的编码方式?

你需要的是一种编码方式,它能用一个字节表示0到255,并且与Unicode匹配。所以试试用'latin_1'代替:

>>> unichr(128).encode('latin_1')
'\x80'

撰写回答