下面我提供了一个从STM32单片机串行读取数据的python代码.我需要用收到的串行数据绘制一个图形。我还使用了一个GUI,在需要的时候,我可以从这个GUI中选择选项来绘制图形。
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
import sys
import serial
import datetime
import time
import threading
headingFont = QFont("Times", 20)
headingFont.setBold(True)
textfont = QFont("Candara Light", 11)
textfont.setBold(True)
on_off_font = QFont("Times", 12)
on_off_font.setBold(True)
class MainWindow(QWidget):
def __init__(self, t):
super().__init__()
self.setWindowTitle("Main Window")
self.setWindowIcon(QIcon('icon.png'))
self.setFixedSize(500, 500)
self.mwUI()
self.th = t
def mwUI(self):
self.mwtext1 = QLabel("Measurement Select", self)
self.mwtext1.setFont(headingFont)
self.mwbutton1 = QPushButton("Voltage", self)
self.mwbutton1.clicked.connect(self.mwb1f)
self.mwbutton1.setFont(textfont)
#########################Layout########################################
mwmainlayout = QVBoxLayout()
mwtoplayout = QHBoxLayout()
mwbottomlayout = QVBoxLayout()
mwmainlayout.addLayout(mwtoplayout)
mwmainlayout.addLayout(mwbottomlayout)
mwtoplayout.setContentsMargins(100, 80, 0, 0)
mwtoplayout.addWidget(self.mwtext1)
mwbottomlayout.setContentsMargins(80, 30, 80, 150)
mwbottomlayout.addWidget(self.mwbutton1)
self.setLayout(mwmainlayout)
self.show()
############################Functions#######################
def mwb1f(self):
self.voltage_window = Graphwindow(self.th)
class Graphwindow(QMainWindow):
def __init__(self, t):
QMainWindow.__init__(self)
self.widget = QWidget()
self.setCentralWidget(self.widget)
self.widget.setLayout(QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.flag1 = 0
self.th = t
self.fig = Figure(figsize=(50, 20), dpi=100)
self.axes = self.fig.add_subplot(111)
self.axes.grid()
self.line, = self.axes.plot(self.th.time1, self.th.data1, 'r')
self.line2, = self.axes.plot(self.th.time1, self.th.data2, 'b')
self.line3, = self.axes.plot(self.th.time1, self.th.data3, 'g')
self.line4, = self.axes.plot(self.th.time1, self.th.data4, 'k')
self.canvas = FigureCanvas(self.fig)
self.nav = NavigationToolbar(self.canvas, self.widget)
self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.show()
self.timer = QTimer()
self.timer.setInterval(510)
self.timer.timeout.connect(self.update_plot)
self.timer.start()
def update_plot(self):
if self.flag1 == 0:
pass
self.flag1 = 1
else:
self.axes.cla()
self.axes.grid()
self.line, = self.axes.plot(self.th.time1, self.th.data1, 'r')
self.line2, = self.axes.plot(self.th.time1, self.th.data2, 'b')
self.line3, = self.axes.plot(self.th.time1, self.th.data3, 'g')
self.line4, = self.axes.plot(self.th.time1, self.th.data4, 'k')
self.axes.xaxis.set_major_locator(plt.MaxNLocator(3))
self.canvas.draw()
class thread_class():
def __init__(self):
self.vc1_thread = threading.Thread(target=self.thread_module3)
self.vc1_thread.daemon = True
self.vc1_thread.start()
self.data1 = [0] * 100
self.data2 = [0] * 100
self.data3 = [0] * 100
self.data4 = [0] * 100
self.time1 = [""] * 100
def thread_module3(self):
self.ser5 = serial.Serial(port="COM6", baudrate=115200, timeout=None)
self.bu = ""
self.w = 0
self.flag2 = 0
self.current_time = 0
while self.ser5.readable():
current_char = self.ser5.read()
if current_char != b'&':
pass
else:
self.read_module()
break
def read_module(self):
while self.ser5.readable():
try:
current_char = self.ser5.read()
if current_char == b'&':
self.bu = ""
elif current_char == b'a':
self.time_calc()
self.w = 1
self.update_list()
elif current_char == b'b':
self.time_calc()
self.w = 2
self.update_list()
elif current_char == b'c':
self.time_calc()
self.w = 3
self.update_list()
elif current_char == b'd':
self.time_calc()
self.w = 4
self.update_list()
elif current_char == b'1' or b'2' or b'3' or b'4' or b'5' or b'6' or '7' or b'8' or b'9' or b'0' or b'.':
self.bu = self.bu + current_char.decode("utf-8")
except AttributeError:
pass
def time_calc(self):
if self.flag2 == 0:
self.current_time = int(round(time.time() * 1000))
self.flag2 = 1
else:
self.current_time = self.current_time + 1
self.s = self.current_time / 1000.0
self.d = datetime.datetime.fromtimestamp(self.s).strftime('%d/%m/%Y %H:%M:%S.%f')
current_time_str = str(self.d[-15:-3])
self.time1.append(current_time_str)
def update_list(self):
self.bu = self.bu.split('\x00', 1)[0]
if self.w == 1:
self.data1.append(float(self.bu))
if len(self.data1) > 99:
self.data1 = self.data1[1:]
self.time1 = self.time1[1:]
elif self.w == 2:
self.data2.append(float(self.bu))
if len(self.data2) > 99:
self.data2 = self.data2[1:]
self.time1 = self.time1[1:]
elif self.w == 3:
self.data3.append(float(self.bu))
if len(self.data3) > 99:
self.data3 = self.data3[1:]
self.time1 = self.time1[1:]
elif self.w == 4:
self.data4.append(float(self.bu))
if len(self.data4) > 99:
self.data4 = self.data4[1:]
self.time1 = self.time1[1:]
def main():
App = QApplication(sys.argv)
t = thread_class()
w1 = MainWindow(t)
quit(App.exec_())
if __name__ == "__main__":
main()
我在读取串行数据时没有问题,但当我点击GUI上的按钮显示图形时,图形是正确的,但只有几秒钟的时间,之后整个程序就关闭了。无论是GUI窗口还是图形.谁能帮助理解为什么会发生这种情况,也能纠正这个问题。
我先谢谢你。
P.S.在thread_module类中,我如何读取数据以及对数据的操作并不是很重要。