杰瑞科技汇

Python串口通信如何正确配置与使用?

Of course! Using Python with serial ports is a common task for communicating with hardware like microcontrollers (Arduino, Raspberry Pi Pico), GPS modules, sensors, and other embedded systems.

Python串口通信如何正确配置与使用?-图1
(图片来源网络,侵删)

The most popular and recommended library for this is pyserial.

Here's a comprehensive guide covering everything from installation to advanced usage.


Installation

First, you need to install the pyserial library. Open your terminal or command prompt and run:

pip install pyserial

Finding Your Serial Port

Before you can communicate, you need to know the name of your serial port. On different operating systems, these names look different:

  • Windows: Looks like a COM port (e.g., COM3, COM10). You can find these in the Device Manager under "Ports (COM & LPT)".
  • Linux: Typically starts with /dev/tty (e.g., /dev/ttyUSB0 for a USB-to-serial adapter, /dev/ttyACM0 for an Arduino).
  • macOS: Usually starts with /dev/tty (e.g., /dev/tty.usbserial-XXXX or /dev/tty.usbmodemXXXX).

How to Find it Programmatically with pyserial

You can use pyserial to list all available serial ports. This is extremely useful for making your code portable.

import serial.tools.list_ports
# Get a list of all available ports
ports = serial.tools.list_ports.comports()
print("Available Serial Ports:")
for port in ports:
    print(f"Device: {port.device}")
    print(f"  Name:   {port.name}")
    print(f"  Description: {port.description}")
    print(f"  Hardware ID: {port.hwid}")
    print("-" * 20)
# A more direct way to get just the device names
port_list = [port.device for port in ports]
print(f"\nPort List: {port_list}")

Basic Usage: Reading and Writing

This is the core of serial communication. The key is to use a try...finally block to ensure the serial port is always closed, even if an error occurs.

Example 1: Simple Read and Write

This example connects to a port, sends a command, and waits for a response.

import serial
import time
# --- Configuration ---
# Replace 'COM3' with your actual serial port
SERIAL_PORT = 'COM3' 
BAUD_RATE = 9600  # Must match the baud rate of the connected device
try:
    # 1. Initialize the serial connection
    # The 'with' statement is recommended as it automatically handles closing the port
    with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) as ser:
        print(f"Connected to {ser.name} at {ser.baudrate} baud.")
        # 2. Write data to the serial port
        # Data must be in bytes. Use .encode() to convert a string.
        command_to_send = "GET_DATA\n" # Example command
        ser.write(command_to_send.encode('utf-8'))
        print(f"Sent: {command_to_send}")
        # 3. Read data from the serial port
        # ser.in_waiting checks how many bytes are in the buffer
        if ser.in_waiting > 0:
            # ser.readline() reads until a newline or timeout
            received_data = ser.readline()
            # Decode the bytes back to a string
            print(f"Received: {received_data.decode('utf-8').strip()}")
        else:
            print("No data received within timeout period.")
except serial.SerialException as e:
    print(f"Error: Could not open serial port {SERIAL_PORT}.")
    print(f"Details: {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

Example 2: Continuous Reading (e.g., from a sensor)

This is a common pattern for reading a stream of data from a device.

import serial
import time
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 115200
try:
    with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) as ser:
        print(f"Connected to {ser.name}. Starting continuous read...")
        ser.reset_input_buffer() # Clear any old data
        while True:
            if ser.in_waiting > 0:
                line = ser.readline()
                # Decode and strip to remove newline characters
                print(line.decode('utf-8').strip())
            # A small sleep to prevent the loop from consuming 100% CPU
            time.sleep(0.1) 
except KeyboardInterrupt:
    print("\nProgram terminated by user.")
except serial.SerialException as e:
    print(f"Error: Could not open serial port {SERIAL_PORT}.")
    print(f"Details: {e}")

Key Serial Object Properties and Methods

Here are the most important attributes and methods you'll use:

Category Method/Attribute Description
Connection serial.Serial(port, baudrate, ...) Constructor to open a port.
ser.close() Closes the port. Handled automatically by with.
ser.is_open Boolean, True if the port is open.
Writing ser.write(data) Writes data (must be bytes) to the port.
ser.write_timeout Timeout for write operations.
Reading ser.read(size) Reads exactly size bytes from the port.
ser.readline() Reads until a newline (\n) or timeout.
ser.readall() Reads all available data in the buffer.
ser.in_waiting Number of bytes in the input buffer.
ser.timeout Timeout for read operations (default is None, which blocks forever).
Configuration ser.baudrate Get/set the baud rate.
ser.parity Get/set parity (serial.PARITY_NONE, serial.PARITY_EVEN, etc.).
ser.bytesize Get/set data size (e.g., serial.EIGHTBITS).
ser.stopbits Get/set stop bits (e.g., serial.STOPBITS_ONE).
Control ser.reset_input_buffer() Clears the input buffer.
ser.reset_output_buffer() Clears the output buffer.
ser.flush() Waits until all data in the output buffer is written.

Troubleshooting Common Issues

  1. SerialException: could not open port 'COM3': Permission denied

    • Cause (Linux/macOS): You don't have permission to access the device.
    • Solution: Add your user to the dialout group (Linux). You may need to log out and log back in for the change to take effect.
      sudo usermod -a -G dialout $USER
    • Cause (Windows): Another program (like Arduino IDE, PuTTY) is already using the port.
    • Solution: Close all other programs that might be using the COM port.
  2. No data is being received, or the data is garbled.

    • Cause #1: Mismatched Baud Rate. The baud rate in your Python script must exactly match the baud rate configured on the device you're talking to.
    • Cause #2: Hardware Flow Control (RTS/CTS). If enabled on one end but not the other, it can block communication. Try disabling it with ser.rtscts = False.
    • Cause #3: Line Endings. Devices expect a specific line ending (e.g., \n, \r\n, or just \r). If ser.readline() isn't working, try ser.read_until(b'\n') and ensure your write() command includes the correct ending.
  3. TimeoutError or ser.readline() returns empty bytes.

    • Cause: The device hasn't sent any data within the timeout period.
    • Solution: Increase the timeout value (e.g., timeout=2). Make sure your device is actually sending data and that your wiring is correct.
  4. UnicodeDecodeError when trying to decode received bytes.

    • Cause: The device is sending non-text data (binary data), but you're trying to treat it as a string (UTF-8).
    • Solution: If you expect binary data, don't decode it. Work with the bytes object directly. If you expect text, check the encoding. Sometimes ASCII is used instead of UTF-8: data.decode('ascii').
分享:
扫描分享到社交APP
上一篇
下一篇