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

1、系统界面如图所示。

首先,对于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 上。

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

 

Python 串口通信 GUI 开发的更多相关文章

  1. Python 串口通信操作

    下载  pyserial包 https://pypi.python.org/packages/source/p/pyserial/pyserial-2.7.tar.gz#md5=794506184df ...

  2. Android串口通信

    前段时间因为工作需要研究了一下android的串口通信,网上有很多讲串口通信的文章,我在做的时候也参考了很多文章,现在就将我学习过程中的一些心得分享给大家,希望可以帮助大家在学习的时候少走一些弯路,有 ...

  3. Qt 串口通信 高速发送出错的解决方法总结

    使用网上的qextserialport-1.2类,自行开发多线程串口通信.开发的过程中,出现两个问题:   问题1:我用信号槽跨线程调用串口类MyCom 发送和接收数据,中间运行的时候,会内存错误,Q ...

  4. 基于Arduino和python的串口通信和上位机控制

    引言 经常的时候我们要实现两个代码之间的通信,比如说两个不同不同人写的代码要对接,例如将python指令控制Arduino控件的开关,此处使用串口通信是非常方便的,下面笔者将结合自己踩过的坑来讲述下自 ...

  5. Win10 IoT C#开发 4 - UART 串口通信

    Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,既可以开发设备UI与用户交互式操作,又可以控制GPIO等接口,使得原来嵌入式繁琐的开发变得简单.通过Remote Debug ...

  6. Python GUI开发环境的搭建

    原文:Python GUI开发环境的搭建 最近对Python的开发又来了兴趣,对于Python的开发一直停留在一个表面层的认识,玩的部分比较大. Python的入手简单,语法让人爱不释手,在网络通信方 ...

  7. android 串口开发第二篇:利用jni实现android和串口通信

    一:串口通信简介 由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以 ...

  8. [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)

    星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...

  9. Python的串口通信(pyserial)

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

随机推荐

  1. C#:Json数据反序列化为Dictionary并根据关键字获取指定的值

    转自曾是土木人原文 C#:Json数据反序列化为Dictionary并根据关键字获取指定的值 Json数据: { "dataSet": { "header": ...

  2. python:数组/列表(remove()函数、append()函数、sort()函数、reverse()函数)

    排序: 1:整理顺序 #冒泡 lista = [5,7,11,19,99,63,3,9,1] list = [] while lista != []: number = 0 for i in list ...

  3. Lambda表达式在Android开发中的应用

    在Java8中拥有Lambda表达式的新功能,如果现在Android项目中使用,首先,必须在项目中的build.gradle配置一下 使用Lambda表达式必须满足只有一个待实现方法这个规则,否则就不 ...

  4. input子系统分析之三:驱动模块

    内核版本:3.9.5 本节将以even handler来分析设备的注册和打开的过程,分析之前不妨回顾一下上节介绍的数据结构. 结合前两节分析可知,input子系统分为3层,最上一层是event han ...

  5. 201671010140. 2016-2017-2 《Java程序设计》java学习第十二周

    java学习第十章:图形程序设计       本章,介绍的是如何编写使用图形用户界面GUI的java程序.主要讲的是如何编写定义屏幕上的窗口大小和位置的程序,如何在窗口中采用多种字体显示文本,如何显示 ...

  6. Linux实战教学笔记23:Inotify事件监控工具

    第二十三节 inotify事件监控工具 标签(空格分隔): Linux实战教学笔记-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品,允许转载, ...

  7. Apache Hive (三)Hive元数据信息对应MySQL数据库表

    转自:https://www.cnblogs.com/qingyunzong/p/8710356.html 概述 Hive 的元数据信息通常存储在关系型数据库中,常用MySQL数据库作为元数据库管理. ...

  8. SSH(安全协议外壳)介绍及Linux SSH免密登录

    SSH(安全外壳协议) SSH 为 Secure Shell 的缩写,是一种网络安全协议,专为远程登录会话和其他网络服务提供安全性的协议.通过使用 SSH,可以把传输的数据进行加密,有效防止远程管理过 ...

  9. 68. Text Justification一行单词 两端对齐

    [抄题]: Given an array of words and a width maxWidth, format the text such that each line has exactly  ...

  10. Java 代理机制

    Table of Contents 1 引言 2 常见的代理 3 代理模式UML图 4 代理模式实例 5 java动态代理 5.1 java动态代理UML图 6 代理模式与装饰者模式的区别 6.1 装 ...