在 Python 3 中使用 PySerial 串行发送字节
Send Byte serially using PySerial in Python 3
我查看了一些线程来解决类似的问题,但还没有看到任何针对这个特定问题的线程。
我在 Python 3.5 中使用 PySerial 库,程序传输的 csv 文件仅包含 0 -> 2G(千兆)范围内的整数值,这意味着每个整数值可以是 1 到4 个字节。
内置的 Python bin() 函数可以很好地为我提供要传输的整数的二进制字符串表示形式。然后我可以删除字符串前面的“0b”,以便传输剩余字符串的 int() 值。我 运行 遇到的问题是 Pyserial 的 write() 函数。
write() 函数只接受序列(字节数组、字节等)。如果我将我的二进制值转换为 bytesarray(),它将 return 我的二进制值的每个数字的值数组 (0-256),这不是我想要的。
当我进行任何类型的编码时,我可以在 Hercules 中看到每一位都作为字节发送。例如,
00001000 results in 8 bytes being sent.
Terminal: {30}{30}{30}{30}{31}{30}{30}{30}
如果我尝试传输十六进制值,我会遇到同样的问题。所以我的问题是,如何使用 Pyserial 的库将我的二进制数据作为真实字节传输。
如果我的问题不清楚,请告诉我,我会尽力澄清。本质上,最终结果将是:
00001000 results in 1 bytes being sent.
Terminal: {08}
我对 write() 定义做了一些调整,看看是否可以让它做我想做的事,但我对 python 的熟练程度还不够高,无法进行任何重大更改。这是原始定义:
def write(self, data):
"""Output the given byte string over the serial port."""
if not self.is_open:
raise portNotOpenError
#~ if not isinstance(data, (bytes, bytearray)):
#~ raise TypeError('expected %s or bytearray, got %s' (bytes,type(data)))
# convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
data = to_bytes(data)
if data:
#~ win32event.ResetEvent(self._overlapped_write.hEvent)
n = win32.DWORD()
success = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0)
if not success and win32.GetLastError() != win32.ERROR_IO_PENDING:
raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))
# Wait for the write to complete.
#~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED:
return n.value # canceled IO is no error
if n.value != len(data):
raise writeTimeoutError
return n.value
else:
errorcode = win32.ERROR_SUCCESS if success else win32.GetLastError()
if errorcode in (win32.ERROR_INVALID_USER_BUFFER, win32.ERROR_NOT_ENOUGH_MEMORY,
win32.ERROR_OPERATION_ABORTED):
return 0
elif errorcode in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
# no info on true length provided by OS function in async mode
return len(data)
else:
raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))
else:
return 0
>>> struct.pack('<I', 1234567)
b'\x87\xd6\x12\x00'
>>> struct.pack('>I', 1234567)
b'\x00\x12\xd6\x87'
发送其中一个,然后将另一侧的 4 个字节读入 long
。
我查看了一些线程来解决类似的问题,但还没有看到任何针对这个特定问题的线程。
我在 Python 3.5 中使用 PySerial 库,程序传输的 csv 文件仅包含 0 -> 2G(千兆)范围内的整数值,这意味着每个整数值可以是 1 到4 个字节。
内置的 Python bin() 函数可以很好地为我提供要传输的整数的二进制字符串表示形式。然后我可以删除字符串前面的“0b”,以便传输剩余字符串的 int() 值。我 运行 遇到的问题是 Pyserial 的 write() 函数。
write() 函数只接受序列(字节数组、字节等)。如果我将我的二进制值转换为 bytesarray(),它将 return 我的二进制值的每个数字的值数组 (0-256),这不是我想要的。
当我进行任何类型的编码时,我可以在 Hercules 中看到每一位都作为字节发送。例如,
00001000 results in 8 bytes being sent.
Terminal: {30}{30}{30}{30}{31}{30}{30}{30}
如果我尝试传输十六进制值,我会遇到同样的问题。所以我的问题是,如何使用 Pyserial 的库将我的二进制数据作为真实字节传输。
如果我的问题不清楚,请告诉我,我会尽力澄清。本质上,最终结果将是:
00001000 results in 1 bytes being sent.
Terminal: {08}
我对 write() 定义做了一些调整,看看是否可以让它做我想做的事,但我对 python 的熟练程度还不够高,无法进行任何重大更改。这是原始定义:
def write(self, data):
"""Output the given byte string over the serial port."""
if not self.is_open:
raise portNotOpenError
#~ if not isinstance(data, (bytes, bytearray)):
#~ raise TypeError('expected %s or bytearray, got %s' (bytes,type(data)))
# convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
data = to_bytes(data)
if data:
#~ win32event.ResetEvent(self._overlapped_write.hEvent)
n = win32.DWORD()
success = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0)
if not success and win32.GetLastError() != win32.ERROR_IO_PENDING:
raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))
# Wait for the write to complete.
#~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED:
return n.value # canceled IO is no error
if n.value != len(data):
raise writeTimeoutError
return n.value
else:
errorcode = win32.ERROR_SUCCESS if success else win32.GetLastError()
if errorcode in (win32.ERROR_INVALID_USER_BUFFER, win32.ERROR_NOT_ENOUGH_MEMORY,
win32.ERROR_OPERATION_ABORTED):
return 0
elif errorcode in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
# no info on true length provided by OS function in async mode
return len(data)
else:
raise SerialException("WriteFile failed ({!r})".format(ctypes.WinError()))
else:
return 0
>>> struct.pack('<I', 1234567)
b'\x87\xd6\x12\x00'
>>> struct.pack('>I', 1234567)
b'\x00\x12\xd6\x87'
发送其中一个,然后将另一侧的 4 个字节读入 long
。