PyQt5+serial模块实现一个串口小工具

2023-01-14 10:00:35
目录
串口简述serial模块参数方法使用模板串口工具示例

串口简述

异步串行是指UART(Universal>

串行接口按电气标准及协议来分包括RS-232-C、RS-422、RS485等。RS-232-C、RS-422与RS-485标准只对接口的电气特性做出规定,不涉及接插件、电缆或协议。

1.RS-232

也称标准串口,最常用的一种串行通讯接口。它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是“ [1] 数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口的技术标准”。传统的RS-232-C接口标准有22根线,采用标准25芯D型插头座(DB25),后来使用简化为9芯D型插座(DB9),现在应用中25芯插头座已很少采用。
RS-232采取不平衡传输方式,即所谓单端通讯。由于其发送电平与接收电平的差仅为2V至3V左右,所以其共模抑制能力差,再加上双绞线上的分布电容,其传送距离最大为约15米,最高速率为20kb/s。RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kΩ。所以RS-232适合本地设备之间的通信。 [2]

2.RS-422

标准全称是“平衡电压数字接口电路的电气特性”,它定义了接口电路的特性。典型的RS-422是四线接口。实际上还有一根信号地线,共5根线。其DB9连接器引脚定义。由于接收器采用高输入阻抗和发送驱动器比RS232更强的驱动能力,故允许在相同传输线上连接多个接收节点,最多可接10个节点。即一个主设备(Master),其余为从设备(Slave),从设备之间不能通信,所以RS-422支持点对多的双向通信。接收器输入阻抗为4k,故发端最大负载能力是10×4k+100Ω(终接电阻)。RS-422四线接口由于采用单独的发送和接收通道,因此不必控制数据方向,各装置之间任何必须的信号交换均可以按软件方式(XON/XOFF握手)或硬件方式(一对单独的双绞线)实现。

RS-422的最大传输距离为1219米,最大传输速率为10Mb/s。其平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能达到最大传输距离。只有在很短的距离下才能获得最高速率传输。一般100米长的双绞线上所能获得的最大传输速率仅为1Mb/s。

3.RS-485

是从RS-422基础上发展而来的,所以RS-485许多电气规定与RS-422相仿。如都采用平衡传输方式、都需要在传输线上接终接电阻等。RS-485可以采用二线与四线方式,二线制可实现真正的多点双向通信,而采用四线连接时,与RS-422一样只能实现点对多的通信,即只能有一个主(Master)设备,其余为从设备,但它比RS-422有改进,无论四线还是二线连接方式总线上可多接到32个设备。

RS-485与RS-422的不同还在于其共模输出电压是不同的,RS-485是-7V至+12V之间,而RS-422在-7V至+7V之间,RS-485接收器最小输入阻抗为12kΩ、RS-422是4kΩ;由于RS-485满足所有RS-422的规范,所以RS-485的驱动器可以在RS-422网络中应用。

RS-485与RS-422一样,其最大传输距离约为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比,在100kb/s速率以下,才可能使用规定最长的电缆长度。只有在很短的距离下才能获得最高速率传输。一般100米长双绞线最大传输速率仅为1Mb/s。

注:以上内容摘自百度百科。

引脚定义:

    RX(Receive Data):接收数据TX(Transmit Data):发送数据CTS(Clear To Send): 清除发送RTS(Request To Send):请求发送DTR(Data Terminal Ready):数据终端准备好DSR(Data Set Ready):数据准备好

    如果UART只有RX、TX两个信号,要流控的话只能是软流控;

    如果有RX,TX,CTS,RTS 四个信号,则多半是支持硬流控的UART;

    如果有 RX,TX,CTS ,RTS ,DTR,DSR 六个信号的话,RS232标准的可能性比较大。

    serial模块

    参数

    方法

    使用模板

    1.初始化端口无指定参数

    mSerial = serial.Serial()
    mSerial.port = ‘COM9'
    mSerial.baudrate = 115200
    '''其它端口参数'''
    m.Serial.open() # 打开端口
    mSerial.isOpen()
    mSerial.read()
    mSerial.write(b'hello world')
    

    2.初始化端口指定端口号和波特率

    mSerial = serial.Serial(‘COM9', 115200)
    mSerial.isOpen()
    mSerial.read()
    mSerial.write(b'hello world')
    

    3.初始化端口指定所有参数

    mSerial = serial.Serial(port=‘COM9', baudrate=115200, bytesize=8, parity=‘N', stopbits=1, timeout=100, xonxoff=False, rtscts=False, dsrdtr=False)
    mSerial.isOpen()
    mSerial.read()
    mSerial.write(b'hello world')
    

    串口工具示例

    主程序代码

    import sys
    import serial
    import serial.tools.list_ports
    
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    
    from ui_comport import Ui_MainWindow
    
    class ComPortWindow(QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None) -> None:
            super(ComPortWindow, self).__init__(parent)
            self.setupUi(self)
    
            self.setWindowTitle('串口小工具')
            self.setWindowIcon(QIcon('./images/iconCOM9.png'))
    
            self.mSerial = serial.Serial()
            self.ScanComPort() # 扫描一次串口端口
            self.OnPortChanged()
     
            self.comboBox_Baudrate.setCurrentText("115200") # 设置默认波特率
            self.comboBox_ByteSize.setCurrentText("8")      # 设置默认数据位
            
            self.BtnScanPort.clicked.connect(self.ScanComPort)
            self.BtnOpenPort.clicked.connect(self.OpenComPort)
            self.BtnClosePort.clicked.connect(self.CloseComPort)
            self.BtnSendData.clicked.connect(self.SendData)
            self.BtnClearRecv.clicked.connect(self.ClearRecvText)
            self.BtnClearSend.clicked.connect(self.ClearSendText)
            self.comboBox_ComPort.currentIndexChanged.connect(self.OnPortChanged)
    
            # 串口接收数据定时器
            self.recvTimer = QTimer(self)
            self.recvTimer.timeout.connect(self.RecvData)
    
        def ClearRecvText(self):
            self.textBrowserRecvArea.clear()
    
        def ClearSendText(self):
            self.lineEdit_SendData.clear()
    
        def OnPortChanged(self):
            if len(self.portDict) > 0:
                self.label_CurrentPortName.setText(self.portDict[self.comboBox_ComPort.currentText()])
    
        def ScanComPort(self):
            self.portDict = {}
            self.comboBox_ComPort.clear()
            portList = list(serial.tools.list_ports.comports())
            for port in portList:
                self.portDict["%s" % port[0]] = "%s" % port[1]
                self.comboBox_ComPort.addItem(port[0])
            if len(self.portDict) == 0:
                QMessageBox.critical(self, "警告", "未找到串口", QMessageBox.Cancel, QMessageBox.Cancel)
            pass
    
        def OpenComPort(self):
            # 设置端口号
            self.mSerial.port = self.comboBox_ComPort.currentText()
    
            # 设置波特率
            self.mSerial.baudrate = int(self.comboBox_Baudrate.currentText())
    
            # 数据位设置
            bytesize = self.comboBox_ByteSize.currentText()
            if "5" == bytesize:
                self.mSerial.bytesize = serial.FIVEBITS
            elif "6" == bytesize:
                self.mSerial.bytesize = serial.SIXBITS
            elif "7" == bytesize:
                self.mSerial.bytesize = serial.SEVENBITS
            elif "8" == bytesize:
                self.mSerial.bytesize = serial.EIGHTBITS
    
            # 停止位设置
            stopbitsItems = [serial.STOPBITS_ONE, serial.STOPBITS_ONE_POINT_FIVE, serial.STOPBITS_TWO]
            self.mSerial.stopbits = stopbitsItems[self.comboBox_Stopbits.currentIndex()]
    
            # 校验位设置
            parityItmes = [serial.PARITY_NONE, 
                        serial.PARITY_ODD,
                        serial.PARITY_EVEN,
                        serial.PARITY_MARK,
                        serial.PARITY_SPACE,
                        serial.PARITY_NAMES]
            self.mSerial.parity = parityItmes[self.comboBox_Parity.currentIndex()]
            
            stopbitsItems = [serial.STOPBITS_ONE, serial.STOPBITS_ONE_POINT_FIVE, serial.STOPBITS_TWO]
            self.mSerial.stopbits = stopbitsItems[self.comboBox_Stopbits.currentIndex()]           # 停止为[]
    
            flowctrl = self.comboBox_FlowCtrl.currentText()
            if 'None' == flowctrl:
                self.mSerial.xonxoff = False            # 软件流控       
                self.mSerial.rtscts = False             # 硬件流控
                self.mSerial.dsrdtr = False             # 硬件流控
            elif 'XON/XOFF' == flowctrl:
                self.mSerial.xonxoff = True            # 软件流控       
                self.mSerial.rtscts = False             # 硬件流控
                self.mSerial.dsrdtr = False             # 硬件流控          
            elif 'RTS/CTS' == flowctrl:
                self.mSerial.xonxoff = False            # 软件流控       
                self.mSerial.rtscts = True             # 硬件流控
                self.mSerial.dsrdtr = False             # 硬件流控
    
            # 超时时间
            self.mSerial.timeout = 100
    
            if self.mSerial.isOpen():
                QMessageBox.warning(self, "警告", "串口已打开", QMessageBox.Cancel, QMessageBox.Cancel)
            else:
                try:
                    self.BtnOpenPort.setEnabled(False)
                    self.mSerial.open()
                    self.mSerial.flushInput()
                    self.mSerial.flushOutput()
                    self.recvTimer.start(20)
                except:
                    QMessageBox.critical(self, "警告", "串口打开失败", QMessageBox.Cancel, QMessageBox.Cancel)
                    self.BtnOpenPort.setEnabled(True)
            
            # 打印端口信息
            print(self.mSerial)
    
        def CloseComPort(self):
            self.recvTimer.stop()
            if self.mSerial.isOpen():
                self.BtnOpenPort.setEnabled(True)
                self.mSerial.flushInput()
                self.mSerial.flushOutput()
                self.mSerial.close()            
            pass
        
        def SendData(self):
            if self.mSerial.isOpen():
                sendtext = self.lineEdit_SendData.text()
                sendtext = sendtext + '\r\n'
                self.mSerial.write(sendtext.encode("utf-8"))
                print("send data:", sendtext)
            else:
                QMessageBox.warning(self, "警告", "串口未打开,请先打开串口", QMessageBox.Cancel, QMessageBox.Cancel)
    
        def RecvData(self):
            dataheader = b'$$:' # 数据帧头, 原始数据帧格式 '$$:10,11,12'
    
            try:
                num = self.mSerial.inWaiting()
            except:
                self.CloseComPort()
    
            if num > 0:
                try:
                    self.data = self.mSerial.readline(1024)
                    # 读取一行数据 添加到数据接收显示区
                    if self.data.endswith("\n".encode("utf-8")):
                        self.textBrowserRecvArea.append(self.data.decode("utf-8"))
    
                    # 解析数据项,数据帧以 b'$$:' 开头,多个数据参数之间以 ‘,' 分割, 数据帧以'\r\n'结束 
                    if self.data.decode('UTF-8').startswith(dataheader.decode('UTF-8')):
                        rawdata = self.data[len(dataheader) : len(self.data)-2]
                        data = rawdata.split(b',')
                        print(int(data[0]), int(data[1]), int(data[2]))
                except:
                    pass
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        win = ComPortWindow()
        win.show()
        sys.exit(app.exec_())
    

    QtDesigner UI界面设计:

    QtDesigner UI文件 comport.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>1135</width>
        <height>713</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralwidget">
       <widget class="QGroupBox" name="groupBox_ComSettings">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>20</y>
          <width>221</width>
          <height>471</height>
         </rect>
        </property>
        <property name="title">
         <string>串口设置</string>
        </property>
        <widget class="QWidget" name="horizontalLayoutWidget">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>400</y>
           <width>201</width>
           <height>51</height>
          </rect>
         </property>
         <layout class="QHBoxLayout" name="horizontalLayout">
          <item>
           <widget class="QPushButton" name="BtnOpenPort">
            <property name="text">
             <string>打开串口</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QPushButton" name="BtnClosePort">
            <property name="text">
             <string>关闭串口</string>
            </property>
           </widget>
          </item>
         </layout>
        </widget>
        <widget class="QWidget" name="horizontalLayoutWidget_2">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>350</y>
           <width>201</width>
           <height>51</height>
          </rect>
         </property>
         <layout class="QHBoxLayout" name="horizontalLayout_8">
          <item>
           <widget class="QPushButton" name="BtnScanPort">
            <property name="text">
             <string>扫描端口</string>
            </property>
           </widget>
          </item>
         </layout>
        </widget>
        <widget class="QLabel" name="label_CurrentPortName">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>20</y>
           <width>201</width>
           <height>31</height>
          </rect>
         </property>
         <property name="text">
          <string/>
         </property>
        </widget>
        <widget class="QWidget" name="layoutWidget">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>60</y>
           <width>201</width>
           <height>281</height>
          </rect>
         </property>
         <layout class="QVBoxLayout" name="verticalLayout">
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_2">
            <item>
             <widget class="QLabel" name="label_ComPort">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>串  口</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_ComPort">
              <property name="editable">
               <bool>false</bool>
              </property>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_3">
            <item>
             <widget class="QLabel" name="label_Baudrate">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>波特率</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_Baudrate">
              <property name="editable">
               <bool>true</bool>
              </property>
              <property name="currentText">
               <string>115200</string>
              </property>
              <property name="currentIndex">
               <number>8</number>
              </property>
              <item>
               <property name="text">
                <string>2400</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>4800</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>9600</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>14400</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>19200</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>38400</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>56000</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>57600</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>115200</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>128000</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>256000</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>230400</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>1000000</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>2000000</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>3000000</string>
               </property>
              </item>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_4">
            <item>
             <widget class="QLabel" name="label_ByteSize">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>数据位</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_ByteSize">
              <property name="editable">
               <bool>false</bool>
              </property>
              <property name="currentText">
               <string>8</string>
              </property>
              <property name="currentIndex">
               <number>3</number>
              </property>
              <item>
               <property name="text">
                <string>5</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>6</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>7</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>8</string>
               </property>
              </item>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_6">
            <item>
             <widget class="QLabel" name="label_Stopbits">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>停止位</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_Stopbits">
              <item>
               <property name="text">
                <string>1</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>1.5</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>2</string>
               </property>
              </item>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_5">
            <item>
             <widget class="QLabel" name="label_Parity">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>校验位</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_Parity">
              <item>
               <property name="text">
                <string>None</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>Odd</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>Even</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>Mark</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>Space</string>
               </property>
              </item>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayout_7">
            <item>
             <widget class="QLabel" name="label_CTS">
              <property name="maximumSize">
               <size>
                <width>60</width>
                <height>16777215</height>
               </size>
              </property>
              <property name="text">
               <string>流  控</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QComboBox" name="comboBox_FlowCtrl">
              <item>
               <property name="text">
                <string>None</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>RTS/CTS</string>
               </property>
              </item>
              <item>
               <property name="text">
                <string>XON/XOFF</string>
               </property>
              </item>
             </widget>
            </item>
           </layout>
          </item>
         </layout>
        </widget>
       </widget>
       <widget class="QGroupBox" name="groupBox">
        <property name="geometry">
         <rect>
          <x>250</x>
          <y>20</y>
          <width>871</width>
          <height>471</height>
         </rect>
        </property>
        <property name="title">
         <string>接收区</string>
        </property>
        <widget class="QTextBrowser" name="textBrowserRecvArea">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>20</y>
           <width>851</width>
           <height>441</height>
          </rect>
         </property>
        </widget>
       </widget>
       <widget class="QGroupBox" name="groupBox_2">
        <property name="geometry">
         <rect>
          <x>250</x>
          <y>500</y>
          <width>871</width>
          <height>161</height>
         </rect>
        </property>
        <property name="title">
         <string>发送区</string>
        </property>
        <widget class="QLineEdit" name="lineEdit_SendData">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>20</y>
           <width>851</width>
           <height>51</height>
          </rect>
         </property>
        </widget>
        <widget class="QPushButton" name="BtnSendData">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>80</y>
           <width>71</width>
           <height>71</height>
          </rect>
         </property>
         <property name="text">
          <string>发送数据</string>
         </property>
        </widget>
       </widget>
       <widget class="QGroupBox" name="groupBox_3">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>500</y>
          <width>221</width>
          <height>161</height>
         </rect>
        </property>
        <property name="title">
         <string>收/发控制</string>
        </property>
        <widget class="QPushButton" name="BtnClearRecv">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>20</y>
           <width>201</width>
           <height>61</height>
          </rect>
         </property>
         <property name="text">
          <string>清空接收区</string>
         </property>
        </widget>
        <widget class="QPushButton" name="BtnClearSend">
         <property name="geometry">
          <rect>
           <x>10</x>
           <y>90</y>
           <width>201</width>
           <height>61</height>
          </rect>
         </property>
         <property name="text">
          <string>清空发送区</string>
         </property>
        </widget>
       </widget>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>1135</width>
         <height>26</height>
        </rect>
       </property>
      </widget>
      <widget class="QStatusBar" name="statusbar"/>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    comport.ui文件编译生成的ui_comport.py

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'd:\project\python\串口工具\串口收发工具\comport.ui'
    #
    # Created by: PyQt5 UI code generator 5.15.7
    #
    # WARNING: Any manual changes made to this file will be lost when pyuic5 is
    # run again.  Do not edit this file unless you know what you are doing.
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(1135, 713)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.groupBox_ComSettings = QtWidgets.QGroupBox(self.centralwidget)
            self.groupBox_ComSettings.setGeometry(QtCore.QRect(10, 20, 221, 471))
            self.groupBox_ComSettings.setObjectName("groupBox_ComSettings")
            self.horizontalLayoutWidget = QtWidgets.QWidget(self.groupBox_ComSettings)
            self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 400, 201, 51))
            self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
            self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
            self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
            self.horizontalLayout.setObjectName("horizontalLayout")
            self.BtnOpenPort = QtWidgets.QPushButton(self.horizontalLayoutWidget)
            self.BtnOpenPort.setObjectName("BtnOpenPort")
            self.horizontalLayout.addWidget(self.BtnOpenPort)
            self.BtnClosePort = QtWidgets.QPushButton(self.horizontalLayoutWidget)
            self.BtnClosePort.setObjectName("BtnClosePort")
            self.horizontalLayout.addWidget(self.BtnClosePort)
            self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.groupBox_ComSettings)
            self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(10, 350, 201, 51))
            self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
            self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
            self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0)
            self.horizontalLayout_8.setObjectName("horizontalLayout_8")
            self.BtnScanPort = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
            self.BtnScanPort.setObjectName("BtnScanPort")
            self.horizontalLayout_8.addWidget(self.BtnScanPort)
            self.label_CurrentPortName = QtWidgets.QLabel(self.groupBox_ComSettings)
            self.label_CurrentPortName.setGeometry(QtCore.QRect(10, 20, 201, 31))
            self.label_CurrentPortName.setText("")
            self.label_CurrentPortName.setObjectName("label_CurrentPortName")
            self.layoutWidget = QtWidgets.QWidget(self.groupBox_ComSettings)
            self.layoutWidget.setGeometry(QtCore.QRect(10, 60, 201, 281))
            self.layoutWidget.setObjectName("layoutWidget")
            self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget)
            self.verticalLayout.setContentsMargins(0, 0, 0, 0)
            self.verticalLayout.setObjectName("verticalLayout")
            self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_2.setObjectName("horizontalLayout_2")
            self.label_ComPort = QtWidgets.QLabel(self.layoutWidget)
            self.label_ComPort.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_ComPort.setObjectName("label_ComPort")
            self.horizontalLayout_2.addWidget(self.label_ComPort)
            self.comboBox_ComPort = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_ComPort.setEditable(False)
            self.comboBox_ComPort.setObjectName("comboBox_ComPort")
            self.horizontalLayout_2.addWidget(self.comboBox_ComPort)
            self.verticalLayout.addLayout(self.horizontalLayout_2)
            self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_3.setObjectName("horizontalLayout_3")
            self.label_Baudrate = QtWidgets.QLabel(self.layoutWidget)
            self.label_Baudrate.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_Baudrate.setObjectName("label_Baudrate")
            self.horizontalLayout_3.addWidget(self.label_Baudrate)
            self.comboBox_Baudrate = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_Baudrate.setEditable(True)
            self.comboBox_Baudrate.setObjectName("comboBox_Baudrate")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.comboBox_Baudrate.addItem("")
            self.horizontalLayout_3.addWidget(self.comboBox_Baudrate)
            self.verticalLayout.addLayout(self.horizontalLayout_3)
            self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_4.setObjectName("horizontalLayout_4")
            self.label_ByteSize = QtWidgets.QLabel(self.layoutWidget)
            self.label_ByteSize.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_ByteSize.setObjectName("label_ByteSize")
            self.horizontalLayout_4.addWidget(self.label_ByteSize)
            self.comboBox_ByteSize = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_ByteSize.setEditable(False)
            self.comboBox_ByteSize.setObjectName("comboBox_ByteSize")
            self.comboBox_ByteSize.addItem("")
            self.comboBox_ByteSize.addItem("")
            self.comboBox_ByteSize.addItem("")
            self.comboBox_ByteSize.addItem("")
            self.horizontalLayout_4.addWidget(self.comboBox_ByteSize)
            self.verticalLayout.addLayout(self.horizontalLayout_4)
            self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_6.setObjectName("horizontalLayout_6")
            self.label_Stopbits = QtWidgets.QLabel(self.layoutWidget)
            self.label_Stopbits.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_Stopbits.setObjectName("label_Stopbits")
            self.horizontalLayout_6.addWidget(self.label_Stopbits)
            self.comboBox_Stopbits = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_Stopbits.setObjectName("comboBox_Stopbits")
            self.comboBox_Stopbits.addItem("")
            self.comboBox_Stopbits.addItem("")
            self.comboBox_Stopbits.addItem("")
            self.horizontalLayout_6.addWidget(self.comboBox_Stopbits)
            self.verticalLayout.addLayout(self.horizontalLayout_6)
            self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_5.setObjectName("horizontalLayout_5")
            self.label_Parity = QtWidgets.QLabel(self.layoutWidget)
            self.label_Parity.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_Parity.setObjectName("label_Parity")
            self.horizontalLayout_5.addWidget(self.label_Parity)
            self.comboBox_Parity = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_Parity.setObjectName("comboBox_Parity")
            self.comboBox_Parity.addItem("")
            self.comboBox_Parity.addItem("")
            self.comboBox_Parity.addItem("")
            self.comboBox_Parity.addItem("")
            self.comboBox_Parity.addItem("")
            self.horizontalLayout_5.addWidget(self.comboBox_Parity)
            self.verticalLayout.addLayout(self.horizontalLayout_5)
            self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
            self.horizontalLayout_7.setObjectName("horizontalLayout_7")
            self.label_CTS = QtWidgets.QLabel(self.layoutWidget)
            self.label_CTS.setMaximumSize(QtCore.QSize(60, 16777215))
            self.label_CTS.setObjectName("label_CTS")
            self.horizontalLayout_7.addWidget(self.label_CTS)
            self.comboBox_FlowCtrl = QtWidgets.QComboBox(self.layoutWidget)
            self.comboBox_FlowCtrl.setObjectName("comboBox_FlowCtrl")
            self.comboBox_FlowCtrl.addItem("")
            self.comboBox_FlowCtrl.addItem("")
            self.comboBox_FlowCtrl.addItem("")
            self.horizontalLayout_7.addWidget(self.comboBox_FlowCtrl)
            self.verticalLayout.addLayout(self.horizontalLayout_7)
            self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
            self.groupBox.setGeometry(QtCore.QRect(250, 20, 871, 471))
            self.groupBox.setObjectName("groupBox")
            self.textBrowserRecvArea = QtWidgets.QTextBrowser(self.groupBox)
            self.textBrowserRecvArea.setGeometry(QtCore.QRect(10, 20, 851, 441))
            self.textBrowserRecvArea.setObjectName("textBrowserRecvArea")
            self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
            self.groupBox_2.setGeometry(QtCore.QRect(250, 500, 871, 161))
            self.groupBox_2.setObjectName("groupBox_2")
            self.lineEdit_SendData = QtWidgets.QLineEdit(self.groupBox_2)
            self.lineEdit_SendData.setGeometry(QtCore.QRect(10, 20, 851, 51))
            self.lineEdit_SendData.setObjectName("lineEdit_SendData")
            self.BtnSendData = QtWidgets.QPushButton(self.groupBox_2)
            self.BtnSendData.setGeometry(QtCore.QRect(10, 80, 71, 71))
            self.BtnSendData.setObjectName("BtnSendData")
            self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
            self.groupBox_3.setGeometry(QtCore.QRect(10, 500, 221, 161))
            self.groupBox_3.setObjectName("groupBox_3")
            self.BtnClearRecv = QtWidgets.QPushButton(self.groupBox_3)
            self.BtnClearRecv.setGeometry(QtCore.QRect(10, 20, 201, 61))
            self.BtnClearRecv.setObjectName("BtnClearRecv")
            self.BtnClearSend = QtWidgets.QPushButton(self.groupBox_3)
            self.BtnClearSend.setGeometry(QtCore.QRect(10, 90, 201, 61))
            self.BtnClearSend.setObjectName("BtnClearSend")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 1135, 26))
            self.menubar.setObjectName("menubar")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            self.comboBox_Baudrate.setCurrentIndex(8)
            self.comboBox_ByteSize.setCurrentIndex(3)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.groupBox_ComSettings.setTitle(_translate("MainWindow", "串口设置"))
            self.BtnOpenPort.setText(_translate("MainWindow", "打开串口"))
            self.BtnClosePort.setText(_translate("MainWindow", "关闭串口"))
            self.BtnScanPort.setText(_translate("MainWindow", "扫描端口"))
            self.label_ComPort.setText(_translate("MainWindow", "串  口"))
            self.label_Baudrate.setText(_translate("MainWindow", "波特率"))
            self.comboBox_Baudrate.setCurrentText(_translate("MainWindow", "115200"))
            self.comboBox_Baudrate.setItemText(0, _translate("MainWindow", "2400"))
            self.comboBox_Baudrate.setItemText(1, _translate("MainWindow", "4800"))
            self.comboBox_Baudrate.setItemText(2, _translate("MainWindow", "9600"))
            self.comboBox_Baudrate.setItemText(3, _translate("MainWindow", "14400"))
            self.comboBox_Baudrate.setItemText(4, _translate("MainWindow", "19200"))
            self.comboBox_Baudrate.setItemText(5, _translate("MainWindow", "38400"))
            self.comboBox_Baudrate.setItemText(6, _translate("MainWindow", "56000"))
            self.comboBox_Baudrate.setItemText(7, _translate("MainWindow", "57600"))
            self.comboBox_Baudrate.setItemText(8, _translate("MainWindow", "115200"))
            self.comboBox_Baudrate.setItemText(9, _translate("MainWindow", "128000"))
            self.comboBox_Baudrate.setItemText(10, _translate("MainWindow", "256000"))
            self.comboBox_Baudrate.setItemText(11, _translate("MainWindow", "230400"))
            self.comboBox_Baudrate.setItemText(12, _translate("MainWindow", "1000000"))
            self.comboBox_Baudrate.setItemText(13, _translate("MainWindow", "2000000"))
            self.comboBox_Baudrate.setItemText(14, _translate("MainWindow", "3000000"))
            self.label_ByteSize.setText(_translate("MainWindow", "数据位"))
            self.comboBox_ByteSize.setCurrentText(_translate("MainWindow", "8"))
            self.comboBox_ByteSize.setItemText(0, _translate("MainWindow", "5"))
            self.comboBox_ByteSize.setItemText(1, _translate("MainWindow", "6"))
            self.comboBox_ByteSize.setItemText(2, _translate("MainWindow", "7"))
            self.comboBox_ByteSize.setItemText(3, _translate("MainWindow", "8"))
            self.label_Stopbits.setText(_translate("MainWindow", "停止位"))
            self.comboBox_Stopbits.setItemText(0, _translate("MainWindow", "1"))
            self.comboBox_Stopbits.setItemText(1, _translate("MainWindow", "1.5"))
            self.comboBox_Stopbits.setItemText(2, _translate("MainWindow", "2"))
            self.label_Parity.setText(_translate("MainWindow", "校验位"))
            self.comboBox_Parity.setItemText(0, _translate("MainWindow", "None"))
            self.comboBox_Parity.setItemText(1, _translate("MainWindow", "Odd"))
            self.comboBox_Parity.setItemText(2, _translate("MainWindow", "Even"))
            self.comboBox_Parity.setItemText(3, _translate("MainWindow", "Mark"))
            self.comboBox_Parity.setItemText(4, _translate("MainWindow", "Space"))
            self.label_CTS.setText(_translate("MainWindow", "流  控"))
            self.comboBox_FlowCtrl.setItemText(0, _translate("MainWindow", "None"))
            self.comboBox_FlowCtrl.setItemText(1, _translate("MainWindow", "RTS/CTS"))
            self.comboBox_FlowCtrl.setItemText(2, _translate("MainWindow", "XON/XOFF"))
            self.groupBox.setTitle(_translate("MainWindow", "接收区"))
            self.groupBox_2.setTitle(_translate("MainWindow", "发送区"))
            self.BtnSendData.setText(_translate("MainWindow", "发送数据"))
            self.groupBox_3.setTitle(_translate("MainWindow", "收/发控制"))
            self.BtnClearRecv.setText(_translate("MainWindow", "清空接收区"))
            self.BtnClearSend.setText(_translate("MainWindow", "清空发送区"))

    COM9接到了树莓派Pico(Raspberry Pi Pico)的串口上,串口小工具发送的数据会通过树莓派Pico接收后再转发给串口小工具

    Raspberry Pi Pico代码

    from machine import Pin,UART
    import utime
    uart0 = UART(0, baudrate=115200, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17), )
    #uart0.deinit()
    txData = b'hello world\r\n'
    rxData = bytes()
    
    while True:
        while uart0.any() > 0:
            rxData = uart0.readline()
            uart0.write(rxData)
            print(rxData.decode('utf-8'))        
        utime.sleep(0.2)
    

    以上就是PyQt5+serial模块实现一个串口小工具的详细内容,更多关于PyQt5 serial串口工具的资料请关注易采站长站其它相关文章!