
源码是在https://blog.csdn.net/chencaw/article/details/105782159/链接的基础上改的,修改了一些bug,优化了串口接收数据
import serial
import serial.tools.list_ports
import time
import threading
from tkinter import *
from tkinter.ttk import *
DATA = "" # 读取的数据
NOEND = True # 是否读取结束
class cbh_Serial():
def __init__(self):
self.ser = serial.Serial()
self.showinterface()
def on_closing(self):
global NOEND
NOEND=False
if self.ser.isOpen():
self.thread.join()
self.ser.close()
self.root.destroy()
# 读数据的本体
def read_data(self,ser):
global DATA, NOEND
while NOEND:
if self.ser.in_waiting :
time.sleep(0.01)
DATA = self.ser.read(self.ser.in_waiting).decode()
#print(DATA)
self.recv.insert(END, DATA)
def open_seri(self,portx, bps, timeout):
global NOEND
ret = False
try:
self.ser = serial.Serial(portx, bps, timeout=timeout)
# 判断是否成功打开
if self.ser.isOpen():
ret = True
# 创建一个子线程去等待读数据
self.thread = threading.Thread(target=self.read_data, args=(self.ser,))
# read_data函数中会使用NOEND做判断
NOEND = True
self.thread.start()
except Exception as e:
print("error!", e)
return self.ser, ret
def btn_hit(self):
global NOEND
if self.ser.isOpen():
NOEND = False
self.thread.join()
self.ser.close()
self.comopenbtnstr.set("打开串口")
else:
# None表示等待时间为一直等待
self.ser, ret = self.open_seri(self.cbcomportvar.get(),self.cbcombpsvar.get(), None)
# 判断串口是否成功打开
if ret==True:
self.comopenbtnstr.set("关闭串口")
def showinterface(self):
self.root = Tk()
self.root.title("串口调试助手")
#self.root.geometry("560x500")
# 打开串口按钮
self.comopenflagstr = StringVar()
self.comopenflagstr.set("串口状态")
self.labelname = Label(self.root,textvariable = self.comopenflagstr)
self.comopenbtnstr = StringVar()
self.comopenbtnstr.set("打开串口")
self.btnopencom = Button(self.root,textvariable = self.comopenbtnstr,command = self.btn_hit)
# 获取存在的端口号
self.comlist=[]
port_list = list(serial.tools.list_ports.comports())
if len(port_list) == 0:
print('无可用串口')
self.comlist.append("无串口")
self.btnopencom['state'] = 'disabled'
else:
for i in range(0,len(port_list)):
plist_com = port_list[i]
plist_com = list(port_list[i])
self.comlist.append(plist_com[0])
self.labelport = Label(self.root,text="端口号")
self.cbcomportvar = StringVar()
self.cbport = Combobox(self.root,textvariable=self.cbcomportvar)
self.cbport["value"]=tuple(self.comlist)
self.cbport.current(0)
# 波特率
self.labelbps = Label(self.root,text="波特率")
self.cbcombpsvar = StringVar()
self.cbbps = Combobox(self.root,textvariable=self.cbcombpsvar)
self.cbbps["value"]=("115200")
self.cbbps.current(0)
# 发送数据
self.btncomsend = Button(self.root,text = "发送",command = self.btn_sendcmd)
self.sendx=StringVar()
self.sendcmd=Entry(self.root,textvariable=self.sendx)
# 接收数据
self.labelrecv = Label(self.root,text="接收的数据")
self.recv = Text(self.root, width=80, height= 24)
self.recv_clean = Button(self.root,text = "清空",command = self.btn_clean_recv)
# grid布局
self.labelname.grid(row=0,column=0, pady=2, padx=3,sticky=W)
self.btnopencom.grid(row=0,column=1, pady=2, padx=3,sticky=E+W)
self.labelport.grid(row=1,column=0, pady=2, padx=3,sticky=W)
self.cbport.grid(row=1,column=1, pady=2, padx=3,sticky=E+W)
self.labelbps.grid(row=2,column=0, pady=2, padx=3,sticky=W)
self.cbbps.grid(row=2,column=1, pady=2, padx=3,sticky=E+W)
self.btncomsend.grid(row=3,column=0,pady=2, padx=3,sticky=W)
self.sendcmd.grid(row=3,column=1,pady=2, padx=3,sticky=W+E)
self.labelrecv.grid(row=4,column=0,columnspan=2,padx=3,pady=3,sticky=W)
self.recv_clean.grid(row=4, column=1,pady=2, padx=3,sticky=W)
self.recv.grid(row=7,column=0,columnspan=2,padx=3,pady=3,sticky=W+E)
# 阻止Python GUI的大小调整
self.root.resizable(0,0)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.root.mainloop()
def btn_clean_recv(self):
self.recv.delete(1.0, END)
def btn_sendcmd(self):
if self.ser.isOpen():
#text = b'c'
text = self.sendx.get()
self.ser.write(str.encode(text))
if __name__ == "__main__":
myserial = cbh_Serial()
原创文章,作者:Carrie001128,如若转载,请注明出处:https://blog.ytso.com/tech/python/278460.html