python3+tkinter+pyserial编写一个串口控制工具

2024-02-25 04:50

本文主要是介绍python3+tkinter+pyserial编写一个串口控制工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

python3+tkinter+pyserial编写一个串口控制工具

首先展示一下自己做的串口工具界面的全貌

在这里插入图片描述
可以看到其中包括文本框、选项框、按键、输入框还有列表,整个界面是用tkinter 实现的。

tkinter是一个方便使用python语言做界面的库,内涵多种控件,使用灵活方便

在windows系统下,tkinter 是python的自带库,就和re、os一样,直接import就能用;
但是在linux系统下,tkinter需要自行安装,指令如下:

sudo apt-get update
sudo apt-get install python3-tk

如果不行的话,需要自己去github或者 pypi.org网站找安装包,然后在终端切换到包所在的目录,输入

python setup.py install 

一般上面两种办法都能安装成功的, import tkinter试一下,不报错就说明安装成功了。
下面代码主要是tkinter对各控件的布局、参数设置的内容,可以直接运行。具体的执行内容pass掉了。

简单概括这个脚本所包含的tkinter的使用:

1.创建Tk父窗口,作为对象调用set_init_window进行窗口控件初始化
2.涉及到按钮Button、框架Frame、标签Label、输入框Entry
还有普通文本框Text、滚动文本框scrolltext、滚动条scrollbar
以及可以用作列表的Treeview控件、下拉选项框Combobox
3.控件的place、grid布局的使用和区别

4.自动获取电脑上可用的串口,作为串口下拉选项框的值

import tkinter
from tkinter import ttk,filedialog,messagebox,scrolledtext
from tkinter import *
import openpyxl
import threading
import time
import serial
import serial.tools.list_ports
import re
from code_dic import MY_CODE
class MY_GUI():#构造函数def __init__(self,name):self.init_window_name=name#窗口控件设置初始化def set_init_window(self):                        #控件设置的内容主要是这个函数,使用非常简单,主要是调用并设置参数self.init_window_name.title('串口控制')self.init_window_name.geometry('1168x631+20+10')self.init_window_name['bg']='pink'self.init_window_name.attributes('-alpha',1)#每个控件都需要用pack、place、grid布局去安置,就是设计了一个控件,要放在什么位置的意思。#按钮self.file_choose_button=Button(self.init_window_name,text='选择文件',bg='lightblue',width=10,command=self.thread_file)self.file_choose_button.place(x=40,y=170)   #place布局,x、y指的是距离父窗口左上端点的位置,像素位置self.conduct_button=Button(self.init_window_name,text='执行',bg='lightblue',width=10,command=self.com_output)self.conduct_button.place(x=40,y=455)self.log_save_button=Button(self.init_window_name,text='保存日志',bg='lightblue',width=10,command=self.thread_save)self.log_save_button.place(x=335,y=455)self.clear_button=Button(self.init_window_name,text='清空',bg='lightblue',width=10,command=self.thread_clear)self.clear_button.place(x=460,y=455)#按钮的command参数必须要指向一个函数进行调用,我这里用多线程实现,可以使各按钮的功能无干涉#串口选择框架self.com_choose_frame=Frame(self.init_window_name)self.com_choose_frame.place(x=20,y=12)#框架容纳多个控件,使界面布局更有层次感#串口选择框架内部标签,标签的值一般不做改变self.com_label=Label(self.com_choose_frame,text='COMx: ')self.com_label.grid(row=0,column=0,sticky=E)self.baudrate_label=Label(self.com_choose_frame,text='Baudrate: ')self.baudrate_label.grid(row=1,column=0,sticky=E,pady=10)#串口框架内部下拉选项框self.com_choose=StringVar()self.com_choose_combo=ttk.Combobox(self.com_choose_frame,width=30,textvariable=self.com_choose)self.com_choose_combo['state']='readonly'self.com_choose_combo.grid(row=0,column=1,padx=15)   #grid是表格式结构,行列都从0开始,padx表示x方向上两栏的间距self.com_choose_combo['values']=self.com_name_get()   #这里调用了一个函数,函数的返回值是一个数组#下拉选项框下拉的时候出现很多选项,选中之后只显示选中的选项#波特率选项框self.baudrate_value=StringVar(value='9600')     #StringVar是一个字符串变量控件self.baudrate_choose_combo=ttk.Combobox(self.com_choose_frame,width=30,textvariable=self.baudrate_value)#选项框中选中的值会赋值给字符串变量,并显示在combobox上self.baudrate_choose_combo['values']=('9600','115200')self.baudrate_choose_combo['state']='readonly'self.baudrate_choose_combo.grid(row=1,column=1,padx=15)#串口框架内部按钮self.connect_button=Button(self.com_choose_frame,text='连接',bg='lightblue',width=10,command=self.com_connect)self.connect_button.grid(row=0,column=2,padx=15)self.cancel_button=Button(self.com_choose_frame,text='取消',bg='lightblue',width=10,command=self.com_cancel)self.cancel_button.grid(row=1,column=2,padx=15)#处理结果显示滚动文本框self.result_text=scrolledtext.ScrolledText(self.init_window_name,width=77,height=42)self.result_text.place(x=600,y=50)#滚动文本框是tkinter库自带的一个小封装,将text构件scrollbar滚动条控件组合形成的,可以直接调用#其他文本框self.file_path_text=Text(self.init_window_name,width=57,height=1)self.file_path_text.place(x=150,y=175)self.com_log_text=Text(self.com_choose_frame,width=78,height=5)self.com_log_text.grid(row =2,column =0,columnspan=3,pady=5)self.com_log_text.insert(END,'此处显示串口工作信息'+'\n')           #这一句给字符串变量赋初值#标签self.result_data_label=Label(self.init_window_name,text='输出结果')self.result_data_label.place(x=600,y=15)self.num_input_label=Label(self.init_window_name,text='输入编号: ')self.num_input_label.place(x=150,y=460)#输入编号框self.input_num=StringVar()self.input_num_entry=Entry(self.init_window_name,textvariable=self.input_num,width=10)self.input_num_entry.place(x=215,y=460)#代码解析后进行显示self.code_frame=Frame(self.init_window_name,width=78,height=29,bg='white')self.code_frame.place(x=20,y=210)#解析后的代码放在表格内显示self.code_tree=ttk.Treeview(self.code_frame,show='headings',height=10,columns=('0','1','2','3','4')) #show='headings'会隐藏首列,否则首列太宽self.code_bar=ttk.Scrollbar(self.code_frame,orient=VERTICAL,command=self.code_tree.yview)self.code_tree.configure(yscrollcommand=self.code_bar.set)self.code_tree.grid(row=0,column=0,sticky=NSEW)self.code_bar.grid(row=0,column=1,sticky=NS)self.code_tree.column('0',width=30)self.code_tree.column('1',width=250)self.code_tree.column('2',width=50)self.code_tree.column('3',width=100)self.code_tree.column('4',width=100)self.code_tree.heading('0',text='序号')self.code_tree.heading('1',text='命令')self.code_tree.heading('2',text='状态')self.code_tree.heading('3',text='失败则执行次数')self.code_tree.heading('4',text='再失败则跳转至')#执行结果显示frameself.result_frame=Frame(self.init_window_name,width=78,height=15,bg='white')self.result_frame.place(x=20,y=500)self.result_tree=ttk.Treeview(self.result_frame,show='headings',height=4,columns=('0','1','2'))self.result_bar=ttk.Scrollbar(self.result_frame,orient=VERTICAL,command=self.result_tree.yview)self.result_tree.configure(yscrollcommand=self.result_bar.set)self.result_tree.grid(row=0,column=0,sticky=NSEW)self.result_bar.grid(row=0,column=1,sticky=NS)self.result_tree.column('0',width=30)self.result_tree.column('1',width=80)self.result_tree.column('2',width=420)self.result_tree.heading('0',text='编号')self.result_tree.heading('1',text='是否成功')self.result_tree.heading('2',text='从哪句指令开始失败')#自动获取当前连接的串口名def com_name_get(self):pass#连接按键的执行内容def com_connect(self):pass#取消按键的执行内容def com_cancel(self):pass#执行按键的执行内容def com_output(self):pass#新建线程,负责选择代码文件、保存代码执行结果和清空代码表格#新建选择文件线程def thread_file(self):thisthread=threading.Thread(target=self.file_choose)thisthread.start()#选择文件打开,并在界面中显示def file_choose(self):pass#新建线程保存执行结果def thread_save(self):thisthread=threading.Thread(target=self.code_log_save)thisthread.start()#保存代码执行结果日志def code_log_save(self):pass#新建线程清空所选文件以备重新选择def thread_clear(self):thisthread=threading.Thread(target=self.file_clear)thisthread.start()#删除所选文件,清空解析后的代码表格def file_clear(self):pass
#主线程
def start():init_window=Tk()            #因为写了一个类,所以要产生一个窗口对象,调用类的函数,进行窗口的构造和控件设置my_window=MY_GUI(init_window)my_window.set_init_window()init_window.mainloop()start()

pyserial 库是python用来控制串口的库,串口的开闭、读写都可以直接调用函数

将界面中的控件和串口的控制建立联系,才能在界面里用按钮控制串口,并将读写的内容在界面的滚动文本框里进行打印。
其中,重要的部分是:

1.自动获取电脑的可用串口名,并作为串口下拉选项框的选项
import re                       #正则表达式,可匹配任何字段
import serial.tools.list_ports  #获取串口名直接调用这个工具
def com_name_get(self):self.port_list=list(serial.tools.list_ports.comports())self.com_port_names=[]self.pattern=re.compile(r'[(](.*?)[)]',re.S) if len(self.port_list)>0:for i in range(len(self.port_list)):self.com_name=re.findall(self.pattern,str(self.port_list[i]))self.com_port_names.append(self.com_name)return self.com_port_names

在设备管理器里面查看串口的话,会发现COM1这个字段即串口名字是用括号括起来的,用serial.Serial开启串口只需要把COM1这个字段进行赋值,也就是只将电脑的串口名的括号内的字段捕获,并给serial赋值,开启这个串口。

pattern=re.compile(r'[(](.*?)[)]',re.S) 
com_name=re.findall(self.pattern,str(self.port_list[i]))

以上两句是正则表达式匹配括号内的值的方法。

2.点击连接按钮,在串口日志文本框显示串口是否成功打开,如果串口连接的设备有自动启动程序,则读取设备自启动程序的输出内容并显示
import time
def com_connect(self):self.result_text.insert(END,'请连接串口设备'+'\n')self.ser_name=str(self.com_choose.get())self.ser_baudrate=str(self.baudrate_value.get())try:self.ser=serial.Serial(self.ser_name)self.ser.baudrate=self.ser_baudrateself.ser.timeout=0.5self.com_log_text.insert(END,time.ctime(time.time())+'\t\t'+'串口成功打开'+'\n')self.com_log_text.see(tkinter.END)self.com_log_text.update()while True:newline=self.ser.readline()#字节类型self.result_text.insert(END,newline)self.result_text.see(tkinter.END)self.result_text.update()except:newline=time.ctime(time.time())+'\t\t'+'串口打开故障或串口被关闭'+'\n'self.com_log_text.insert(END,newline)self.com_log_text.see(tkinter.END)self.com_log_text.update()

这三句可以实现text文本框的动态打印,不会将原有内容清楚,一直向下滚动打印

text.insert(END,newline)
text.see(tkinter.END)
text.update()

这个串口工具还包括解析一个excel表格,将表格中的内容写入串口,将串口的执行结果写道界面的两个表格里显示,以及保存等,暂时还没写入文章,有了新的文章会把链接贴上。敬请期待~

这篇关于python3+tkinter+pyserial编写一个串口控制工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/744442

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

超强的截图工具:PixPin

你是否还在为寻找一款功能强大、操作简便的截图工具而烦恼?市面上那么多工具,常常让人无从选择。今天,想给大家安利一款神器——PixPin,一款真正解放双手的截图工具。 想象一下,你只需要按下快捷键就能轻松完成多种截图任务,还能快速编辑、标注甚至保存多种格式的图片。这款工具能满足这些需求吗? PixPin不仅支持全屏、窗口、区域截图等基础功能,它还可以进行延时截图,让你捕捉到每个关键画面。不仅如此

Python3 BeautifulSoup爬虫 POJ自动提交

POJ 提交代码采用Base64加密方式 import http.cookiejarimport loggingimport urllib.parseimport urllib.requestimport base64from bs4 import BeautifulSoupfrom submitcode import SubmitCodeclass SubmitPoj():de

控制反转 的种类

之前对控制反转的定义和解释都不是很清晰。最近翻书发现在《Pro Spring 5》(免费电子版在文章最后)有一段非常不错的解释。记录一下,有道翻译贴出来方便查看。如有请直接跳过中文,看后面的原文。 控制反转的类型 控制反转的类型您可能想知道为什么有两种类型的IoC,以及为什么这些类型被进一步划分为不同的实现。这个问题似乎没有明确的答案;当然,不同的类型提供了一定程度的灵活性,但

PR曲线——一个更敏感的性能评估工具

在不均衡数据集的情况下,精确率-召回率(Precision-Recall, PR)曲线是一种非常有用的工具,因为它提供了比传统的ROC曲线更准确的性能评估。以下是PR曲线在不均衡数据情况下的一些作用: 关注少数类:在不均衡数据集中,少数类的样本数量远少于多数类。PR曲线通过关注少数类(通常是正类)的性能来弥补这一点,因为它直接评估模型在识别正类方面的能力。 精确率与召回率的平衡:精确率(Pr

husky 工具配置代码检查工作流:提交代码至仓库前做代码检查

提示:这篇博客以我前两篇博客作为先修知识,请大家先去看看我前两篇博客 博客指路:前端 ESlint 代码规范及修复代码规范错误-CSDN博客前端 Vue3 项目开发—— ESLint & prettier 配置代码风格-CSDN博客 husky 工具配置代码检查工作流的作用 在工作中,我们经常需要将写好的代码提交至代码仓库 但是由于程序员疏忽而将不规范的代码提交至仓库,显然是不合理的 所

10个好用的AI写作工具【亲测免费】

1. 光速写作 传送入口:http://u3v.cn/6hXWYa AI打工神器,一键生成文章&ppt 2. 讯飞写作 传送入口:http://m6z.cn/5ODiSw 3. 讯飞绘文 传送入口:https://turbodesk.xfyun.cn/?channelid=gj3 4. AI排版助手 传送入口:http://m6z.cn/6ppnPn 5. Kim