鱼C论坛

 找回密码
 立即注册
查看: 4522|回复: 6

[已解决]用Python写了个串口工具,但是程序老是容易崩溃,求帮忙找下原因

[复制链接]
发表于 2018-3-14 23:08:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
自学python,写了个串口工具,但是一旦连续接收数据多了之后,程序就会崩溃。
不知道是何原因,请小伙伴们帮忙找下原因。

另外代码写的不合理的地方,也希望帮忙指出,谢谢。

出错截图如下图。右边是网上找的串口工具,连续不断的给右边(自己写的)程序发数据,两条消息间隔30ms。
没传多久就会出现如图的停止工作的情况。

出错截图

出错截图


Pthon3 + PyQT

helloU.py
  1. # -*- coding: utf-8 -*-

  2. # Form implementation generated from reading ui file 'helloU.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.9.2
  5. #
  6. # WARNING! All changes made in this file will be lost!

  7. from PyQt5 import QtCore, QtGui, QtWidgets

  8. class Ui_MainWindow(object):
  9.     def setupUi(self, MainWindow):
  10.         MainWindow.setObjectName("MainWindow")
  11.         MainWindow.resize(562, 437)
  12.         MainWindow.setMinimumSize(QtCore.QSize(562, 437))
  13.         self.centralwidget = QtWidgets.QWidget(MainWindow)
  14.         self.centralwidget.setEnabled(True)
  15.         self.centralwidget.setObjectName("centralwidget")
  16.         self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
  17.         self.gridLayout_2.setObjectName("gridLayout_2")
  18.         self.gridLayout = QtWidgets.QGridLayout()
  19.         self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
  20.         self.gridLayout.setObjectName("gridLayout")
  21.         self.sendLineEdit = QtWidgets.QLineEdit(self.centralwidget)
  22.         self.sendLineEdit.setObjectName("sendLineEdit")
  23.         self.gridLayout.addWidget(self.sendLineEdit, 2, 0, 1, 7)
  24.         self.dataBits = QtWidgets.QComboBox(self.centralwidget)
  25.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  26.         sizePolicy.setHorizontalStretch(0)
  27.         sizePolicy.setVerticalStretch(0)
  28.         sizePolicy.setHeightForWidth(self.dataBits.sizePolicy().hasHeightForWidth())
  29.         self.dataBits.setSizePolicy(sizePolicy)
  30.         self.dataBits.setMinimumSize(QtCore.QSize(50, 20))
  31.         self.dataBits.setMaximumSize(QtCore.QSize(50, 20))
  32.         self.dataBits.setObjectName("dataBits")
  33.         self.gridLayout.addWidget(self.dataBits, 0, 4, 1, 1)
  34.         self.sendBtn = QtWidgets.QPushButton(self.centralwidget)
  35.         self.sendBtn.setObjectName("sendBtn")
  36.         self.gridLayout.addWidget(self.sendBtn, 3, 0, 1, 1)
  37.         self.rcvBrowser = QtWidgets.QTextBrowser(self.centralwidget)
  38.         self.rcvBrowser.setObjectName("rcvBrowser")
  39.         self.gridLayout.addWidget(self.rcvBrowser, 1, 0, 1, 7)
  40.         self.parityMode = QtWidgets.QComboBox(self.centralwidget)
  41.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  42.         sizePolicy.setHorizontalStretch(0)
  43.         sizePolicy.setVerticalStretch(0)
  44.         sizePolicy.setHeightForWidth(self.parityMode.sizePolicy().hasHeightForWidth())
  45.         self.parityMode.setSizePolicy(sizePolicy)
  46.         self.parityMode.setMinimumSize(QtCore.QSize(60, 20))
  47.         self.parityMode.setMaximumSize(QtCore.QSize(60, 20))
  48.         self.parityMode.setObjectName("parityMode")
  49.         self.gridLayout.addWidget(self.parityMode, 0, 3, 1, 1)
  50.         self.stopBits = QtWidgets.QComboBox(self.centralwidget)
  51.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  52.         sizePolicy.setHorizontalStretch(0)
  53.         sizePolicy.setVerticalStretch(0)
  54.         sizePolicy.setHeightForWidth(self.stopBits.sizePolicy().hasHeightForWidth())
  55.         self.stopBits.setSizePolicy(sizePolicy)
  56.         self.stopBits.setMinimumSize(QtCore.QSize(50, 20))
  57.         self.stopBits.setMaximumSize(QtCore.QSize(50, 20))
  58.         self.stopBits.setObjectName("stopBits")
  59.         self.gridLayout.addWidget(self.stopBits, 0, 5, 1, 1)
  60.         self.baudLineEdit = QtWidgets.QLineEdit(self.centralwidget)
  61.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  62.         sizePolicy.setHorizontalStretch(0)
  63.         sizePolicy.setVerticalStretch(0)
  64.         sizePolicy.setHeightForWidth(self.baudLineEdit.sizePolicy().hasHeightForWidth())
  65.         self.baudLineEdit.setSizePolicy(sizePolicy)
  66.         self.baudLineEdit.setMinimumSize(QtCore.QSize(80, 20))
  67.         self.baudLineEdit.setMaximumSize(QtCore.QSize(80, 20))
  68.         self.baudLineEdit.setText("")
  69.         self.baudLineEdit.setObjectName("baudLineEdit")
  70.         self.gridLayout.addWidget(self.baudLineEdit, 0, 2, 1, 1)
  71.         spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
  72.         self.gridLayout.addItem(spacerItem, 0, 6, 1, 1)
  73.         self.openButton = QtWidgets.QPushButton(self.centralwidget)
  74.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  75.         sizePolicy.setHorizontalStretch(0)
  76.         sizePolicy.setVerticalStretch(0)
  77.         sizePolicy.setHeightForWidth(self.openButton.sizePolicy().hasHeightForWidth())
  78.         self.openButton.setSizePolicy(sizePolicy)
  79.         self.openButton.setMinimumSize(QtCore.QSize(80, 20))
  80.         self.openButton.setMaximumSize(QtCore.QSize(80, 20))
  81.         self.openButton.setObjectName("openButton")
  82.         self.gridLayout.addWidget(self.openButton, 0, 0, 1, 1)
  83.         self.portNum = QtWidgets.QComboBox(self.centralwidget)
  84.         sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
  85.         sizePolicy.setHorizontalStretch(0)
  86.         sizePolicy.setVerticalStretch(0)
  87.         sizePolicy.setHeightForWidth(self.portNum.sizePolicy().hasHeightForWidth())
  88.         self.portNum.setSizePolicy(sizePolicy)
  89.         self.portNum.setMinimumSize(QtCore.QSize(80, 20))
  90.         self.portNum.setMaximumSize(QtCore.QSize(80, 20))
  91.         self.portNum.setObjectName("portNum")
  92.         self.gridLayout.addWidget(self.portNum, 0, 1, 1, 1)
  93.         spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
  94.         self.gridLayout.addItem(spacerItem1, 3, 3, 1, 4)
  95.         self.HexCheckBox = QtWidgets.QCheckBox(self.centralwidget)
  96.         self.HexCheckBox.setObjectName("HexCheckBox")
  97.         self.gridLayout.addWidget(self.HexCheckBox, 3, 1, 1, 1)
  98.         self.NewLineCheckBox = QtWidgets.QCheckBox(self.centralwidget)
  99.         self.NewLineCheckBox.setObjectName("NewLineCheckBox")
  100.         self.gridLayout.addWidget(self.NewLineCheckBox, 3, 2, 1, 1)
  101.         self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
  102.         MainWindow.setCentralWidget(self.centralwidget)
  103.         self.menubar = QtWidgets.QMenuBar(MainWindow)
  104.         self.menubar.setGeometry(QtCore.QRect(0, 0, 562, 23))
  105.         self.menubar.setObjectName("menubar")
  106.         MainWindow.setMenuBar(self.menubar)
  107.         self.statusbar = QtWidgets.QStatusBar(MainWindow)
  108.         self.statusbar.setObjectName("statusbar")
  109.         MainWindow.setStatusBar(self.statusbar)

  110.         self.retranslateUi(MainWindow)
  111.         QtCore.QMetaObject.connectSlotsByName(MainWindow)

  112.     def retranslateUi(self, MainWindow):
  113.         _translate = QtCore.QCoreApplication.translate
  114.         MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  115.         self.sendBtn.setText(_translate("MainWindow", "Send"))
  116.         self.openButton.setText(_translate("MainWindow", "OPEN"))
  117.         self.HexCheckBox.setText(_translate("MainWindow", "HEX"))
  118.         self.NewLineCheckBox.setText(_translate("MainWindow", "NewLine"))

复制代码



SerialHandle.py
  1. #!/usr/bin/env python
  2. # _*_ coding:utf-8 _*_

  3. import sys
  4. import threading
  5. import time
  6. import serial
  7. import binascii
  8. import logging

  9. logging.basicConfig(level=logging.INFO)

  10. class SerialHandle(object):
  11.     def __init__(self, Port="COM3", BaudRate="9600", ByteSize="8", Parity="N", Stopbits="1"):
  12.         '''
  13.         初始化一些参数
  14.         :param Port:
  15.         :param BaudRate:
  16.         :param ByteSize:
  17.         :param Parity:
  18.         :param Stopbits:
  19.         :return:
  20.         '''
  21.         self.l_serial = None
  22.         self.alive = False
  23.         self.portNum = Port
  24.         self.baudrate = BaudRate
  25.         self.bytesize = ByteSize
  26.         self.parity = Parity
  27.         self.stopbits = Stopbits
  28.         self.receiveData = ""


  29.     def start(self):
  30.         '''
  31.         打开串口
  32.         :return:
  33.         '''
  34.         self.l_serial = serial.Serial()
  35.         self.l_serial.port = self.portNum
  36.         self.l_serial.baudrate = self.baudrate
  37.         self.l_serial.bytesize = int(self.bytesize)
  38.         self.l_serial.parity = self.parity
  39.         self.l_serial.stopbits = int(self.stopbits)
  40.         self.l_serial.timeout = 2

  41.         try:
  42.             self.l_serial.open()
  43.             if self.l_serial.isOpen():
  44.                 self.alive = True
  45.         except Exception as e:
  46.             self.alive = False
  47.             logging.error(e)

  48.     def stop(self):
  49.         '''
  50.         关闭串口
  51.         :return:
  52.         '''
  53.         self.alive = False
  54.         if self.l_serial.isOpen():
  55.             self.l_serial.close()

  56.         # 获取COM号列表

  57.     def port_list(self):
  58.         comlist = []
  59.         port_list = list(serial.tools.list_ports.comports())
  60.         for port in port_list:
  61.             comlist.append(port[0])
  62.         return comlist

  63.     def read(self):
  64.         '''
  65.         循环读取串口的数据
  66.         :return:
  67.         '''
  68.         isRcved = False
  69.         timeRcved = 0
  70.         while self.alive:
  71.             try:
  72.                 number = self.l_serial.inWaiting()
  73.                 if number:
  74.                     isRcved = True
  75.                     timeRcved = int(round(time.time() * 1000))
  76.                     self.receiveData += self.l_serial.read(number).decode()#.replace(binascii.unhexlify("00"), "")
  77.                     #print(self.receiveData)
  78.                     #print("rcv data: %s" % self.l_serial.read(number).decode())
  79.             except Exception as e:
  80.                 logging.error(e)

  81.             if isRcved == True :
  82.                 if (int(round(time.time() * 1000)) - timeRcved)>10:
  83.                     print(self.receiveData)
  84.                     isRcved = False
  85.                     self.receiveData = ""


  86.     def dataReceiveAndProcess(self, func):
  87.         try:
  88.             thread_read = threading.Thread(target=self._dataRecevie, args=(func, ))
  89.             thread_read.setDaemon(True)
  90.             thread_read.start()
  91.         except BaseException as e:
  92.             print("error:",e)


  93.     def _dataRecevie(self, func):
  94.         '''
  95.         循环读取串口的数据
  96.         :return:
  97.         '''
  98.         isRcved = False
  99.         timeRcved = 0
  100.         while self.alive:
  101.             number = self.l_serial.inWaiting()
  102.             if number:
  103.                 logging.info('receive data\n')
  104.                 isRcved = True
  105.                 timeRcved = int(round(time.time() * 1000))
  106.                 self.receiveData += self.l_serial.read(number).decode()#.replace(binascii.unhexlify("00"), "")
  107.                 #print(self.receiveData)
  108.                 #print("rcv data: %s" % self.l_serial.read(number).decode())

  109.             if isRcved == True :
  110.                 if (int(round(time.time() * 1000)) - timeRcved)>10:
  111.                     logging.info('process data\n')
  112.                     #print(self.receiveData)
  113.                     func(self.receiveData)
  114.                     isRcved = False
  115.                     self.receiveData = ""



  116.     def sendData(self, data, isHex=False, isNewLine=False):
  117.         '''
  118.         发送数据
  119.         :param data: self.sendLineEdit.text()
  120.         :param isHex: self.HexCheckBox.checkState()
  121.         :param isNewLine: self.NewLineCheckBox.checkState()
  122.         :return:
  123.         '''
  124.         if data != "":
  125.             if (isHex == False):
  126.                 # 字符串发送
  127.                 if isNewLine:
  128.                     data = data + "\r\n"
  129.                 inputData = data.encode('utf-8')
  130.             else:
  131.                 # 十六进制发送
  132.                 data = data.strip()  # 删除前后的空格
  133.                 sendList = []
  134.                 while data != "":
  135.                     try:
  136.                         # int() 函数用于将一个字符串或数字转换为整型。
  137.                         num = int(data[0:2], 16)
  138.                     except ValueError:
  139.                         print("input hex data!")
  140.                         #QMessageBox.critical(self, 'pycom', '请输入十六进制数据,以空格分开!')
  141.                         return None
  142.                     data = data[2:]
  143.                     data = data.strip()

  144.                     # 添加到发送列表中
  145.                     sendList.append(num)

  146.                 if isNewLine:
  147.                     sendList.append(0x0d)
  148.                     sendList.append(0x0a)

  149.                 inputData = bytes(sendList)

  150.         # d = "12abc"
  151.         # d = d.encode("ascii")
  152.         self.l_serial.write(inputData)

  153. if __name__ == '__main__':
  154.     import threading
  155.     ser = SerialHandle()
  156.     ser.start()

  157.     ser.sendData("12 23 34", True)
  158.     thread_read = threading.Thread(target=ser.read)
  159.     thread_read.setDaemon(True)
  160.     thread_read.start()
  161.     import time
  162.     time.sleep(25)
  163.     ser.stop()
复制代码


main.py
  1. #!/usr/bin/env python
  2. # _*_ coding:utf-8 _*_

  3. import sys
  4. import threading
  5. import time
  6. import datetime
  7. import helloU
  8. import SerialHandle
  9. import serial
  10. import serial.tools.list_ports
  11. from PyQt5.QtGui import *
  12. from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox




  13. class SerialDlg(helloU.Ui_MainWindow):
  14.     def defaultInit(self):
  15.         self.ser = SerialHandle.SerialHandle()
  16.         self.serial_receive_count = 0

  17.         self.portNum.addItems(self.ser.port_list())
  18.         self.baudLineEdit.setText("9600")
  19.         self.parityMode.addItems(['None', 'Even', 'Odd', 'Mark', 'Space'])
  20.         self.dataBits.addItems(['5', '6', '7', '8'])
  21.         self.stopBits.addItems(['1', '1.5', '2'])

  22.         self.dataBits.setCurrentText("8")

  23.         self.openButton.setText("OPEN")
  24.         self.openButton.setStyleSheet("background-color:#4abdac")
  25.         self.openButton.setFont(QFont('SansSerif', 15, QFont.Bold))
  26.         self.openButton.setAutoFillBackground(True)
  27.         self.openButton.clicked.connect(self.OpenSerial)
  28.         self.sendBtn.clicked.connect(self.SendData)

  29.         self.sendBtn.setDisabled(True)


  30.     # 打开串口
  31.     def OpenSerial(self):

  32.         if self.openButton.text() == "OPEN":
  33.             self.portNum.setDisabled(True)
  34.             self.baudLineEdit.setDisabled(True)
  35.             self.parityMode.setDisabled(True)
  36.             self.dataBits.setDisabled(True)
  37.             self.stopBits.setDisabled(True)
  38.             self.sendBtn.setDisabled(False)

  39.             self.port = self.portNum.currentText()
  40.             self.baudrate = self.baudLineEdit.text()

  41.             ParityValue = self.parityMode.currentText()
  42.             self.parity = ParityValue[0]

  43.             self.bytesize = int(self.dataBits.currentText())
  44.             self.stopbits = int(self.stopBits.currentText())

  45.             self.openButton.setText("CLOSE")
  46.             self.openButton.setStyleSheet("background-color:#fc4a1a")
  47.             # self.openButton.setAutoFillBackground(True)

  48.             self.ser.portNum = self.port
  49.             self.ser.baudrate = self.baudrate
  50.             self.ser.bytesize = self.bytesize
  51.             self.ser.parity = self.parity
  52.             self.ser.stopbits = self.stopbits

  53.             self.ser.start()

  54.             self.ser.dataReceiveAndProcess(self.showDataOnQTextBrowser)
  55.             #thread_read = threading.Thread(target=self.ser.read)
  56.             #thread_read.setDaemon(True)
  57.             #thread_read.start()

  58.         elif self.openButton.text() == "CLOSE":
  59.             self.ser.stop()
  60.             self.openButton.setText("OPEN")
  61.             self.openButton.setStyleSheet("background-color:#4abdac")
  62.             # self.openButton.setAutoFillBackground(True)

  63.             self.portNum.setDisabled(False)
  64.             self.baudLineEdit.setDisabled(False)
  65.             self.parityMode.setDisabled(False)
  66.             self.dataBits.setDisabled(False)
  67.             self.stopBits.setDisabled(False)
  68.             self.sendBtn.setDisabled(True)

  69.     # 发送数据
  70.     def SendData(self):
  71.         self.ser.sendData(self.sendLineEdit.text(), self.HexCheckBox.checkState(), self.NewLineCheckBox.checkState())

  72.     # 数据显示
  73.     def showDataOnQTextBrowser(self, data):
  74.         self.serial_receive_count += 1
  75.         self.rcvBrowser.append("[" + str(datetime.datetime.now()) + " - "+ str(self.serial_receive_count) + "]:\n")
  76.         self.rcvBrowser.append(data)
  77.         #QTextCursor cursor = self.rcvBrowser.textCursor()
  78.         self.rcvBrowser.setTextCursor(self.rcvBrowser.textCursor())



  79. if __name__ == '__main__':
  80.     app = QApplication(sys.argv)
  81.     MainWindow = QMainWindow()
  82.     ui = SerialDlg() #helloU.Ui_MainWindow()
  83.     ui.setupUi(MainWindow)
  84.     ui.defaultInit()
  85.     MainWindow.show()
  86.     sys.exit(app.exec_())
复制代码
最佳答案
2018-3-15 17:32:10
justloong 发表于 2018-3-15 09:58
系统问题?你指我PC的操作系统的问题吗?
WIN10系统

,我的archlinux+gnome就没有事,你再等等吧,python更新后应该会好,还有,别装测试版,bug多
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-3-15 07:34:30 | 显示全部楼层
这闪退有很多种可能,我估计是系统的问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-3-15 09:58:41 | 显示全部楼层
AndyZhou 发表于 2018-3-15 07:34
这闪退有很多种可能,我估计是系统的问题

系统问题?你指我PC的操作系统的问题吗?
WIN10系统
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-3-15 17:32:10 | 显示全部楼层    本楼为最佳答案   
justloong 发表于 2018-3-15 09:58
系统问题?你指我PC的操作系统的问题吗?
WIN10系统

,我的archlinux+gnome就没有事,你再等等吧,python更新后应该会好,还有,别装测试版,bug多
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-3-15 18:31:33 | 显示全部楼层
AndyZhou 发表于 2018-3-15 17:32
对,我的archlinux+gnome就没有事,你再等等吧,python更新后应该会好,还有,别装测试版 ...

多谢。这种问题对于我这种新手来讲,要不是别人指点,简直就是无解啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-3-15 18:45:37 | 显示全部楼层
justloong 发表于 2018-3-15 18:31
多谢。这种问题对于我这种新手来讲,要不是别人指点,简直就是无解啊

哦对了,你试试先更新python,再pip install pip-review ,然后 pip-review --auto,这样可以更新pip包
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-6-28 17:08:34 | 显示全部楼层
请问你实现了没有,我遇到跟你一样的问题,我的QQ号171365505希望跟我联系
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 18:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表