在Python中可以使用pyserial库来连接串口并发送命令。pyserial是一个用于串行通信的第三方库支持多种平台。首先需要安装pyserial库。可以使用pip进行安装pip install pyserial使用pyserial连接串口并发送命令以下是一个示例代码展示了如何使用pyserial连接串口并发送测试命令import serial import time def connect_serial(port, baudrate): try: # 创建Serial对象并打开串口 ser serial.Serial(port, baudrate, timeout1) print(f成功连接到串口 {port}波特率 {baudrate}) return ser except serial.SerialException as e: print(f无法连接到串口{e}) return None def send_command(ser, command): if ser is not None: try: # 发送命令并添加换行符 ser.write((command \n).encode()) print(f已发送命令{command}) # 等待响应 time.sleep(1) # 读取响应数据 response ser.read_all().decode() print(f接收到的响应{response}) except Exception as e: print(f发送命令时发生错误{e}) def close_serial(ser): if ser is not None: ser.close() print(已关闭串口) # 示例参数 port COM3 # Windows上的端口例如 COM3 # port /dev/ttyUSB0 # Linux上的端口例如 /dev/ttyUSB0 baudrate 9600 # 波特率根据实际情况设置 # 测试命令 command TEST_COMMAND # 连接串口 ser connect_serial(port, baudrate) # 发送测试命令 send_command(ser, command) # 关闭串口 close_serial(ser)支持发送HEX格式的命令兼容代码参考import serial import time def connect_serial(port, baudrate, timeout1): 打开串口返回 Serial 对象失败返回 None。 try: ser serial.Serial(port, baudrate, timeouttimeout) print(f成功连接到串口 {port}波特率 {baudrate}) return ser except serial.SerialException as e: print(f无法连接到串口{e}) return None def parse_hex(hex_str): 将 HEX 字符串解析为 bytes。 支持格式 01 02 0A FF 01020AFF 0x01,0x02,0x0A 01-02-0A-FF # 去掉常见分隔符和 0x 前缀 cleaned ( hex_str.strip() .replace(0x, ) .replace(0X, ) .replace(,, ) .replace(-, ) .replace(:, ) ) cleaned .join(cleaned.split()) # 去掉所有空白 if len(cleaned) % 2 ! 0: raise ValueError(fHEX 字符串长度必须为偶数{hex_str}) try: return bytes.fromhex(cleaned) except ValueError as e: raise ValueError(f非法的 HEX 字符串{hex_str}{e}) def send_command(ser, command, modeascii, append_newlineTrue): 向串口发送命令。 :param ser: 已打开的 Serial 对象 :param command: 命令内容。modeascii 时为字符串modehex 时为 HEX 字符串 :param mode: ascii 或 hex :param append_newline: 仅 ascii 模式有效是否在末尾追加 \n if ser is None: print(串口未打开无法发送。) return # ---------- 1. 把用户输入转换成字节流 ---------- try: if mode hex: payload parse_hex(command) # HEX/二进制协议通常没有“换行符”概念强制不追加 if append_newline: print(提示HEX 模式下 append_newline 被忽略。) elif mode ascii: text command (\n if append_newline else ) payload text.encode(utf-8) else: raise ValueError(f不支持的模式{mode}只能是 ascii 或 hex) except ValueError as e: print(f命令解析失败{e}) return # ---------- 2. 发送 ---------- try: ser.reset_input_buffer() # 清掉上一次残留避免响应串台 ser.write(payload) ser.flush() # 确保数据真正写出 if mode hex: print(f已发送 HEX{payload.hex( ).upper()}) else: print(f已发送 ASCII{command!r}) except Exception as e: print(f发送命令时发生错误{e}) return # ---------- 3. 读取响应 ---------- response read_response(ser) if response: print(f接收到的响应HEX{response.hex( ).upper()}) # 尝试按文本显示失败则跳过 try: print(f接收到的响应ASCII{response.decode(utf-8)!r}) except UnicodeDecodeError: print(接收到的响应无法按 UTF-8 解码仅显示 HEX。) else: print(未接收到响应可能超时或设备无回复。) def read_response(ser, idle_timeout1.0, max_bytes4096): 读取串口响应在 idle_timeout 秒内没有新数据就认为读取结束。 比 time.sleep(1) read_all() 更稳健。 data bytearray() deadline time.time() idle_timeout last_rx time.time() while time.time() deadline and len(data) max_bytes: waiting ser.in_waiting if waiting: data.extend(ser.read(waiting)) last_rx time.time() deadline last_rx idle_timeout # 每收到数据就重置空闲计时 else: time.sleep(0.01) return bytes(data) def close_serial(ser): if ser is not None and ser.is_open: ser.close() print(已关闭串口) # 示例 if __name__ __main__: port COM3 # WindowsLinux 用 /dev/ttyUSB0 baudrate 9600 ser connect_serial(port, baudrate) if ser is None: raise SystemExit(1) try: # 示例 1发送 ASCII 文本命令自动加换行 send_command(ser, TEST_COMMAND, modeascii, append_newlineTrue) # 示例 2发送 HEX 命令不带换行 # 等价于发送字节 0x01 0x03 0x00 0x00 0x00 0x0A 0xCD 0xC5 send_command(ser, 01 03 00 00 00 0A CD C5, modehex) # 示例 3紧凑写法的 HEX send_command(ser, 01030000000ACDC5, modehex) finally: close_serial(ser)原理说明原理说明1. 串口发送的本质是字节流不是字符串ser.write()的参数必须是bytes/bytearray不是str。原代码(command \n).encode()做的是两件事command \n按文本协议的约定在命令后追加换行符作为帧结束符.encode()按某种字符编码默认 UTF-8把字符串转成字节。这套流程只适用于“人可读的文本命令”例如ATRST\r\n。一旦设备要求的是二进制/HEX 协议例如 Modbus RTU 的01 03 00 00 00 0A CD C5再走.encode()就会把字符0、1、空格等按 ASCII 编码发出去得到的是b01 03 ...这串文本的 ASCII 字节而不是真正的二进制帧。2. HEX 模式的核心是bytes.fromhex()bytes.fromhex()把01 03 0A FF这样的十六进制文本解析成真正的字节b\x01\x03\x0a\xff。它允许空格分隔但不允许0x前缀、逗号、冒号等所以parse_hex()先做一次规范化清洗去掉0x/0X把,-:统一替换为空格去掉所有空白校验长度为偶数每个字节两位十六进制这一步是 HEX 支持的关键用户输入的是“十六进制表示”程序要把它还原成“二进制字节”。3. 为什么 HEX 模式不应自动追加\n换行符是文本协议的帧分隔约定。二进制协议Modbus、自定义帧、二进制指令的帧边界通常由帧头、长度字段、校验码CRC/LRC或固定超时决定而不是\n。如果强行在 HEX 帧后追加0x0A会破坏帧结构导致 CRC 校验失败让设备把0x0A当成下一帧的起始字节。所以优化后的代码在modehex时忽略append_newline并给出提示。如果某些设备确实需要0x0D 0x0A结尾应由调用者显式写进 HEX 字符串例如01 03 ... 0D 0A这样语义清晰、可控。