欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

Python之PyQT多线程串口代码分析

程序员文章站 2022-03-30 16:28:08
...

这篇文章主要介绍了Python之PyQT多线程串口代码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

这篇博客主要记录一下PyQT多线程串口的主要代码分析,文末会有工程的源代码文件
首先,从PyCharm启动QtDesigner


Python之PyQT多线程串口代码分析
之前给客户做的上位机,保密起见,删减了大部分的框图构件,但不影响本篇串口教程
QtDesigner界面如下:


Python之PyQT多线程串口代码分析
忽略 添加数据以及表格数据显示,这里用不到
着重讲一下类的构成
新建一个串口类SerialThread,继承自QtCore.QThread,实现全部的串口收发功能

class SerialThread(QtCore.QThread):
    dataReadoutSignal = pyqtSignal(str)    def __init__(self, parent = None, portName = 'COM3', baudrate = 9600, parity = 'N', bytesize = 8, stopbits = 1, timeout = None):
        super(SerialThread, self).__init__(parent)
        self.m_serialPort = serial.Serial()
        self.m_serialPort.port = portName
        self.m_serialPort.baudrate = baudrate
        self.m_serialPort.parity = parity
        self.m_serialPort.bytesize = bytesize
        self.m_serialPort.stopbits = stopbits
        self.m_serialPort.timeout = timeout
        self.OpenScom()    def OpenScom(self):
        try:
            self.m_serialPort.open()
            self.m_serialPort.setRTS(True)
            self.m_serialPort.setDTR(True)        except Exception as ex:
            print(ex)            return ex    def ScomSendOneData(self,datain):
        if isinstance(datain,int):
            listTemp = []
            listTemp.append(datain)
            d = bytes(listTemp)
            self.m_serialPort.write(d)        else:            if isinstance(datain,str):
                d = datain.encode('utf-8')
                self.m_serialPort.write(d)    def ScomGetintData(self):
        n = self.m_serialPort.inWaiting()        if n:
            data = self.m_serialPort.read(n).hex()            #writefile
            print(data)    def ScomGetstrData(self):
        if self.m_serialPort.is_open:
            n = self.m_serialPort.inWaiting()            if n > 0:
                data = self.m_serialPort.read(n).decode('GB2312',errors='ignore')                return data    def run(self):
        cnt = 50

        while cnt <= 3000:
            sendstr = str(cnt)            if len(sendstr) == 2:
                sendstr = '00' + sendstr            else:                if len(sendstr) == 3:
                    sendstr = '0' + sendstr

            self.ScomSendOneData('SET' + sendstr + 'V')
            cnt = cnt + 5
            print('此时设置电压为:' + sendstr + 'V')
            time.sleep(2)

函数功能见名知意,此处不表。这里主要讲一下run函数,run函数实现了一次循环,50到3000步进取5,发送内容是SET0050V到SET3000V,当然,我这样做是业务需求,如果并不需要这个功能,run函数可以写成

    def run(self):
        while true:
            time.sleep(2)

界面我们用QtDesigner制作的ui文件通过pyUIC生成py文件


Python之PyQT多线程串口代码分析
生成的代码如下(太长,只留前几行)

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'CashUpdateUI11v.ui'## Created by: PyQt5 UI code generator 5.6## WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_cash(object):
    def setupUi(self, cash):
    **
    **
    **

此时,新建一个类MyWindow,继承QMainWindow和Ui_cash,并在类内部,创建SerialThread成员
总体代码如下:

class MyWindow(QMainWindow,Ui_cash):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.scomList = []
        self.threadList = []
        self.setupUi(self)
        self.actionOpen.triggered.connect(self.openMsg)
        self.actionSave.triggered.connect(self.saveMsg)
        self.pushButton.clicked.connect(self.ScomAutoFind)
        self.addDataButton.clicked.connect(self.getRHandT)

        self.tableWidget.setColumnCount(5)
        self.tableWidget.setRowCount(1)
        self.tableWidget.setHorizontalHeaderLabels(['11', '22', '33', '44', '55'])
        self.tableRowCnt = 0
        self.tableColumnCnt = 0
        self.ThreadComID = 0
        self.addDatasignal = pyqtSignal(str)
        self.datadict = {'RHldy':0,'Tldy':0,'meaRT':0,'voltport':0}    def getMCUdata(self):
        if self.ThreadComID == 0:
            self.showMsgbox('请先连接串口')        else:
            self.ThreadComID.ScomSendOneData(' 5501AA')
            time.sleep(0.1)
            strt = self.ThreadComID.ScomGetstrData()            if strt is None:
                self.showMsgbox('请将串口线连接到电路板')                return None
            print(strt)
            self.datadict['voltport'] = strt[4:-3] + '.' + strt[-3:-2]
            self.ThreadComID.ScomSendOneData(' 5502AA')
            time.sleep(0.1)
            strt = self.ThreadComID.ScomGetstrData()            if strt is None:
                self.showMsgbox('请将串口线连接到电路板')                return None
            print(strt)
            self.datadict['meaRT'] = strt[4:-4] + '.' + strt[-4:-2]            return 1


    def insertTableNewLine(self):
        self.tableWidget.setItem(self.tableRowCnt, 0, QTableWidgetItem(self.datadict['RHldy']))
        self.tableWidget.setItem(self.tableRowCnt, 1, QTableWidgetItem(self.datadict['Tldy']))
        self.tableWidget.setItem(self.tableRowCnt, 2, QTableWidgetItem(self.datadict['meaRT']))
        self.tableWidget.setItem(self.tableRowCnt, 3, QTableWidgetItem(self.datadict['voltport']))
        self.tableWidget.setItem(self.tableRowCnt, 4, QTableWidgetItem(str(datetime.date.today())+' '+str(datetime.datetime.today().hour)+':'+str(datetime.datetime.today().minute)))
        self.tableRowCnt += 1
        self.tableWidget.insertRow(self.tableRowCnt)    def openMsg(self):
        file,ok = QFileDialog.getOpenFileName(self,"打开记录表","C:/",".txt")    def getRHandT(self):
        if self.ThreadComID == 0:
            self.showMsgbox('请先连接串口')        else:
            data,ok = QInputDialog.getText(self, "露点仪数据", "按如下格式记录:\n  RH空格T\n示例:\n  RH(0~100):66.6\n  T(0~200):9.8\n  输入:66.6 9.8", QLineEdit.Normal, "66.6 9.8" )            if ok == True:
                data = re.findall('^[0-9]+\.[0-9]+\s+[0-9]+\.[0-9]+$', data.rstrip())                if len(data) == 0:
                    self.showMsgbox('数据格式有误,重新录入')                else:
                    data = data[0].split()
                    print(data)
                    self.datadict['RHldy'] = data[0]
                    self.datadict['Tldy'] = data[1]                    if self.getMCUdata() is None:                        return None
                    print(self.datadict)
                    self.insertTableNewLine()            else:
                self.showMsgbox('请重新录入数据')    def showMsgbox(self,strtoshow):
        QMessageBox.warning(self,'提示',strtoshow,QMessageBox.Ok)    def saveMsg(self):
        file,ok = QFileDialog.getSaveFileName(self,"保存记录表","C:/",".txt")    def ScomAutoFind(self):
        self.pushButton.setDisabled(True)
        self.scomList = list(serial.tools.list_ports.comports())        if len(self.scomList) <= 0:
            self.showMsgbox('未发现串口,请检查线缆连接')
            self.pushButton.setDisabled(False)        else:
            comNum = len(self.scomList)
            print(str(comNum) + 'Scom is found')            while comNum:
                comNum = comNum - 1
                if "USB" in str(self.scomList[comNum]):
                    self.ThreadComID = SerialThread(portName=self.scomList[comNum][0])
                    self.ThreadComID.start()
                    self.graphicsView.setStyleSheet("background-color: rgb(0, 255, 0);")
                    print(str(self.scomList[comNum]) + ' is added')

由于我用的是RS232转USB接入电脑,设备名称是USB-SERIAL CH340,当然还有其他RS232转USB芯片,如PL2303等。我这里就单独检查USB是否在设备名称中,没有检查全名,这里要根据实际需求变动
Python之PyQT多线程串口代码分析
最后就是main了,没什么特别

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myshow = MyWindow()
    myshow.show()    print('程序终止')
    sys.exit(app.exec_())

看一下实际运行效果:
实际运行,(忽略 添加数据 与 数据记录表….)
Python之PyQT多线程串口代码分析
点击connect后,
Python之PyQT多线程串口代码分析
当然点击添加数据也是没问题的哈
Python之PyQT多线程串口代码分析

奉上全部工程文件,链接如下:
https://download.csdn.net/download/ysgjiangsu/10324162

以上就是Python之PyQT多线程串口代码分析的详细内容,更多请关注其它相关文章!