tkinter编写的串口助手——带CRC校验功能,可以读取松下侍服驱动器的线圈信息!!!

在这里插入图片描述
功能函数部分代码

import threading
import tkinter as tk
import serial
import serial.tools.list_ports
from tkinter import ttk
from tkinter import scrolledtext
from tkinter import END
import tkinter.messagebox
import binascii
import time

SerialPort = serial.Serial()
##创建窗口
GUI = tk.Tk()
GUI.title("松下伺服串口调试助手.(All copyrights reserved by Dage)")
GUI.geometry("530x380")
GUI.resizable(0, 0)

##发送函数
def WriteData():
    try:
        #global DataSend
        DataSend = EntrySend.get()
        DataSend = calc_crc16_modbus(DataSend)
        if CrcStatus.get() == 1:
            Information_Window.insert("end", '发送指令为:' + DataSend + '\n')
            Information_Window.see("end")
            DataSendHex = binascii.a2b_hex(DataSend)
            SerialPort.write(DataSendHex)
        else:
            DataSend = DataSend[:-4]
            Information_Window.insert("end", '发送指令为:' + DataSend + '\n')
            Information_Window.see("end")
            DataSendHex = binascii.a2b_hex(DataSend)
            SerialPort.write(DataSendHex)
    except:
        tk.messagebox.showinfo('Port Error', '串口未打开')
        return None

##接收函数
def ReceiveData():
    while SerialPort.isOpen():
        try:
            ReceiveDataStr = SerialPort.readline().hex()
            if len(ReceiveDataStr) != 0:
                global TRANSDATA
                TRANSDATA = ReceiveDataStr
                ReturnData = ReceiveDataStr[:-4]
                ReturnCRC = calc_crc16_modbus(ReturnData)[-4:]
                if ReturnCRC == ReceiveDataStr[-4:]:
                    Receive_Window.insert("end", ReceiveDataStr + ' √'+'\n')
                    Receive_Window.see("end")
                else:
                    Receive_Window.insert("end", ReceiveDataStr + ' ×'+'\n')
                    Receive_Window.see("end")
        except:
            SerialPort.close()

##关闭串口
def Close_Serial():
    tk.Label(option, background='tomato', text="串口已关闭").grid(column=1, row=2,sticky='w')
    SerialPort.close()

##打开串口
def Open_Serial():
    SerialPort.port = Port_list.get()
    SerialPort.baudrate = BaudRate_list.get()
    SerialPort.bytesize = 8
    SerialPort.stopbits = 1
    SerialPort.timeout = 0.1
    try:
        SerialPort.open()
    except:
        tk.messagebox.showwarning('Port Error', '串口已打开或无此串口')
        return None
    if SerialPort.isOpen():
        tk.Label(option, background='lime',text="串口已开启").grid(column=1, row=2,sticky='w')
        t = threading.Thread(target=ReceiveData)
        t.setDaemon(True)
        t.start()

##增加CRC校验码
def calc_crc16_modbus(string):
    data = bytearray.fromhex(string)
    #data = string
    crc = 0xFFFF
    for pos in data:                    #pos是position的缩写是data的substr
        crc ^= pos
        for i in range(8):
            if ((crc & 1) == 1):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    A=hex(((crc & 0xff) << 8) + (crc >> 8))
    B=data.hex()
    return (B+A[2:6])

##清除所有窗口
def ClearAllDisplay():
    Information_Window.delete(0.0, END)
    Receive_Window.delete(0.0, END)

##读取编码器数值
def ReadRecoder():
    try:
        Data = '01 03 42 02 00 02'
        Data  = calc_crc16_modbus(Data)
        DataSendHex = binascii.a2b_hex(Data)
        SerialPort.write(DataSendHex)
        time.sleep(0.2)
        t2.delete(1.0,tkinter.END)
        #print(int(TRANSDATA[10:14]+TRANSDATA[6:10],16))
        t2.insert(1.0,int(TRANSDATA[10:14]+TRANSDATA[6:10],16))
    except:
        tk.messagebox.showinfo('Port Error', '串口未打开或读取编码器数值失败')
        return None

##读取圈数
def ReadRounds():
    try:
        Data = '01 03 42 04 00 01'
        Data  = calc_crc16_modbus(Data)
        DataSendHex = binascii.a2b_hex(Data)
        SerialPort.write(DataSendHex)
        t1.delete(1.0,tkinter.END)
        print ('22222')
        if TRANSDATA[0:7] == '010302f':
            #print( (65535- int(TRANSDATA[6:10],16) ) )
            t1.insert(1.0,'-')
            t1.insert(1.1 ,(65535- int(TRANSDATA[6:10],16) ))
        elif TRANSDATA[0:7]  == '0103020':
            #print(int(TRANSDATA[6:10],16))
            t1.insert(1.0,'+')
            t1.insert(1.1, int(TRANSDATA[6:10], 16))
        else:
            return None
    except:
        tk.messagebox.showinfo('Port Error', '串口未打开或读取圈数失败')
        return None

##圈数清零
def ClearRounds():
    try:
        Data = '01 06 41 00 61 65'
        Data  = calc_crc16_modbus(Data)
        DataSendHex = binascii.a2b_hex(Data)
        SerialPort.write(DataSendHex)
    except:
        tk.messagebox.showinfo('Port Error', '串口未打开或圈数清零失败')
        return None

def ChangeCrcSelText():
    if CrcStatus.get() == 1:
        CrcSelText.set('CrcSel')
    else:
        CrcSelText.set('CrcUnSel')

UI部分代码

#***************************  UI ****************************

######串口设定#####
option = tk.LabelFrame(GUI, text="串口设定", padx=10, pady=10)  # 水平,垂直方向上的边距均为10
option.place(x=10, y=10, width=250)  # 定位坐标
tk.Label(option, text="    串口号:        ").grid(column=0, row=0,sticky='w')  # 添加串口号标签
tk.Label(option, text="    波特率:        ").grid(column=0, row=1,sticky='w')  # 添加波特率标签
tk.Label(option, text="串口已关闭").grid(column=1, row=2,sticky='w')
tk.Button(option, text="打开串口", command=Open_Serial).grid(column=0, row=3)
tk.Button(option, text="关闭串口", command=Close_Serial).grid(column=1,row=3)
Port = tk.StringVar()  # 端口号字符串
Port_list = ttk.Combobox(option, width=15, textvariable=Port, state='readonly')
ListPorts = list(serial.tools.list_ports.comports())
Port_list['values'] = [i[0] for i in ListPorts]
Port_list.current(0)
Port_list.grid(column=1, row=0)
BaudRate = tk.StringVar()
BaudRate_list = ttk.Combobox(option, width=15, textvariable=BaudRate, state='readonly')
BaudRate_list['values'] = (1200, 2400, 4800, 9600, 14400, 19200, 38400, 43000, 57600, 76800, 115200)
BaudRate_list.current(10)
BaudRate_list.grid(column=1, row=1)

######操作指令#####
Send = tk.LabelFrame(GUI, text="操作指令", padx=5, pady=5)  # 水平,垂直方向上的边距均为 10
Send.place(x=10, y=155)
DataSend = tk.StringVar()  # 定义DataSend为保存文本框内容的字符串
EntrySend = tk.StringVar()
Send_Window = ttk.Entry(Send, textvariable=EntrySend, width=25)
Send_Window.grid()
tk.Button(Send, text="发送", command=WriteData).grid(pady=5, sticky=tk.E)

######CRC校验后的操作指令#####
Information = tk.LabelFrame(GUI, text="增加CRC校验后的操作指令", padx=5, pady=5)  # 水平,垂直方向上的边距均为10
Information.place(x=270, y=10)
Information_Window = scrolledtext.ScrolledText(Information, width=30, height=5, padx=5, pady = 10,wrap = tk.WORD)
Information_Window.grid()

######接收指令#####
Receive = tk.LabelFrame(GUI, text="接收指令", padx=5, pady=5)  # 水平,垂直方向上的边距均为 10
Receive.place(x=270, y=130)
Receive_Window = scrolledtext.ScrolledText(Receive, width=30, height=5, padx=5, pady=10, wrap=tk.WORD)
Receive_Window.grid()

######清除按钮#####
tk.Button(text="清除", command=ClearAllDisplay).place(x=220,y=170)

######CRC选择######
CrcSelText = tk.StringVar()
CrcSelText.set('CrcUnSel')
CrcStatus = tk.IntVar()
tk.Checkbutton(GUI, variable=CrcStatus,command=ChangeCrcSelText).place(x=225,y=210)  # 给Checkbutton添加选中事件
tk.Label(GUI, textvariable=CrcSelText).place(x=210,y=230)

######读回编码器信息#####
Recoder = tk.LabelFrame(GUI, text="编码器信息读取", padx=5, pady=5)  # 水平,垂直方向上的边距均为10
Recoder.place(x=10, y=250)

tk.Label(Recoder, text=" 圈数解析:").grid(column=0, row=0)
t1 = tk.Text(Recoder,width=15, height=1)
t1.grid(column=1, row=0)

tk.Label(Recoder, text="编码值解析:").grid(column=0, row=2)
t2 = tk.Text(Recoder,width=15, height=1)
t2.grid(column=1, row=2)

tk.Button(Recoder, text="读取圈数", command=ReadRounds).grid(column=3, row=0)
tk.Button(Recoder, text="圈数清零", command=ClearRounds).grid(column=5, row=0)
tk.Button(Recoder, text="读编码值", command=ReadRecoder).grid(column=3, row=2)

tk.Label(Recoder, text="").grid(column=0, row=1)
tk.Label(Recoder, text="").grid(column=2, row=0)
tk.Label(Recoder, text="").grid(column=4, row=0)

GUI.mainloop()
Pycharm是一款功能强大的集成开发环境(IDE),而TkinterPython标准库中用于创建GUI应用程序的工具包。如果想要用Pycharm和Tkinter实现串口助手,可以按照以下步骤进行: 1. 在Pycharm中新建一个Python项目。 2. 使用pip或者PyCharm自的包管理器,安装pyserial模块以便进行串口通信。可以通过在PyCharm的终端窗口中运行命令`pip install pyserial`来安装。 3. 创建一个新的Python文件,并导入Tkinter和pyserial模块。 ```python import tkinter as tk import serial ``` 4. 创建一个Tkinter应用程序的主窗口,并设置其标题和大小。 ```python root = tk.Tk() root.title("串口助手") root.geometry("400x300") ``` 5. 创建一个串口对象,并设置其参数。 ```python ser = serial.Serial() ser.port = 'COM1' # 设置串口号 ser.baudrate = 9600 # 设置波特率 ser.timeout = 1 # 设置超时时间 ``` 6. 创建一个函数用于处理串口数据的接收和发送。 ```python def serial_communication(): # 数据接收 data = ser.readline().decode("utf-8") receive_data_label.config(text=data) # 数据发送 ser.write("Hello World".encode("utf-8")) ``` 7. 在主窗口中添加按钮和标签等GUI组件,以便控制串口的打开和关闭,并显示接收到的数据。 ```python open_button = tk.Button(root, text="打开串口", command=lambda: ser.open()) open_button.pack() close_button = tk.Button(root, text="关闭串口", command=lambda: ser.close()) close_button.pack() receive_data_label = tk.Label(root, text="接收到的数据") receive_data_label.pack() ``` 8. 运行Tkinter应用程序的主循环。 ```python root.mainloop() ``` 通过以上步骤,我们就可以在Pycharm中使用Tkinter实现一个简单的串口助手。当点击打开按钮时,会打开指定的串口,并通过串口接收数据并显示在标签中;当点击关闭按钮时,会关闭串口连接。同时,可以通过编写其他的按钮和输入框等组件来实现更多功能,如发送特定的数据等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值