Python串口通信模块PySerial使用教程(CH340 USB TTL转接芯片)

1. CH340 USB TTL介绍

TTL 一般是从单片机或者芯片中发出的电平,高电平为 5V(51单片机)或者 3.3V(STM32)。USB 转 TTL 模块的作用就是把电平转换到双方都能识别进行通信。

单片机通信接口的电平逻辑和 PC 机通信接口的电平逻辑不同,PC 机上的通信接口有 USB 接口,相应电平逻辑遵照 USB 原则;还有 DB9 接口(九针口),相应电平逻辑遵照 RS-232 原则。

单片机上的串行通信通过单片机的 RXD、TXD、VCC、GND 四个引脚,相应电平逻辑遵照 TTL 原则。

USB 是一种串口(串口是一大类接口,包括但不仅限于 RS232),它拥有复杂的通讯协议,支持热插拔,并可以以非常快的速度传输数据。串口,是指 RS232 串口,这是一种几乎没有协议的传输接口,可以直接收发数据。

USB 转 TTL 串口模块是一个非常实用的工具,可以测试模块的 UART 串口通信和通过单片机的 UART 接口给单片机等下载程序。能够在电脑上的串口助手软件非常直观的显示出串口设备返回的数据以及发送相应的控制数据给串口设备。常见的有 CP2102、PL2303、FT232、CH340 等串口芯片方案的 USB 转串口模块。以下以 CH340 串口模块为例,对其进行自检测试。

  • 串口发送工作原理:串口应用发送数据 -> USB 串口驱动获取数据 -> 驱动将数据经过 USB 通道发送给 USB 串口设备 -> USB 串口设备接收到数据通过串口发送
  • 串口接收工作原理:USB 串口设备接收串口数据 -> 将串口数据经过 USB 打包后上传给 USB 主机 -> USB 串口驱动获取到通过 USB 上传的串口数据 -> 驱动将数据保存在串口缓冲区提供给串口应用读取

我们打开串口调试工具,将 CH340 USB TTL 模块的 TXDRXD 引脚短接(用同一跟线接在一起,这样相当于自己给自己发送信息),然后插入电脑,打开设备管理器,确保电脑已经识别到端口(USB-SERIAL CH340 (COM4)),注意 COM4 后面的数字可能是随机的,不一定是这个端口。

尝试给自己发送信息,选择所设置好的串口,打开串口,输入并发送文字,查看是否收到,或收到的字符是否一致,如果能自收自发数据,且收发数据一致,就说明驱动配置完成,并且模块功能完整:

在这里插入图片描述

注意事项:

  • CH340 模块插在 USB2.0 口时,5V 排针输出口电流只有 500MA 左右,如过要接的功率比较的大模块建议接 USB3.0 或者给大功率模块单独外接电源且共地;
  • 切勿将 VCCGND 短接,否则会烧坏模块,发现插上后模块灯不亮或模块发烫严重请立即拔掉检测是否接反或短路。

2. PySerial教程

串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。串口是计算机上一种非常通用的设备通信协议。

PySerial 模块封装了 Python 对串口的访问,为多平台的使用提供了统一的接口。它支持 Windows、Linux、OSX、BSD 等多个平台。如果要使用 PySerial 模块,首先必须保证 Python 版本高于 Python 2.7 或者 Python 3.4。另外,如果你是用的是 Windows 系统,那必须使用 Win7 及以上的版本。

首先我们安装 PySerial:

pip install pyserial

(1)确定电脑是否有可用的串口,并确定可用串口的串口号

import serial
import serial.tools.list_ports

ports_list = list(serial.tools.list_ports.comports())  # 获取所有串口设备实例
if len(ports_list) <= 0:
    print("无可用的串口设备!")
else:
    print("可用的串口设备如下:")
    for port in ports_list:  # 依次输出每个设备对应的串口号和描述信息
        print(list(port)[0], list(port)[1])  # COM4 USB-SERIAL CH340 (COM4)

(2)打开与关闭串口

serial.Serial 的参数如下:

  • port:串口名字(COMn 或者 /dev/ttyUSB)或者 None
  • baudrate (int):波特率,比如9600或者115200;
  • bytesize:数据位数,可能的参数值有:FIVEBITSSIXBITSSEVENBITSEIGHTBITS
  • parity:奇偶校验,可能的参数值:PARITY_NONEPARITY_EVENPARITY_ODDPARITY_MARKPARITY_SPACE
  • stopbits:停止位的比特数,可能的参数值:STOPBITS_ONESTOPBITS_ONE_POINT_FIVESTOPBITS_TWO
  • timeout (float):设置 PySerial 持续读取数据的最长时间(单位:秒);
  • xonxoff (bool):是否启动软件流控制;
  • rtscts (bool):是否启动硬件(RTS/CTS)流控制;
  • dsrdtr (bool):是否启动硬件(DSR/DTR)流控制;
  • write_timeout (float):设置 PySerial 最长写入串口数据的时间(单位:秒);
  • inter_byte_timeout (float):字符间超时,没有则禁止(默认禁止);
  • exclusive (bool):设置独占访问模式(仅 POSIX)。 如果端口已经以独占访问模式打开,则不能以独占访问模式打开端口。

异常返回值如下:

  • ValueError:如果一些参数不在允许参数内,则返回 ValueError,比如波特率设置;
  • SerialException:如果设备无法被找到或者被设置,则返回 SerialException
ser = serial.Serial("COM4", 115200)  # 打开COM4,将波特率配置为115200,其余参数使用默认值
if ser.isOpen():  # 判断串口是否成功打开
    print("串口成功打开")
    print(ser.name)  # 输出串口号,即COM4
else:
    print("串口打开失败")

ser.close()  # 关闭串口
if ser.isOpen():  # 判断串口是否关闭
    print("串口未关闭")
else:
    print("串口已关闭")

(3)发送与接收数据

注意:timeout 参数会影响到 read() 函数的使用,这个 timeout 参数非常重要,直接影响到我们对串口数据的读取。

  • timeout = None:一直等待,直到设置的接收字节数满后退出;
  • timeout = 0:非阻塞模式,在任何情况下都立即返回,返回零或更多,最多为请求的字节数;
  • timeout = x:当请求的字节数可用时,将 timeout 设置为 x 秒(允许浮动)立即返回,否则等待超时到期,并返回在此之前收到的所有字节。
# 打开COM4,将波特率配置为115200,读超时时间为1秒
ser = serial.Serial(port="COM4", baudrate=115200, timeout=1)

# 串口发送数据ABC123,并输出发送的字节数
write_len = ser.write("ABC123".encode('utf-8'))  # 可以指定encode
print(f"串口共发出{
      
      write_len}个字节")  # 串口共发出6个字节

while True:
    com_input = ser.read(10)  # 每次读10字节的数据,可以指定decode:ser.read().decode()
    if com_input:   # 如果读取结果非空,则输出
        print(com_input)  # b'ABC123'
        print(com_input.decode('utf-8'))  # ABC123
    else:
        break

ser.close()

(4)实战测试传送文件数据

with open('../images/sonar_images/seg_height15_txt_01(compressed)/20210108_142207_01_XTF/8_15height.lz', 'rb') as f:  # 可以用编码'ISO-8859-1'
    file = f.read()
    print(file)

    ser = serial.Serial(port="COM4", baudrate=115200, timeout=1)
    write_len = ser.write(file)
    print(f"串口共发出{
      
      write_len}个字节")

    print(ser.in_waiting)  # input buffer中缓存字节数
    while True:
        com_input = ser.read(write_len)  # 读取所有字节
        if com_input:  # 如果读取结果非空,则输出
            print(com_input)
        else:
            break

    ser.close()

猜你喜欢

转载自blog.csdn.net/m0_51755720/article/details/132789900