Python串行模块无法configuration端口

我正在使用Python3.5.1 串行模块 。 当我打开一个端口时,OS Error 22(Windows Error 87) failure to configure port, one of the arguments in OPEN system call were incorrect, or malformed. ,表示failure to configure port, one of the arguments in OPEN system call were incorrect, or malformed.

我的代码使用循环串口设置 – 将坏包发送到设备,直到设备响应(可读)错误消息(所以我知道我的串口configuration正确)。 是的,我应该知道设备的设置,但这不是一个完美的世界。

  import serial import time baud_rate = [50,75,110,134,150,200,300600,1200,1800,2400,4800,9600,19200,38400,57600,115200] parity = [serial.PARITY_ODD,serial.PARITY_EVEN,serial.PARITY_NONE] stop_bits = [serial.STOPBITS_TWO, serial.STOPBITS_ONE] bytesize = [serial.SEVENBITS,serial.EIGHTBITS] timeout = 5000 for b in baud_rate: for p in parity: for s in stop_bits: for bs in bytesize: ser = serial.Serial(port='COM3',baudrate=b,parity=p,stopbits=s,bytesize=bs) try: if ser.isOpen(): ser.write(b'TEST') ser.reset_output_buffer() time.sleep(1) out = ser.read(3) if out[0] == 64 and out[1] == 67 and out[2] == 32: print("dumping settings") print(ser.get_settings()) else: ser.close() except SerialException: print("Serial Exception occured.") pass 

问题发生在windows 7 x64 service pack 1下。python版本是3.5。 cmd.exe实例以pipe理员身份运行。

我非常肯定当我运行脚本时COM3存在

  import serial.tools.list_ports ports = list(serial.tools.list_ports.comports()) for p in ports: print(p) 

我收到输出:

  >python list_serial.py COM3 - Prolific USB-to-Serial Comm Port (COM3) 

所以我相信端口URL / URI(idfk)是正确的。

完整的错误文本:

  Traceback (most recent call last): File "serial_reader.py", line 13, in <module> ser = serial.Serial(port='COM3',baudrate=b,parity=p,stopbits=s,bytesize=bs) File "C:\Users\FA1\AppData\Local\Programs\Python\Python35-32\lib\site-packages\serial\serialwin32.py", line 31, in __init__ SerialBase.__init__(self, *args, **kwargs) File "C:\Users\FA1\AppData\Local\Programs\Python\Python35-32\lib\site-packages\serial\serialutil.py", line 180, in __init__ self.open() File "C:\Users\FA1\AppData\Local\Programs\Python\Python35-32\lib\site-packages\serial\serialwin32.py", line 78, in open self._reconfigure_port() File "C:\Users\FA1\AppData\Local\Programs\Python\Python35-32\lib\site-packages\serial\serialwin32.py", line 220, in _reconfigure_port raise SerialException("Cannot configure port, something went wrong. Original message: %r" % ctypes.WinError()) serial.serialutil.SerialException: Cannot configure port, something went wrong. Original message: OSError(22, 'The parameter is incorrect.', None, 87) 

我已经确保驱动程序安装正确,但是我收到了2个不同的串行转换器的错误。 所以我相信这个问题不是硬件或驱动相关的。

你说你应该知道设备的设置,但这不是一个完美的世界。 但Windows确实允许通过GetCommProperties查询通信设备的属性。 pySerial似乎不支持这个,但你可以使用ctypes来直接调用这个函数。

以下定义了一个get_comm_properties函数来查询通信端口的可设置属性。 它接受现有的设备句柄(例如, _handle端口的_handle属性)或DOS设备名称(如COM1或WinAPI设备名称,如\\.\COM1

 import collections import ctypes from ctypes import wintypes kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 3 INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value ERROR_FILE_NOT_FOUND = 0x0002 class COMMPROP(ctypes.Structure): _fields_= (('wPacketLength', wintypes.WORD), ('wPacketVersion', wintypes.WORD), ('dwServiceMask', wintypes.DWORD), ('dwReserved1', wintypes.DWORD), ('dwMaxTxQueue', wintypes.DWORD), ('dwMaxRxQueue', wintypes.DWORD), ('dwMaxBaud', wintypes.DWORD), ('dwProvSubType', wintypes.DWORD), ('dwProvCapabilities', wintypes.DWORD), ('dwSettableParams', wintypes.DWORD), ('dwSettableBaud', wintypes.DWORD), ('wSettableData', wintypes.WORD), ('wSettableStopParity', wintypes.WORD), ('dwCurrentTxQueue', wintypes.DWORD), ('dwCurrentRxQueue', wintypes.DWORD), ('dwProvSpec1', wintypes.DWORD), ('dwProvSpec2', wintypes.DWORD), ('wcProvChar', wintypes.WCHAR * 1)) class _CONST: COMMPROP_INITIALIZED = 0xE73CF52E SP_SERIALCOMM = 0x00000001 BAUD_USER = 0x10000000 # programmable baud rate DATABITS_16X = 0x0020 # hardware wide data path PROV_SUBTYPE = collections.OrderedDict([ ('UNSPECIFIED', 0x00000000), ('RS232', 0x00000001), ('PARALLELPORT', 0x00000002), ('RS422', 0x00000003), ('RS423', 0x00000004), ('RS449', 0x00000005), ('MODEM', 0x00000006), ('FAX', 0x00000021), ('SCANNER', 0x00000022), ('NETWORK_BRIDGE', 0x00000100), ('LAT', 0x00000101), ('TCPIP_TELNET', 0x00000102), ('X25', 0x00000103), ]) PROV_CAPABILITIES = collections.OrderedDict([ ('DTRDSR', 0x0001), # data-terminal-ready / data-set-ready ('RTSCTS', 0x0002), # request-to-send / clear-to-send ('RLSD', 0x0004), # receive-line-signal-detect ('PARITY_CHECK', 0x0008), ('XONXOFF', 0x0010), # XON/XOFF flow control ('SETXCHAR', 0x0020), # settable XON/XOFF ('TOTALTIMEOUTS', 0x0040), # total (elapsed) time-outs ('INTTIMEOUTS', 0x0080), # interval time-outs ('SPECIALCHARS', 0x0100), ('16BITMODE', 0x0200), ]) SETTABLE_PARAMS = collections.OrderedDict([ ('PARITY', 0x0001), ('BAUD', 0x0002), ('DATABITS', 0x0004), ('STOPBITS', 0x0008), ('HANDSHAKING', 0x0010), # flow control ('PARITY_CHECK', 0x0020), ('RLSD', 0x0040), # receive-line-signal-detect ]) SETTABLE_BAUD = collections.OrderedDict([ (75, 0x00000001), (110, 0x00000002), (134.5, 0x00000004), (150, 0x00000008), (300, 0x00000010), (600, 0x00000020), (1200, 0x00000040), (1800, 0x00000080), (2400, 0x00000100), (4800, 0x00000200), (7200, 0x00000400), (9600, 0x00000800), (14400, 0x00001000), (19200, 0x00002000), (38400, 0x00004000), (56000, 0x00008000), (57600, 0x00040000), (115200, 0x00020000), (128000, 0x00010000), ]) SETTABLE_DATA = collections.OrderedDict([ (5, 0x0001), # 5 data bits (6, 0x0002), # 6 data bits (7, 0x0004), # 7 data bits (8, 0x0008), # 8 data bits (16, 0x0010), # 16 data bits ]) SETTABLE_STOP = collections.OrderedDict([ (1, 0x0001), # 1 stop bit (1.5, 0x0002), # 1.5 stop bits (2, 0x0004), # 2 stop bits ]) SETTABLE_PARITY = collections.OrderedDict([ ('NONE', 0x0100), # no parity ('ODD', 0x0200), # odd parity ('EVEN', 0x0400), # even parity ('MARK', 0x0800), # mark parity ('SPACE', 0x1000), # space parity ]) @property def max_baud(self): s = self.dwMaxBaud m = self._CONST.SETTABLE_BAUD if s == self._CONST.BAUD_USER: return 0 else: return m[s] @property def prov_subtype(self): s = self.dwProvSubType m = self._CONST.PROV_SUBTYPE return [x for x, c in m.items() if c & s] @property def prov_capabilities(self): s = self.dwProvCapabilities m = self._CONST.PROV_CAPABILITIES return [x for x, c in m.items() if c & s] @property def settable_params(self): s = self.dwSettableParams m = self._CONST.SETTABLE_PARAMS return [x for x, c in m.items() if c & s] @property def settable_baud(self): s = self.dwSettableBaud m = self._CONST.SETTABLE_BAUD return [x for x, c in m.items() if c & s] @property def user_settable_baud(self): return bool(self.dwSettableBaud & self._CONST.BAUD_USER) @property def settable_data(self): s = self.wSettableData m = self._CONST.SETTABLE_DATA return [x for x, c in m.items() if c & s] @property def wide_settable_data(self): return bool(self.wSettableData & self._CONST.DATABITS_16X) @property def settable_stop(self): s = self.wSettableStopParity m = self._CONST.SETTABLE_STOP return [x for x, c in m.items() if c & s] @property def settable_parity(self): s = self.wSettableStopParity m = self._CONST.SETTABLE_PARITY return [x for x, c in m.items() if c & s] LPCOMMPROP = ctypes.POINTER(COMMPROP) class SECURITY_ATTRIBUTES(ctypes.Structure): _fields_ = (('nLength', wintypes.DWORD), ('lpSecurityDescriptor', wintypes.LPVOID), ('bInheritHandle', wintypes.BOOL)) LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES) kernel32.CreateFileW.restype = wintypes.HANDLE kernel32.CreateFileW.argtypes = ( wintypes.LPCWSTR, # _In_ lpFileName wintypes.DWORD, # _In_ dwDesiredAccess wintypes.DWORD, # _In_ dwShareMode LPSECURITY_ATTRIBUTES, # _In_opt_ lpSecurityAttributes wintypes.DWORD, # _In_ dwCreationDisposition wintypes.DWORD, # _In_ dwFlagsAndAttributes wintypes.HANDLE) # _In_opt_ hTemplateFile kernel32.CloseHandle.argtypes = (wintypes.HANDLE,) kernel32.GetCommProperties.argtypes = ( wintypes.HANDLE, # _In_ hFile LPCOMMPROP) # _Out_ lpCommProp def get_comm_properties(handle_or_port): if isinstance(handle_or_port, str): handle = kernel32.CreateFileW( handle_or_port, GENERIC_READ | GENERIC_WRITE, 0, # exclusive access None, # default security OPEN_EXISTING, 0, None) if handle == INVALID_HANDLE_VALUE: raise ctypes.WinError(ctypes.get_last_error()) close_handle = True else: handle = handle_or_port close_handle = False try: prop = COMMPROP() if not kernel32.GetCommProperties(handle, ctypes.byref(prop)): raise ctypes.WinError(ctypes.get_last_error()) finally: if close_handle: kernel32.CloseHandle(handle) return prop 

例:

 if __name__ == '__main__': for i in range(1, 10): port = r'\\.\COM%d' % i try: prop = get_comm_properties(port) except WindowsError as e: if e.winerror == ERROR_FILE_NOT_FOUND: continue print('%s properties' % port) x = prop.dwMaxTxQueue if prop.dwMaxTxQueue else 'no limit' print('\tMax output buffer size: %s' % x) x = prop.dwMaxRxQueue if prop.dwMaxRxQueue else 'no limit' print('\tMax input buffer size: %s' % x) x = prop.dwCurrentTxQueue if prop.dwCurrentTxQueue else 'unavailable' print('\tCurrent output buffer size: %s' % x) x = prop.dwCurrentRxQueue if prop.dwCurrentRxQueue else 'unavailable' print('\tCurrent input buffer size: %s' % x) x = prop.max_baud if prop.max_baud else 'user programmable' print('\tMax baud rate: %s' % x) print('\tProvider subtypes:\n\t\t%s' % '\n\t\t'.join(prop.prov_subtype)) print('\tProvider capabilities:\n\t\t%s' % '\n\t\t'.join(prop.prov_capabilities)) print('\tSettable parameters:\n\t\t%s' % '\n\t\t'.join(prop.settable_params)) print('\tSettable baud rates:\n\t\t%s' % '\n\t\t'.join([str(x) for x in prop.settable_baud])) print('\tSettable user baud rates: %s' % prop.user_settable_baud) print('\tSettable data bits:\n\t\t%s' % '\n\t\t'.join([str(x) for x in prop.settable_data])) print('\tSettable wide data bits: %s' % prop.wide_settable_data) print('\tSettable stop bits:\n\t\t%s' % '\n\t\t'.join([str(x) for x in prop.settable_stop])) print('\tSettable parity:\n\t\t%s' % '\n\t\t'.join(prop.settable_parity)) 

输出:

 \\.\COM1 properties Max output buffer size: no limit Max input buffer size: no limit Current output buffer size: unavailable Current input buffer size: 4096 Max baud rate: user programmable Provider subtypes: RS232 RS422 RS449 FAX LAT X25 Provider capabilities: DTRDSR RTSCTS RLSD PARITY_CHECK XONXOFF SETXCHAR TOTALTIMEOUTS INTTIMEOUTS Settable parameters: PARITY BAUD DATABITS STOPBITS HANDSHAKING PARITY_CHECK RLSD Settable baud rates: 75 110 134.5 150 300 600 1200 1800 2400 4800 7200 9600 14400 19200 38400 56000 57600 115200 Settable user baud rates: True Settable data bits: 5 6 7 8 Settable wide data bits: False Settable stop bits: 1 1.5 2 Settable parity: NONE ODD EVEN MARK SPACE 

波特率<100被视为Windows 7中的配置错误。因此,以50,75波特开始循环都会产生错误。 110波特不返回错误。