Ubuntu Linux下无法读写串口问题排查求助
问题描述
我编写了如下Python脚本用于串口读写,在Windows系统下可正常操作COM3端口(连接的是能通过串口返回数据的Arduino)。但在Ubuntu Linux系统中使用/dev/tty2端口时无法正常工作:已将自身加入对应用户组,串口对象显示已连接,但连接后无任何数据交互。另外,/dev/tty1和/dev/tty3无法连接,这是否说明/dev/tty2的权限配置正常?实际上我更希望连接/dev/tty1,但始终无法获取该端口的访问权限。
# This test file will write / read to a COM port on Windows but not on # Ubuntu Linux against "/dev/tty2". Why? import serial while True: try: ser = serial.Serial('/dev/tty2', 9600, timeout = 1) if ser: print("Connected to: ", ser.name) except serial.SerialException as e: print(f"Error opening serial port: {e}") exit() try: ser.write(b"Test from Python\n") while True: data = ser.readline() if data: print("Received: ", data.decode().strip()) except Exception as e: print(f"Error during communication: {e}") finally: # Close the serial port if ser.is_open: ser.close() print("Serial port closed")
问题分析与解决方法
1. 核心误区:Linux下的TTY设备区分
/dev/tty1、/dev/tty2这类设备是虚拟控制台终端,并非Arduino使用的串口设备。这就是为什么:
- 你能打开
/dev/tty2但无数据交互:它只是系统的控制台窗口,和Arduino无关 /dev/tty1//dev/tty3无法连接:这些控制台通常被系统占用,普通用户没有访问权限
Arduino在Linux下会被识别为/dev/ttyACM*(大部分官方板)或/dev/ttyUSB*(第三方USB转串口芯片的板)。
2. 找到正确的Arduino串口设备
- 插拔Arduino前后,执行以下命令对比,找到新增的设备:
ls /dev/ttyACM* /dev/ttyUSB* - 或者查看内核日志确认设备路径:
日志中会显示类似dmesg | grep ttyusb 1-1.2: ch341-uart converter now attached to ttyUSB0的信息,ttyUSB0就是目标端口。
3. 配置串口访问权限
- 将当前用户加入
dialout组(Linux下串口设备的默认所属组):sudo usermod -aG dialout $USER - 注销并重新登录,让权限变更生效
- 验证权限:执行
ls -l /dev/ttyACM0(替换为你的设备路径),确认所属组为dialout,且当前用户有读写权限。
4. 调整Python脚本
将脚本中的串口路径替换为找到的正确设备(比如/dev/ttyACM0),同时优化脚本逻辑(原外层while循环会重复打开串口,易导致异常):
import serial import time def main(): # 替换为正确的串口设备路径 port = '/dev/ttyACM0' baud_rate = 9600 ser = None try: ser = serial.Serial(port, baud_rate, timeout=1) print(f"Connected to: {ser.name}") while True: # 发送测试数据 ser.write(b"Test from Python\n") # 读取返回数据 data = ser.readline() if data: print(f"Received: {data.decode().strip()}") time.sleep(0.1) except serial.SerialException as e: print(f"Error opening serial port: {e}") except Exception as e: print(f"Error during communication: {e}") finally: if ser and ser.is_open: ser.close() print("Serial port closed") if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者DaveFer
相关产品推荐
相关产品推荐

