python开发串口通信界面_Python 串口通信 GUI 开发

在项目中遇到树莓派串口通信问题。由于本人一直从事.net 开发,希望将树莓派系统换成Win10 IOT版。但是在测试过程中出现无法找到串口的问题。最终也没有解决。最终按照领导要求,linux (了解不多)比较稳定。所以硬着头皮重拾了python(之前学习过简单的语法),刚开始做成了控制台,配置比较麻烦最终通过Qt改成了桌面版的,至于能不能在linux上运行,还没做测试。。废话不多少了,进入正题。。。。

1、系统界面如图所示。

712403-20190110155417962-554762437.png

首先,对于python基础都不太熟悉,对GUI更不用说了。通过在园子中查找查找,将Qt Designer 设计的图像话界面转换成.py文件。这个过程比较艰辛,可以通过其他童鞋的博客进行配置。(查找太多了也没有将地址copy下来。非常感谢园友的博客)

1、转换的ui.py代码。

其中包括布局代码已经按钮事件处理逻辑部分

(不会使用pycharm,将转换的文件保存,使用vscode打开)

在QT中通过clicked的connect绑定事件处理函数。如下所示。

self.pushButton.clicked.connect(self.conectSerial)#绑定click 事件

对于列表,刚开始选择listView,主要在使用过程中不知怎么动态绑定内容,遂改成了listWidget,可以像C#语言中的List一样,通过InsertItem或者AddItem进行添加。

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'uitest.ui'

#

# Created by: PyQt5 UI code generator 5.11.3

#

# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

import serialportHelper

import time

import threading

import treadtest

class Ui_MainWindow(object):

def setupUi(self, MainWindow):

MainWindow.setObjectName("MainWindow")

MainWindow.resize(417, 357)

self.centralwidget = QtWidgets.QWidget(MainWindow)

self.centralwidget.setObjectName("centralwidget")

self.label = QtWidgets.QLabel(self.centralwidget)

self.label.setGeometry(QtCore.QRect(20, 0, 61, 31))

self.label.setLayoutDirection(QtCore.Qt.LeftToRight)

self.label.setAutoFillBackground(True)

self.label.setAlignment(QtCore.Qt.AlignCenter)

self.label.setWordWrap(True)

self.label.setObjectName("label")

self.comboBox = QtWidgets.QComboBox(self.centralwidget)

self.comboBox.setGeometry(QtCore.QRect(80, 10, 131, 22))

self.comboBox.setObjectName("comboBox")

portList=serialportHelper.serialPortslist()

for i in range(0,len(portList)):

self.comboBox.addItem(portList[i].device)

self.label_2 = QtWidgets.QLabel(self.centralwidget)

self.label_2.setGeometry(QtCore.QRect(20, 30, 61, 31))

self.label_2.setLayoutDirection(QtCore.Qt.LeftToRight)

self.label_2.setAutoFillBackground(True)

self.label_2.setAlignment(QtCore.Qt.AlignCenter)

self.label_2.setWordWrap(True)

self.label_2.setObjectName("label_2")

self.comboBox_2 = QtWidgets.QComboBox(self.centralwidget)

self.comboBox_2.setGeometry(QtCore.QRect(80, 40, 131, 22))

self.comboBox_2.setObjectName("comboBox_2")

self.comboBox_2.addItem("")

self.comboBox_2.addItem("")

self.comboBox_2.addItem("")

self.comboBox_2.addItem("")

self.comboBox_2.addItem("")

self.label_3 = QtWidgets.QLabel(self.centralwidget)

self.label_3.setGeometry(QtCore.QRect(20, 60, 61, 31))

self.label_3.setLayoutDirection(QtCore.Qt.LeftToRight)

self.label_3.setAutoFillBackground(True)

self.label_3.setAlignment(QtCore.Qt.AlignCenter)

self.label_3.setWordWrap(True)

self.label_3.setObjectName("label_3")

self.comboBox_3 = QtWidgets.QComboBox(self.centralwidget)

self.comboBox_3.setGeometry(QtCore.QRect(80, 70, 131, 22))

self.comboBox_3.setObjectName("comboBox_3")

self.comboBox_3.addItem("")

self.comboBox_3.addItem("")

self.comboBox_3.addItem("")

self.label_4 = QtWidgets.QLabel(self.centralwidget)

self.label_4.setGeometry(QtCore.QRect(20, 90, 61, 31))

self.label_4.setLayoutDirection(QtCore.Qt.LeftToRight)

self.label_4.setAutoFillBackground(True)

self.label_4.setAlignment(QtCore.Qt.AlignCenter)

self.label_4.setWordWrap(True)

self.label_4.setObjectName("label_4")

self.comboBox_4 = QtWidgets.QComboBox(self.centralwidget)

self.comboBox_4.setGeometry(QtCore.QRect(80, 100, 131, 22))

self.comboBox_4.setObjectName("comboBox_4")

self.comboBox_4.addItem("")

self.comboBox_4.addItem("")

self.comboBox_4.addItem("")

self.pushButton = QtWidgets.QPushButton(self.centralwidget)

self.pushButton.setGeometry(QtCore.QRect(260, 80, 75, 23))

self.pushButton.setIconSize(QtCore.QSize(20, 20))

self.pushButton.setDefault(False)

self.pushButton.setObjectName("pushButton")

self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)

self.pushButton_2.setGeometry(QtCore.QRect(260, 120, 75, 23))

self.pushButton_2.setIconSize(QtCore.QSize(20, 20))

self.pushButton_2.setDefault(False)

self.pushButton_2.setObjectName("pushButton_2")

self.listWidget = QtWidgets.QListWidget(self.centralwidget)

self.listWidget.setGeometry(QtCore.QRect(10, 160, 391, 192))

self.listWidget.setObjectName("listWidget")

self.comboBox_5 = QtWidgets.QComboBox(self.centralwidget)

self.comboBox_5.setGeometry(QtCore.QRect(80, 130, 131, 22))

self.comboBox_5.setObjectName("comboBox_5")

self.comboBox_5.addItem("")

self.label_5 = QtWidgets.QLabel(self.centralwidget)

self.label_5.setGeometry(QtCore.QRect(20, 120, 61, 31))

self.label_5.setLayoutDirection(QtCore.Qt.LeftToRight)

self.label_5.setAutoFillBackground(True)

self.label_5.setAlignment(QtCore.Qt.AlignCenter)

self.label_5.setWordWrap(True)

self.label_5.setObjectName("label_5")

MainWindow.setCentralWidget(self.centralwidget)

self.retranslateUi(MainWindow)

QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):

_translate = QtCore.QCoreApplication.translate

MainWindow.setWindowTitle(_translate("MainWindow", "串口通信"))

self.label.setText(_translate("MainWindow", "串口"))

self.label_2.setText(_translate("MainWindow", "波特率"))

self.comboBox_2.setItemText(0, _translate("MainWindow", "1200"))

self.comboBox_2.setItemText(1, _translate("MainWindow", "2400"))

self.comboBox_2.setItemText(2, _translate("MainWindow", "9600"))

self.comboBox_2.setItemText(3, _translate("MainWindow", "19200"))

self.comboBox_2.setItemText(4, _translate("MainWindow", "115200"))

self.label_3.setText(_translate("MainWindow", "校验位"))

self.comboBox_3.setItemText(0, _translate("MainWindow", "N"))

self.comboBox_3.setItemText(1, _translate("MainWindow", "O"))

self.comboBox_3.setItemText(2, _translate("MainWindow", "E"))

self.label_4.setText(_translate("MainWindow", "数据位"))

self.comboBox_4.setItemText(0, _translate("MainWindow", "8"))

self.comboBox_4.setItemText(1, _translate("MainWindow", "7"))

self.comboBox_4.setItemText(2, _translate("MainWindow", "6"))

self.pushButton.setText(_translate("MainWindow", "打开"))

self.pushButton_2.setText(_translate("MainWindow", "关闭"))

self.comboBox_5.setItemText(0, _translate("MainWindow", "1"))

self.label_5.setText(_translate("MainWindow", "停止位"))

self.pushButton.clicked.connect(self.conectSerial)

self.pushButton_2.clicked.connect(self.closeSerial)

self.pushButton_2.setEnabled(False)

global ser

flag=False

ser =None

def conectSerial(self):

try:

self.openSerial()

except:

if self.pushButton.isEnabled==False:

self.pushButton.setEnabled(True)

self.pushButton_2.setEnabled(False)

if ser!=None and ser.is_open==True:

self.closeSerial()

pass

def closeSerial(self):

try:

if ser!=None and ser.is_open==True:

global flag

flag=False

serialportHelper.ClosePort(ser)

self.listWidget.insertItem(0,"串口已关闭 {}".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))

self.pushButton.setEnabled(True)

self.pushButton_2.setEnabled(False)

self.setEnable(True)

except Exception as e:

self.listWidget.insertItem(0,e)

pass

def openSerial(self):

try:

portname=self.comboBox.currentText()

baudrate=self.comboBox_2.currentText()

parity=self.comboBox_3.currentText()

bytesize=self.comboBox_4.currentText()

stopbits=self.comboBox_5.currentText()

global ser

ser,ret=serialportHelper.OpenPort(portname,baudrate,parity,int(bytesize),int(stopbits),100)

if ret==True:

global flag

flag=True

self.listWidget.insertItem(0,'串口已打开 {}'.format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))

self.pushButton.setEnabled(False)

self.pushButton_2.setEnabled(True)

# thread=threading.Thread(target=self.readdata)

# self.thread.

# thread.setDaemon(True)

# thread.start()

self.thread=treadtest.MyThread(ser)

self.thread._single.connect(self.chuli)

self.thread.start()

self.setEnable(False)

except Exception as e:

self.listWidget.insertItem(0,e)

def chuli(self,s):

self.listWidget.insertItem(0,s)

def setEnable(self,flag):

self.comboBox.setEnabled(flag)

self.comboBox_2.setEnabled(flag)

self.comboBox_3.setEnabled(flag)

self.comboBox_4.setEnabled(flag)

self.comboBox_5.setEnabled(flag)

2、新增一个aa.py文件,手动添加如下代码作为窗体程序运行的入口。

import sys

from PyQt5.QtWidgets import QApplication , QMainWindow

from ui import *

class MyMainWindow(QMainWindow, Ui_MainWindow):

def __init__(self, parent=None):

super(MyMainWindow, self).__init__(parent)

self.setupUi(self)

if __name__=="__main__":

# 每一pyqt5应用程序必须创建一个应用程序对象。sys.argv参数是一个列表,从命令行输入参数。

app = QApplication(sys.argv)

myWin = MyMainWindow()

# 显示在屏幕上

myWin.show()

# 系统exit()方法确保应用程序干净的退出

# 的exec_()方法有下划线。因为执行是一个Python关键词。因此,exec_()代替

sys.exit(app.exec_())

3、串口操作模块 serialportHelper.py

通过pyserial 模块进行处理

import msvcrt

import serial

import serial.tools.list_ports

def OpenPort(comName,bps,parity,size,stopbits,timeout):

try:

ser =serial.Serial(comName,bps,bytesize=size,parity=parity,stopbits=stopbits,timeout=timeout)

if (ser.is_open):

ret =True

except Exception as e:

print("---异常---:", e)

ser=None

ret=False

return ser,ret

def DWritePort(ser,text):

result = ser.write(text.encode("gbk")) # 写数据

return result

def ClosePort(ser):

ser.close()

def serialPortslist():

port_list=list(serial.tools.list_ports.comports())

if len(port_list)==0:

print("没有端口")

return None

else:

for i in range(0,len(port_list)):

print(port_list[i])

return port_list

4、通过多线程进行串口数据接收

由于在处理过程中将处理结果进行显示在主线程UI中,进过艰难查找,需要继承QThread线程处理类,通过信号量进行传递。(该过程类似于C#中的delegate委托)

from PyQt5.QtCore import *

import time

import services

class MyThread(QThread):

_single=pyqtSignal(str)

def __init__(self,ser):

super(MyThread,self).__init__()

self.ser=ser

print(ser)

def run(self):

try:

while self.ser!=None and self.ser.is_open==True:

try:

# for i in range(10):

# self._single.emit('串口接收的值:%s' % i)

# time.sleep(0.1)

count=self.ser.in_waiting

if count>0:

time.sleep(1)

str1 = self.ser.read(self.ser.in_waiting).decode("gbk")

print(str1)

self._single.emit('串口接收的值:'+str1.replace('\r\n',''))

user_url="http://172.16.0.101:8088/SAPFRCEX.asmx?wsdl"

client1=services.ClientObj(user_url)

result=client1.service.getBOM(str('J010190968'))

if result!=None:

#print("测试结果:",result)

get_list=services.GetArrayOfStringValue(result,'diffgram')

get_list1=services.GetArrayOfStringValue(get_list[0],'DocumentElement')

get_list2=services.GetArrayOfStringValue(get_list1[0],'dt')

for i in range(0,len(get_list2)):

self._single.emit('webservice返回值:%s' % get_list2[i][3][0])

else:

self._single.emit("webservice 无返回信息")

except Exception as e:

print(e)

self._single.emit(e)

pass

except:

pass

5、由于串口接收的数据需要进行上传webservice

创建一个services.py文件。通过使用pip install 按照suds模块,按照完成有异常,最后查找,按照suds-jurko 问题解决。

import suds

from suds.client import Client,sudsobject

from array import array

def GetArrayOfStringValue(array,info):

'''处理webservice返回的array of string,并获取返回值列表'''

getarray = array

getdict = sudsobject.asdict(getarray)

getlist = getdict.get('%s'%info)

return getlist

def ClientObj(url):

user_url="http://xxxx:xxxx/SAPFRCEX.asmx?wsdl"

client1=Client(user_url)

return client1

6、linux 下打包

在vscode 终端下,通过输入 pyinstaller -F aa.py 则在文件根目录文件下生成Linux下aa的可执行文件。截图和第一张截图一致。

总之,通过艰难的寻找,基本完成了GUI串口通信Demo ,后续我会将Demo 上传到Git 上。

非常感谢园友博客的支持。。再次感谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值