我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用python+Pyqt5实现串口调试助手

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用python+Pyqt5实现串口调试助手

python可以利用serial模块来和串口设备进行485或者232通讯。

在这里插入图片描述

当然,网上这类串口调试助手的小程序有很多,不过这些程序要么是要收费,只能试用30天,要么是不好用。

况且,别人写的程序,你只能使用,无法取出其中的数据来进行处理,所以,如果可以自己写一个程序,既方便使用,又可以随时随地使用其中的数据。

软件:python3.10
pycharm2021
硬件:window10电脑
串口485设备(国产流量计)
串口转usb线(电脑不带串口,只能转接)

串口转usb线

流量计带485通讯

准备好了后,就可以开始写程序了。

串口通讯程序首先要对串口进行设置,如波特率、数据位、停止位、校验位等。可以称之为初始化:

初始化:

def serial_init(self):   #初始化

        self.port = self.port_set.currentText()
        self.bps = int(self.baud_set.currentText())
        self.timeout = float(self.timeout_set.text())
        try:
            self.ser = serial.Serial(port=self.port,baudrate=self.bps,bytesize=8,parity='N',stopbits=1)
            print(self.ser)
            if self.ser.is_open:
                print('串口正常')
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
            print('异常:', e)

初始化完成后,需要将串口打开,只有串口成功打开,才可以进行后面的数据传输。python中的serial模块,提供serial.isopen来进行检查。当然,此处需要注意的是,在串口serial实例化的时候,实际上已经同时打开串口了。所以,如果在初始化程序里建立了实例化:

 self.ser = serial.Serial(port=self.port,baudrate=self.bps,bytesize=8,parity='N',stopbits=1)

那么也可以不用在重复打开串口了。

串口打开:

def open_serial(self):   #打开串口
        try:
            self.ser.open()
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
            print('异常:', e)

串口关闭:

 def close_serial(self):  #关闭串口
        try:
            self.ser.close()

        except Exception as e:
            QMessageBox.warning(self,'tips!',str(e),QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Ok)
            print('异常:', e)

调试完成后,最好关闭串口,有始有终。

在完成上面的初始化和打开步骤后,就可以进行数据的读、写了,本例中使用了与流量计进行通讯,读取流量计实时流量。该流量计读、写数据时有专门的格式:

在这里插入图片描述

所以,从电脑端发送指令时,需要按照流量计的格式发送,才能得到正确的反馈。485是半双工传输,即同一时间只能进行读或者写,读、写不能同时进行。

本例中,读取流量指令格式为:
01 03 00 10 00 02 C5 CE
实际操作中,我将流量计设备地址修改为2,即
02 03 00 10 00 02 C5 CE

发送数据:

def send_data(self):
        ct = datetime.datetime.now()                       #获取当前系统时间
        ct_str = ct.strftime("%Y-%m-%d %H:%M:%S")          #格式化当前系统时间(字符形式)
        try:
            self.senddata_s=self.le_senddata.text()
            self.senddata=bytes.fromhex(self.senddata_s)  #字符转成字节
            self.ser.write(self.senddata)
            #self.senddata_str=self.senddata.hex()
            self.senddata_str_fg=self.str_fenge(self.senddata_s)
            #self.le_senddata.setText(self.senddata.hex())
            self.le_recdata.append('\n' + '[' + ct_str+ ']' + ' ' + self.senddata_str_fg + '\n')
            #print(self.senddata)
            time.sleep(0.1)
            self.read_data_size()
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)

读取数据:

 def read_data_size(self):
        ct=datetime.datetime.now()
        ct_str=ct.strftime("%Y-%m-%d %H:%M:%S")
        try:
            #self.size=10
            self.read_data=self.ser.read_all()
            #print(self.read_data)
            self.read_data_str=self.read_data.hex()   #字节转成16进制字符显示
            #re.findall(r'.{3}',self.read_data_str)
            self.read_data_str_fg=self.str_fenge(self.read_data_str)
            #print(self.read_data_str)
            self.le_recdata.append('\n'+'['+ct_str+']'+' '+self.read_data_str_fg+'\n')
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
        #return self.read_data

serial的读取数据时,有几种方式,read()、read_all()、readline(),read()就是按照字节数size大小读取缓存区字节,read_all()即读取所有数据,readline()读取缓存区最新一行数据。

完整程序:

from numpy.lib.function_base import place
import serial
import serial.tools.list_ports
import sys
import re
import os
import time
import datetime
import threading
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Serialwindow(QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.initUI()
    def initUI(self):
        #self.stylefile = 'E:\\100proworld2021\opencvtestpro01\爬虫程序\爬虫-style.qss'
        #self.qssstyle = CommonHelper.readQSS(self.stylefile)
        self.port = ''
        self.bps = 0
        self.timeout = 0.0
        self.senddata=bytes()
        self.read_data=''
        
        self.btn_plist=QPushButton('获取可用串口',self)
        self.btn_plist.setGeometry(20,20,60,20)
        self.btn_plist.clicked.connect(self.get_serial_info)
        self.btn_plist.adjustSize()
        
        self.btn_ser_init=QPushButton('初始化',self)
        self.btn_ser_init.setGeometry(20,50,60,20)
        self.btn_ser_init.clicked.connect(self.serial_init)
        self.btn_ser_init.adjustSize()
        self.btn_open=QPushButton('打开串口',self)
        self.btn_open.setGeometry(20,80,60,20)
        self.btn_open.clicked.connect(self.open_serial)
        self.btn_open.adjustSize()
        self.btn_close=QPushButton('关闭串口',self)
        self.btn_close.setGeometry(20,110,60,20)
        self.btn_close.clicked.connect(self.close_serial)
        self.btn_close.adjustSize()
        self.btn_read_data=QPushButton('读取数据',self)
        self.btn_read_data.setGeometry(20,140,60,20)
        self.btn_read_data.clicked.connect(self.read_data_size)
        self.btn_read_data.adjustSize()
        self.btn_write_data=QPushButton('发送数据',self)
        self.btn_write_data.setGeometry(40,460,60,20)
        self.btn_write_data.clicked.connect(self.send_data)
        self.btn_write_data.adjustSize()
        #Qcombobox
        self.port_set=QComboBox(self)
        self.port_set.setGeometry(500,20,100,20)
        self.port_set.addItems(['COM1'])
        #self.port_set.activated.connect(self.Qcombo)
        self.lbl_port_set=QLabel(self)
        self.lbl_port_set.setGeometry(420,20,60,20)
        self.lbl_port_set.setText('串口号:')
        self.baud_set=QComboBox(self)
        self.baud_set.setGeometry(500,50,100,20)
        self.baud_set.addItems(['9600','19200','38400','115200'])
        self.lbl_baud_set=QLabel(self)
        self.lbl_baud_set.setGeometry(420,50,60,20)
        self.lbl_baud_set.setText('波特率:')
        self.stopbit_set=QComboBox(self)
        self.stopbit_set.setGeometry(500,80,100,20)
        self.stopbit_set.addItems(['0','1'])
        self.lbl_stopbit_set = QLabel(self)
        self.lbl_stopbit_set.setGeometry(420, 80, 60, 20)
        self.lbl_stopbit_set.setText('停止位:')
        self.parity_set=QComboBox(self)
        self.parity_set.setGeometry(500,110,100,20)
        self.parity_set.addItems(['无','奇校验','偶校验'])
        self.lbl_parity_set = QLabel(self)
        self.lbl_parity_set.setGeometry(420, 110, 60, 20)
        self.lbl_parity_set.setText('校验位:')
        self.databit_set=QComboBox(self)
        self.databit_set.setGeometry(500,140,100,20)
        self.databit_set.addItems(['8','7'])
        self.lbl_databit_set=QLabel(self)
        self.lbl_databit_set.setGeometry(420,140,60,20)
        self.lbl_databit_set.setText('数据位:')
        self.timeout_set=QLineEdit(self)
        self.timeout_set.setGeometry(500,170,100,20)
        self.timeout_set.setText('1000')
        self.lbl_timeout_set=QLabel(self)
        self.lbl_timeout_set.setGeometry(420,170,60,20)
        self.lbl_timeout_set.setText('超时设置:')
        self.lbl_timeout_set_2=QLabel(self)
        self.lbl_timeout_set_2.setGeometry(610,170,60,20)
        self.lbl_timeout_set_2.setText('ms')
        #
        self.le_senddata=QLineEdit(self)
        self.le_senddata.setGeometry(120,460,300,20)
        self.le_senddata.setText('010300100002C5CE')
        self.le_recdata=QTextEdit(self)
        self.le_recdata.setGeometry(120,220,600,200)
        self.setGeometry(100,100,800,600)
        self.setWindowTitle('简易串口调试助手-菌尘')
       # self.setStyleSheet(self.qssstyle)
        self.show()
    def Qcombo(self):
        print(self.port_set.currentText())
        print(self.baud_set.currentText())
        print(self.stopbit_set.currentText())
        print(self.parity_set.currentText())
        print(self.databit_set.currentText())
        print(self.timeout_set.text())
    def get_serial_info(self):   #获取可用串口列表
        #打印可用串口列表
        #self.need_serial = ''
        self.plist = list(serial.tools.list_ports.comports())
        if len(self.plist) <= 0:
            print('未找到串口')
            qm = QMessageBox.warning(self, '提示窗口', '未找到串口!请检查接线和电脑接口。', QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Ok)
            if qm == QMessageBox.Yes:
                print('Yes')
            else:
                print('No')
        else:
            for i in list(self.plist):
                self.port_set.addItem(i.name)
        #return self.need_serial
        #print(self.plist)
    def serial_init(self):   #初始化
        self.port = self.port_set.currentText()
        self.bps = int(self.baud_set.currentText())
        self.timeout = float(self.timeout_set.text())
        try:
            self.ser = serial.Serial(port=self.port,baudrate=self.bps,bytesize=8,parity='N',stopbits=1)
            print(self.ser)
            if self.ser.is_open:
                print('串口正常')
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
            print('异常:', e)
    def open_serial(self):   #打开串口
        try:
            self.ser.open()
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
            print('异常:', e)
    def close_serial(self):  #关闭串口
        try:
            self.ser.close()
        except Exception as e:
            QMessageBox.warning(self,'tips!',str(e),QMessageBox.Ok|QMessageBox.Cancel,QMessageBox.Ok)
            print('异常:', e)
    def read_data_size(self):
        ct=datetime.datetime.now()
        ct_str=ct.strftime("%Y-%m-%d %H:%M:%S")
        try:
            #self.size=10
            self.read_data=self.ser.read_all()
            #print(self.read_data)
            self.read_data_str=self.read_data.hex()   #字节转成16进制字符显示
            #re.findall(r'.{3}',self.read_data_str)
            self.read_data_str_fg=self.str_fenge(self.read_data_str)
            #print(self.read_data_str)
            self.le_recdata.append('\n'+'['+ct_str+']'+' '+self.read_data_str_fg+'\n')
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
        #return self.read_data
    def read_data_line(self):
        self.read_data=self.ser.readline()
        return self.read_data
    def send_data(self):
        ct = datetime.datetime.now()                       #获取当前系统时间
        ct_str = ct.strftime("%Y-%m-%d %H:%M:%S")          #格式化当前系统时间(字符形式)
        try:
            self.senddata_s=self.le_senddata.text()
            self.senddata=bytes.fromhex(self.senddata_s)  #字符转成字节
            self.ser.write(self.senddata)
            #self.senddata_str=self.senddata.hex()
            self.senddata_str_fg=self.str_fenge(self.senddata_s)
            #self.le_senddata.setText(self.senddata.hex())
            self.le_recdata.append('\n' + '[' + ct_str+ ']' + ' ' + self.senddata_str_fg + '\n')
            #print(self.senddata)
            time.sleep(0.1)
            self.read_data_size()
        except Exception as e:
            QMessageBox.warning(self, 'tips!', str(e), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
    def read_data_alway(self, way):
        print('开始接受数据:')
        while True:
            try:
                if self.ser.inWaiting:
                    if(way == 0 ):
                        for i in range(self.ser.inWaiting):
                            print('接收ascII数据:'+str(self.read_data_size(1)))
                            data1 = self.read_data_size(1).hex()
                            data2 = int(data1, 16)
                            print('接收到16进制数据:'+data1+'接收到10进制数据:'+str(data2))
                    if(way == 1 ):
                        data = self.ser.read_all()
            except Exception as e:
                print('异常:', e)
    def str_fenge(self,A):
        '''
        对字符串进行按长度分割,并在中间加入其他字符,如空格、短横等
        '''
        b = re.findall(r'.{2}',A)
        c = ' '.join(b)
        #print(c)
        return c
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Serialwindow()
    sys.exit(app.exec_())

上面的程序经过测试,可以与流量计正常通讯。

到此这篇关于使用python+Pyqt5实现串口调试助手的文章就介绍到这了,更多相关python Pyqt5串口调试助手内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用python+Pyqt5实现串口调试助手

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在python中使用PyQt5实现一个窗口功能

怎么在python中使用PyQt5实现一个窗口功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。python主要应用领域有哪些1、云计算,典型应用OpenSta
2023-06-14

java如何调用chatgpt接口来实现专属于自己的人工智能助手

这篇文章主要介绍“java如何调用chatgpt接口来实现专属于自己的人工智能助手”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java如何调用chatgpt接口来实现专属于自己的人工智能助手”文章
2023-07-05

如何使用Python实现一个打字速度测试工具来测试你的手速

这篇文章将为大家详细讲解有关如何使用Python实现一个打字速度测试工具来测试你的手速,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、程序解读本次程序中,我们使用的python库完全是python的内置
2023-06-15

python实现接口自动化测试中如何使用pymysql直连数据库

这篇文章给大家介绍python实现接口自动化测试中如何使用pymysql直连数据库,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。实现步骤1 PyMySQL 安装启动命令行,联网的前提下键入命令: pip install
2023-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录