开发者

Python中pyserial 实现模拟串口通信的示例详解

目录
  • 一、串口通信的基本概念
    • 1.1 什么是串口通信?
    • 1.2 串口通信的关键参数
  • 二、python 串口通信的核心库:pyserial
    • 2.1 安装 pyserial
    • 2.2 核心功能
  • 三、Python 模拟串口通信的完整示例
    • 3.1 列出可用的串口设备
    • 3.2 配置并打开串口
    • 3.3 发送数据到串口
    • 3.4 从串口接收数据
      • 方法一:读取指定字节数
      • 方法二:读取一行数据(直到换行符)
    • 3.5 完整的收发示例
    • 四、常见问题与解决方案
      • 4.1 串口未找到或无法打开
        • 4.2 数据接收不完整
          • 4.3 编码错误
          • 五、实际应用场景示例
            • 5.1 与 STM32 通信
              • 5.2 模拟设备调试
              • 六、总结

                在嵌入式系统开发、工业自动化和物联网(IoT)设备调试中,串口通信是一种基础且重要的技术。Python通过 pyserial 库提供了强大的串口通信支持,使得开发者能够快速实现串口数据的发送与接收。本文将详细介绍如何使用 Python 模拟串口通信,并通过实际代码示例演示其核心功能和应用场景。

                一、串口通信的基本概念

                1.1 什么是串口通信?

                串口通信(Serial Communication)是一种通过串行接口传输数据的通信方式。它通过一根数据线逐位传输数据,常用于设备间的点对点通信。常见的应用场景包括:

                • 与嵌入式设备(如 STM32、Arduino)交互。
                • 工业设备的调试与监控。
                • GPS 模块、传感器等外设的数据采集。

                1.2 串口通信的关键参数

                • 波特率(Baud Rate):数据传输速率,单位为 bit/s。常见值如 9600、115200。
                • 数据位(Data Bits):每帧数据的位数,通常为 7 或 8 位。
                • 停止位(Stop Bits):每帧数据的结束标志,通常为 1 或 2 位。
                • 校验位(Parity):用于错误检测,可选无校验(None)、奇校验(Odd)、偶校验(Even)等。
                • 超时时间(Timeout):读取数据时等待的最长时间。

                二、Python 串口通信的核心库:pyserial

                2.1 安装 pyserial

                使用 pip 安装 pyserial 库:

                pip install pyserial
                

                2.2 核心功能

                • 打开/关闭串口:通过 Serial 类管理串口连接。
                • 数据发送:使用 write() 方法发送字节数据。
                • 数据接收:使用 read()readline() 等方法接收数据。
                • 串口参数配置:灵活设置波特率、数据位、校验位等。

                三、Python 模拟串口通信的完整示例

                3.1 列出可用的串口设备

                在开始通信前,可以先查询系统中可用的串口设备:

                import serial.tools.list_ports
                
                ports = list(serial.tools.list_ports.comports())
                for port in ports:
                    print(f"设备名: {port.device}, 描述: {port.description}")
                

                运行结果(以 Windows 为例):

                设备名: COM1, 描述: 通信端口 (COM1)

                设备名: COM3, 描述: com0com - serial port emulator (COM3)

                设备名: COM4, 描述: com0com - serial port emulator (COM4)

                3.2 配置并打开串口

                以下代码演示如何配置串口参数并打开串口:

                import serial
                
                # 配置串口参数
                ser = serial.Serial(
                    port="COM3",         js # 串口号(需根据实际设备修改)
                    baudrate=115200,      # 波特率
                    bytesize=serial.EIGHTBITS,  # 数据位:8 位
                    parity=serial.PARITY_NONE,  # 校验位:无校验
                    stopbits=serial.STOPBITS_ONE,  # 停止位:1 位
                    timeout=0.5           # 读取超时时间(秒)
                )
                
                # 检查串口是否成功打开
                if ser.is_open:
                    print(f"串口 {ser.port} 已成功打开")
                else:
                    print(f"无法打开串口 {ser.port}")
                

                3.3 发送数据到串口

                通过 write() 方法向串口发送数据。注意,发送的数据必须是字节格式(bytes):

                def send_data(ser, data):
                    if ser.is_open:
                        ser.write(data.encode('utf-8'))  # 将字符串编码为字节
                        print(f"发送数据: {data}")
                    else:
                        print("串口未打开,无法发送数据")
                
                # 示例:发送 "Hello, Serial!" 到串口
                send_data(ser, "Hello, Serial!")
                

                3.4 从串口接收数据

                接收数据的方式有多种,以下是常见的两种方法:

                方法一:读取指定字节数

                def read_fixed_bytes(ser, num_bytes):
                    if ser.in_waiting >= num_bytes:  # 检查缓冲区是否有足够数据
                        data = ser.read(num_bytes)   # 读取指定字节数
                        print(f"接收到数据({len(data)} 字节): {data.decode('utf-8')}")
                    else:
                        print("缓冲区数据不足,未读取到完整数据")
                
                # 示例:读取 10 字节数据
                read_fixed_bytes(ser, 10)
                

                方法二:读取一行数据(直到换行符)

                def read_line(ser):
                    if ser.in_waiting > 0:  # 检查是否有数据可读
                        line = ser.readline()  # 读取一行数据
                        print(f"接收到一行数据: {line.decode('utf-8').strip()}")
                    else:
                        print("未接收到数据")
                
                # 示例:读取一行数据
                read_line(ser)
                

                3.5 完整的收发示例

                以下代码演示了一个完整的串口通信流程,包括发送数据和循环接收响应:

                import serial
                import time
                
                # 配置串口
                ser = serial.Serial(
                    port="CandroidOM3",
                    baudrate=9600,
                    timeout=1
                )
                
                # 发送数据并接收响应
                def communicate():
                    if not ser.is_open:
                        print("串口未打开,无法通信")
                        return
                
                    while True:
                        # 发送数据
                        command = input("请输入要发送的数据(输入 'exit' 退出): ")
                        if command.lower() == 'exit':
                            break
                        ser.write(command.encode('utf-8'))
                
                        # 接收响应
                        time.sleep(0.5)  # 等待设备响应
                        if ser.in_waiting > 0:
                            response = ser.readline().decode('utf-8').strip()
                            print(f"设备响应: {response}")
                        else编程客栈:
                            print("未收到设备响应")
                
                    # 关闭串口
                    ser.close()
                    print("串口已关闭")
                
                if __name__ == "__main__":
                    communicate()
                

                四、常见问题与解决方案

                4.1 串口未找到或无法打开

                • 原因:串口号错误或设备未连接。
                • 解决方法:使用 serial.tools.list_ports 查询可用串口,确认设备是否正常连接。

                4.2 数据接收不完整

                • 原因:波特率设置不一致,或读取操作未等待足够时间。
                • 解决方法:确保发送端和接收端的波特率一致,并适当增加 timeout 或 time.sleep() 的等待时间。

                4.3 编码错误

                • 原因:数据解码时使用的字符集与实际数据不匹配。
                • 解决方法:尝试使用 utf-8latin-1 等不同编码方式,或直接处理字节数据(bytes)。

                五、实际应用场景示例

                5.1 与 STM32 通信

                假设 STM32 通过串口返回温度传感器数据,Python 可以实时读取并显示:

                while True:
                    if ser.in_waiting > 0:
                        data = ser.readline().decode('utf-8').strip()
                        print(f"当前温度: {data} ℃")
                    time.sleep(0.1)
                

                5.2 模拟设备调试

                通过 pyserial 模拟设备响应,无需真实硬件即可测试上位机逻辑:

                # 模拟设备响应
                if command == "GET_STATUS":
                    ser.write(b"Status: OK\r\n")
                elif command == "GET_VERSION":
                    ser.write(b"Version: 1.0.0\r\n")
                

                六、总结

                通过 pysphperial 库,Python 能够高效地实现串口通信,适用于调试硬件设备、开发上位机程序等多种场景。本文通过详细代码示例,演示了串口的配置、数据发送与接收的核心操作,并提供了常见问题的解决方案。掌握这些技能后,开发者可以更轻松地与嵌入式设备、传感器或其他串口设备进行交互,提升开发效率和调试能力。

                扩展学习

                • 探索 pyserial 的高级功能,如异步通信(asyncio 集成)。
                • 结合 GUI 框架(如 PyQt)开发串口调试工具。
                • 使用 pySerial-asyncio 实现非阻塞串口通信。

                到此这篇关于Python中pyserial 实现模拟串口通信的示例详解的文章就介绍到这了,更多相关Python 模拟串口通信内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.cpythonppcns.com)! 

                0

                上一篇:

                下一篇:

                精彩评论

                暂无评论...
                验证码 换一张
                取 消

                最新开发

                开发排行榜