用Python做一个上位机进行串口通讯发送16进制指令

Python上位机进行串口通讯发送16进制指令

一、要求

在这里插入图片描述

二、python上位机设计

1.内容描述

在这里插入图片描述


2.串口设置

在这里插入图片描述


3.程序流程图

在这里插入图片描述

4.程序设计(python)

4.1 导入所需库
import tkinter as tk
import tkinter.messagebox
import serial
import serial.tools.list_ports
4.2 通过serial库获取当前串口列表
#Python serial获取串口列表
#serial.tools.list_ports()方法可以获取到串口列表数组,遍历数组,每个元素的name属性就是串口名称(COMx)
plist = list(serial.tools.list_ports.comports())
ports = [p.name for p in plist]
print(ports)
4.3 创建一个上位机窗口
# 创建主窗口
window = tk.Tk()
window.title("python上位机--发送指令")
window.geometry("600x400") #设置窗口大小
4.4 设置串口下拉选择框
# 创建下拉选择框
options = ports
variable = tk.StringVar(window)
if len(options) == 0:
    print("The list is empty")
    options.append("暂无可选端口")  # 设置默认值
else:
    print("The list is not empty")
variable.set(options[0])  # 设置默认值
dropdown = tk.OptionMenu(window, variable, *options)
dropdown.grid(row=0, column=0)
4.5 创建按钮,用于获取选择的值,并打开串口默认配置相应参数

若串口无法使用,便提示相应错误信息

# 创建按钮,用于获取选择的值
def get_value():
    try:
        # 打开串口
        #指定串口号、波特率、校验位、停止位和字节大小等参数。这些参数要与设备使用的串口参数保持一致,否则可能无法正常通信。
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        print(f"当前选择的值:{variable.get()}")
        # 串口选择弹窗
        tk.messagebox.showinfo("提示", f"您选择了:{variable.get()}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")
            
button = tk.Button(window, text="打开串口", command=get_value)
button.grid(row=0, column=3)
4.6 创建文本框,用于显示发送的数据
# 创建文本框
frame = tk.Frame(window)  # 创建一个框架,用于放置文本框和滚动条
text = tk.Text(frame, width=50, height=20)  # 创建文本框,设置宽度和高度
scroll = tk.Scrollbar(frame)  # 创建滚动条
text.pack(side=tk.LEFT)  # 将文本框放在左侧
scroll.pack(side=tk.RIGHT, fill=tk.Y)  # 将滚动条放在右侧,垂直填充
frame.grid(row=0, column=7)

# 将文本框和滚动条关联起来
text.config(yscrollcommand=scroll.set)
scroll.config(command=text.yview)
4.7 定义4个电机按钮触发的函数
# 定义按钮触发的函数
def button_clicked1(button_text):
    try:
        # 打开串口
        #指定串口号、波特率、校验位、停止位和字节大小等参数。这些参数要与设备使用的串口参数保持一致,否则可能无法正常通信。
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0A]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0A\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked2(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0B]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0B\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked3(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0C]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0C\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked4(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0D]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0D\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")
4.8 生成4个电机按钮
# 创建四个按钮
button1 = tk.Button(window, text="启动电机1", command=lambda: button_clicked1("按钮:启动电机1"))
button1.grid(row=2, column=7)
button2 = tk.Button(window, text="启动电机2", command=lambda: button_clicked2("按钮:启动电机2"))
button2.grid(row=3,column=7)
button3 = tk.Button(window, text="启动电机3", command=lambda: button_clicked3("按钮:启动电机3"))
button3.grid(row=4, column=7)
button4 = tk.Button(window, text="停止电机", command=lambda: button_clicked4("按钮:停止电机"))
button4.grid(row=5, column=7)
4.9 运行窗口
# 运行窗口
window.mainloop()
4.10 程序源码
import tkinter as tk
import tkinter.messagebox
import serial
import serial.tools.list_ports

#Python serial获取串口列表
#serial.tools.list_ports()方法可以获取到串口列表数组,遍历数组,每个元素的name属性就是串口名称(COMx)
plist = list(serial.tools.list_ports.comports())
ports = [p.name for p in plist]
print(ports)



# 创建主窗口
window = tk.Tk()
window.title("python上位机--发送指令")
window.geometry("600x400") #设置窗口大小

# 创建下拉选择框
options = ports
variable = tk.StringVar(window)
if len(options) == 0:
    print("The list is empty")
    options.append("暂无可选端口")  # 设置默认值
else:
    print("The list is not empty")
variable.set(options[0])  # 设置默认值
dropdown = tk.OptionMenu(window, variable, *options)
dropdown.grid(row=0, column=0)
# dropdown.pack()

# 创建按钮,用于获取选择的值
def get_value():
    try:
        # 打开串口
        #指定串口号、波特率、校验位、停止位和字节大小等参数。这些参数要与设备使用的串口参数保持一致,否则可能无法正常通信。
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        print(f"当前选择的值:{variable.get()}")
        # 串口选择弹窗
        tk.messagebox.showinfo("提示", f"成功打开{variable.get()}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# # 打开串口
# ser = serial.Serial(variable.get(), baudrate=9600, timeout=1)

button = tk.Button(window, text="打开串口", command=get_value)
button.grid(row=0, column=3)
# button.pack()

# 创建文本框
frame = tk.Frame(window)  # 创建一个框架,用于放置文本框和滚动条
text = tk.Text(frame, width=50, height=20)  # 创建文本框,设置宽度和高度
scroll = tk.Scrollbar(frame)  # 创建滚动条
text.pack(side=tk.LEFT)  # 将文本框放在左侧
scroll.pack(side=tk.RIGHT, fill=tk.Y)  # 将滚动条放在右侧,垂直填充
frame.grid(row=0, column=7)
# frame.pack()

# 将文本框和滚动条关联起来
text.config(yscrollcommand=scroll.set)
scroll.config(command=text.yview)

# 定义按钮触发的函数
def button_clicked1(button_text):
    try:
        # 打开串口
        #指定串口号、波特率、校验位、停止位和字节大小等参数。这些参数要与设备使用的串口参数保持一致,否则可能无法正常通信。
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0A]
        # 发送数据
        ser.write(data)
        # # 数字转16进制 0x形式的字符串,再截取后面2位数
        # hex_string1 = hex(data[0]).upper()[2:]
        # hex_string2 = hex(data[1]).upper()[2:]
        # # print(hex_string1)
        # # 文本插入
        # text.insert("end", "发送命令:"+hex_string1+" "+hex_string2+"\n")  # 在文本框末尾插入
        # print(f"您单击了按钮:{button_text}")
        # 文本插入
        text.insert("end", "发送命令:AA 0A\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked2(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0B]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0B\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked3(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0C]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0C\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")

# 定义按钮触发的函数
def button_clicked4(button_text):
    try:
        # 打开串口
        ser = serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
        # 将命令数据转换为 16 进制数组
        data = [0xAA, 0x0D]
        # 发送数据
        ser.write(data)
        # 文本插入
        text.insert("end", "发送命令:AA 0D\n")  # 在文本框末尾插入
        print(f"您单击了按钮:{button_text}")
    except Exception as e:
            #未选择端口发送,会报错
            print("---异常---:", e)
            # 按钮报错触发弹窗
            tk.messagebox.showinfo("提示", f"---异常---:{e}")



# 创建四个按钮
button1 = tk.Button(window, text="启动电机1", command=lambda: button_clicked1("按钮:启动电机1"))
button1.grid(row=2, column=7)
# button1.pack()
button2 = tk.Button(window, text="启动电机2", command=lambda: button_clicked2("按钮:启动电机2"))
button2.grid(row=3,column=7)
# button2.pack()
button3 = tk.Button(window, text="启动电机3", command=lambda: button_clicked3("按钮:启动电机3"))
button3.grid(row=4, column=7)
# button3.pack()
button4 = tk.Button(window, text="停止电机", command=lambda: button_clicked4("按钮:停止电机"))
button4.grid(row=5, column=7)
# button4.pack()

# 运行窗口
window.mainloop()


三、调试

1.上位机界面

在这里插入图片描述

2.串口检查提示

无可用串口时,打开串口

在这里插入图片描述


3.打开串口

当有多个串口时,默认选择第一个,可自己手动调整

在这里插入图片描述

成功打开串口

在这里插入图片描述

当串口成功打开后,串口的参数会默认自动配置

#指定串口号、波特率、校验位、停止位和字节大小等参数。这些参数要与设备使用的串口参数保持一致,否则可能无法正常通信。
ser =
serial.Serial(variable.get(),baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)

4.发送指令(以16进制格式)

指令默认以16进制发送,不同按钮具有对应的指令,例如“启动电机1”按钮:

# 将命令数据转换为 16 进制数组
data = [0xAA, 0x0A]
# 发送数据
ser.write(data)

当发送后,文本框会显示已发送相应的指令

# 文本插入
text.insert("end", "发送命令:AA 0A\n")  # 在文本框末尾插入

点击相应按钮,会以16进制发送相应的指令,并显示在文本框

在这里插入图片描述


5.实践操作(暂无)

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

索子也敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值