串口调试工具(Python2.7+pyserial+Tkinter)
生活随笔
收集整理的這篇文章主要介紹了
串口调试工具(Python2.7+pyserial+Tkinter)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
需要與串口設備進行通訊,那么一個調試工具是必須的。
根據我自己的需要,寫了個簡易版本的串口調試工具:
預覽圖:
======================
項目結構:
COM
--SerialHelper.py
UI
--Adaptive.py
--SerialTool.py
--PyTkinter.py
main.py
======================
COM文件夾
SerialHelper.py 串口通訊幫助類
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 '''
5 Serial設備通訊幫助類
6 '''
7 __author__ = "jakey.chen"
8 __version__ = "v1.0"
9
10 import sys
11 import threading
12 import time
13 import serial
14 import binascii
15 import logging
16
17 class SerialHelper(object):
18 def __init__(self, Port="COM6", BaudRate="9600", ByteSize="8", Parity="N", Stopbits="1"):
19 '''
20 初始化一些參數
21 '''
22 self.l_serial = None
23 self.alive = False
24 self.port = Port
25 self.baudrate = BaudRate
26 self.bytesize = ByteSize
27 self.parity = Parity
28 self.stopbits = Stopbits
29 self.thresholdValue = 64
30 self.receive_data = ""
31
32 def start(self):
33 '''
34 開始,打開串口
35 '''
36 self.l_serial = serial.Serial()
37 self.l_serial.port = self.port
38 self.l_serial.baudrate = self.baudrate
39 self.l_serial.bytesize = int(self.bytesize)
40 self.l_serial.parity = self.parity
41 self.l_serial.stopbits = int(self.stopbits)
42 self.l_serial.timeout = 2
43
44 try:
45 self.l_serial.open()
46 if self.l_serial.isOpen():
47 self.alive = True
48 except Exception as e:
49 self.alive = False
50 logging.error(e)
51
52 def stop(self):
53 '''
54 結束,關閉串口
55 '''
56 self.alive = False
57 if self.l_serial.isOpen():
58 self.l_serial.close()
59
60 def read(self):
61 '''
62 循環讀取串口發送的數據
63 '''
64 while self.alive:
65 try:
66 number = self.l_serial.inWaiting()
67 if number:
68 self.receive_data += self.l_serial.read(number).replace(binascii.unhexlify("00"), "")
69 if self.thresholdValue <= len(self.receive_data):
70 self.receive_data = ""
71 except Exception as e:
72 logging.error(e)
73
74 def write(self, data, isHex=False):
75 '''
76 發送數據給串口設備
77 '''
78 if self.alive:
79 if self.l_serial.isOpen():
80 if isHex:
81 # data = data.replace(" ", "").replace("
", "")
82 data = binascii.unhexlify(data)
83 self.l_serial.write(data)
84
85 if __name__ == '__main__':
86 import threading
87 ser = SerialHelper()
88 ser.start()
89
90 ser.write("123", isHex=False)
91 thread_read = threading.Thread(target=ser.read)
92 thread_read.setDaemon(True)
93 thread_read.start()
94 import time
95 time.sleep(25)
96 ser.stop()
View Code
======================
UI文件夾
Adaptive.py 防止錯位
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import platform
5
6 g_systemName = platform.system()
7 g_systemInfo = platform.platform()
8 g_pyVersion = platform.python_version()
9 size_dict = dict()
10
11 # System will be Linux and python == 2.7
12 if g_systemName == "Linux" and g_pyVersion[:3] == "2.7":
13 if "Ubuntu" in g_systemInfo:
14 size_dict = {
15 "list_box_height": 20,
16 "send_text_height": 12,
17 "receive_text_height": 15,
18 "reset_label_width": 24,
19 "clear_label_width": 22
20 }
21
22 # raspberry pi
23 elif "armv6l" in g_systemInfo:
24 size_dict = {
25 "list_box_height": 19,
26 "send_text_height": 12,
27 "receive_text_height": 15,
28 "reset_label_width": 24,
29 "clear_label_width": 22
30 }
31 else:
32 if g_systemInfo[:9]== "Windows-8":
33 size_dict = {
34 "list_box_height": 14,
35 "send_text_height": 6,
36 "receive_text_height": 18,
37 "reset_label_width": 7,
38 "clear_label_width": 5
39 }
40
41 elif g_systemInfo[:9]== "Windows-7":
42 size_dict = {
43 "list_box_height": 13,
44 "send_text_height": 12,
45 "receive_text_height": 15,
46 "reset_label_width": 7,
47 "clear_label_width": 5
48 }
49
50 elif g_systemInfo[:10]== "Windows-XP":
51 size_dict = {
52 "list_box_height": 20,
53 "send_text_height": 12,
54 "receive_text_height": 22,
55 "reset_label_width": 7,
56 "clear_label_width": 5
57 }
58
59 # font
60 monaco_font = ('Monaco', 12)
View Code
PyTkinter.py 根據個人喜好來初始化一些Tkinter控件的顏色配置
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 '''
5 Tkinter控件初始化配置(默認為深色)
6 '''
7 __author__ = "jakey.chen"
8 __version__ = "v1.0"
9
10
11 import Tkinter as tk
12
13 g_default_theme = "dark"
14 # g_default_theme = "default"
15
16 class PyButton(tk.Button):
17 '''
18 Button
19 '''
20 def __init__(self, master, theme=g_default_theme, **kv):
21 self.theme = theme
22 self.kv = kv
23 self.temp = dict()
24 self.choose_theme()
25 tk.Button.__init__(self, master, self.temp)
26
27 def choose_theme(self):
28 if self.theme == "dark":
29 dark_theme_dict = {
30 "activebackground": "#00B2EE",
31 "activeforeground": "#E0EEEE",
32 "bg": "#008B8B",
33 "fg": "#FFFFFF"
34 }
35 for key,value in dark_theme_dict.items():
36 self.temp[key] = value
37
38 for key,value in self.kv.items():
39 self.temp[key] = value
40
41 class PyLabel(tk.Label):
42 '''
43 Label
44 '''
45 def __init__(self, master, theme=g_default_theme, **kv):
46 self.theme = theme
47 self.kv = kv
48 self.temp = dict()
49 self.choose_theme()
50 tk.Label.__init__(self, master, self.temp)
51
52 def choose_theme(self):
53 if self.theme == "dark":
54 dark_theme_dict = {
55 "bg": "#292929",
56 "fg": "#E0EEEE"
57 }
58 for key,value in dark_theme_dict.items():
59 self.temp[key] = value
60
61 for key,value in self.kv.items():
62 self.temp[key] = value
63
64 class PyLabelFrame(tk.LabelFrame):
65 '''
66 Frame
67 '''
68 def __init__(self, master, theme=g_default_theme, **kv):
69 self.theme = theme
70 self.kv = kv
71 self.temp = dict()
72 self.choose_theme()
73 tk.LabelFrame.__init__(self, master, self.temp)
74
75 def choose_theme(self):
76 if self.theme == "dark":
77 dark_theme_dict = {
78 "bg": "#292929",
79 "fg": "#1E90FF"
80 }
81 for key,value in dark_theme_dict.items():
82 self.temp[key] = value
83
84 for key,value in self.kv.items():
85 self.temp[key] = value
86
87 class PyListbox(tk.Listbox):
88 '''
89 Listbox
90 '''
91 def __init__(self, master, theme=g_default_theme, **kv):
92 self.theme = theme
93 self.kv = kv
94 self.temp = dict()
95 self.choose_theme()
96 tk.Listbox.__init__(self, master, self.temp)
97
98 def choose_theme(self):
99 if self.theme == "dark":
100 dark_theme_dict = {
101 "bg": "#292929",
102 "fg": "#1E90FF",
103 "selectbackground": "#00B2EE"
104 }
105 for key,value in dark_theme_dict.items():
106 self.temp[key] = value
107
108 for key,value in self.kv.items():
109 self.temp[key] = value
110
111 class PyText(tk.Text):
112 '''
113 Text
114 '''
115 def __init__(self, master, theme=g_default_theme, **kv):
116 self.theme = theme
117 self.kv = kv
118 self.temp = dict()
119 self.choose_theme()
120 tk.Text.__init__(self, master, self.temp)
121
122 def choose_theme(self):
123 if self.theme == "dark":
124 dark_theme_dict = {
125 "bg": "#292929",
126 "fg": "#1E90FF"
127 }
128 for key,value in dark_theme_dict.items():
129 self.temp[key] = value
130
131 for key,value in self.kv.items():
132 self.temp[key] = value
133
134 class PyCheckbutton(tk.Checkbutton):
135 '''
136 Checkbutton
137 '''
138 def __init__(self, master, theme=g_default_theme, **kv):
139 self.theme = theme
140 self.kv = kv
141 self.temp = dict()
142 self.choose_theme()
143 tk.Checkbutton.__init__(self, master, self.temp)
144
145 def choose_theme(self):
146 if self.theme == "dark":
147 dark_theme_dict = {
148 "bg": "#292929",
149 "fg": "#FFFFFF",
150 "activebackground": "#292929",
151 "activeforeground": "#FFFFFF",
152 "selectcolor": "#292929"
153 }
154 for key,value in dark_theme_dict.items():
155 self.temp[key] = value
156
157 for key,value in self.kv.items():
158 self.temp[key] = value
159
160 class PyRadiobutton(tk.Radiobutton):
161 '''
162 Radiobutton
163 '''
164 def __init__(self, master, theme=g_default_theme, **kv):
165 self.theme = theme
166 self.kv = kv
167 self.temp = dict()
168 self.choose_theme()
169 tk.Radiobutton.__init__(self, master, self.temp)
170
171 def choose_theme(self):
172 if self.theme == "dark":
173 dark_theme_dict = {
174 "bg": "#292929",
175 "fg": "#FFFFFF",
176 "activebackground": "#292929",
177 "selectcolor": "#292929"
178 }
179 for key,value in dark_theme_dict.items():
180 self.temp[key] = value
181
182 for key,value in self.kv.items():
183 self.temp[key] = value
184
185
186 class PyEntry(tk.Entry):
187 '''
188 Entry
189 '''
190 def __init__(self, master, theme=g_default_theme, **kv):
191 self.theme = theme
192 self.kv = kv
193 self.temp = dict()
194 self.choose_theme()
195 tk.Entry.__init__(self, master, self.temp)
196
197 def choose_theme(self):
198 if self.theme == "dark":
199 dark_theme_dict = {
200 "bg": "#292929",
201 "fg": "#E0EEEE",
202 "insertbackground": "#E0EEEE"
203 }
204 for key,value in dark_theme_dict.items():
205 self.temp[key] = value
206
207 for key,value in self.kv.items():
208 self.temp[key] = value
209
210 if __name__ == '__main__':
211 root = tk.Tk()
212 root.configure(bg="#292929")
213 PyButton(root, text="1234", font=("Monaco", 12)).pack()
214 PyLabel(root, text="123", font=("Monaco", 15)).pack()
215 PyCheckbutton(root, text="123", font=("Monaco", 15)).pack()
216 PyEntry(root, font=("Monaco", 15)).pack()
217 PyText(root, font=("Monaco", 15), height=2, width=20).pack()
218 listbox_0 = PyListbox(root, height=2, font=("Monaco", 15))
219 listbox_0.pack()
220 for i in range(2):
221 listbox_0.insert("end", i)
222 radio_intvar = tk.IntVar()
223 PyRadiobutton(root, text="001", variable=radio_intvar, value=0, font=("Monaco", 15)).pack()
224 PyRadiobutton(root, text="002", variable=radio_intvar, value=1, font=("Monaco", 15)).pack()
225 radio_intvar.set(1)
226
227 root.mainloop()
View Code
SerialTool.py 主界面
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import Tkinter as tk
5 import ttk
6 import PyTkinter as pytk
7 import Adaptive
8
9 font = Adaptive.monaco_font
10 size_dict = Adaptive.size_dict
11 g_default_theme = pytk.g_default_theme
12
13
14 class SerialToolUI(object):
15 def __init__(self, master=None):
16 self.root = master
17 self.create_frame()
18 self.thresholdValue = 1
19
20 def create_frame(self):
21 '''
22 新建窗口,分為上下2個部分,下半部分為狀態欄
23 '''
24 self.frm = pytk.PyLabelFrame(self.root)
25 self.frm_status = pytk.PyLabelFrame(self.root)
26
27 self.frm.grid(row=0, column=0, sticky="wesn")
28 self.frm_status.grid(row=1, column=0, sticky="wesn")
29
30 self.create_frm()
31 self.create_frm_status()
32
33 def create_frm(self):
34 '''
35 上半部分窗口分為左右2個部分
36 '''
37 self.frm_left = pytk.PyLabelFrame(self.frm)
38 self.frm_right = pytk.PyLabelFrame(self.frm)
39
40 self.frm_left.grid(row=0, column=0, padx=5, pady=5, sticky="wesn")
41 self.frm_right.grid(row=0, column=1, padx=5, pady=5, sticky="wesn")
42
43 self.create_frm_left()
44 self.create_frm_right()
45
46 def create_frm_left(self):
47 '''
48 上半部分左邊窗口:
49 Listbox顯示可用的COM口
50 Button按鈕點擊連接設備
51 '''
52 self.frm_left_label = pytk.PyLabel(self.frm_left,
53 text="Serial Ports",
54 font=font)
55 self.frm_left_listbox = pytk.PyListbox(self.frm_left,
56 height=size_dict["list_box_height"],
57 font=font)
58 self.frm_left_serial_set = pytk.PyLabelFrame(self.frm_left)
59 self.frm_left_btn = pytk.PyButton(self.frm_left,
60 text="Open",
61 font=font,
62 command=self.Toggle)
63
64 self.frm_left_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
65 self.frm_left_listbox.grid(row=1, column=0, padx=5, pady=5, sticky="wesn")
66 self.frm_left_serial_set.grid(row=2, column=0, padx=5, pady=5, sticky="wesn")
67 self.frm_left_btn.grid(row=3, column=0, padx=5, pady=5, sticky="wesn")
68
69 self.frm_left_listbox.bind("<Double-Button-1>", self.Open)
70 self.create_frm_left_serial_set()
71
72 def create_frm_left_serial_set(self):
73 '''
74 串口配置,比如波特率,奇偶校驗等
75 '''
76 setting_label_list = ["BaudRate :", "Parity :", "DataBit :", "StopBit :"]
77 baudrate_list = ["1200", "2400", "4800", "9600", "14400", "19200", "38400",
78 "43000", "57600", "76800", "115200", "12800"]
79 # PARITY_NONE, PARITY_EVEN, PARITY_ODD PARITY_MARK, PARITY_SPACE
80 parity_list = ["N", "E", "O", "M", "S"]
81 bytesize_list = ["5", "6", "7", "8"]
82 stopbits_list = ["1", "1.5", "2"]
83 for index,item in enumerate(setting_label_list):
84 frm_left_label_temp = pytk.PyLabel(self.frm_left_serial_set,
85 text=item,
86 font=('Monaco', 10))
87 frm_left_label_temp.grid(row=index, column=0, padx=1, pady=2, sticky="e")
88 self.frm_left_combobox_baudrate = ttk.Combobox(self.frm_left_serial_set,
89 width=15,
90 values=baudrate_list)
91 self.frm_left_combobox_parity = ttk.Combobox(self.frm_left_serial_set,
92 width=15,
93 values=parity_list)
94 self.frm_left_combobox_databit = ttk.Combobox(self.frm_left_serial_set,
95 width=15,
96 values=bytesize_list)
97 self.frm_left_combobox_stopbit = ttk.Combobox(self.frm_left_serial_set,
98 width=15,
99 values=stopbits_list)
100 self.frm_left_combobox_baudrate.grid(row=0, column=1, padx=2, pady=2, sticky="e")
101 self.frm_left_combobox_parity.grid(row=1, column=1, padx=2, pady=2, sticky="e")
102 self.frm_left_combobox_databit.grid(row=2, column=1, padx=2, pady=2, sticky="e")
103 self.frm_left_combobox_stopbit.grid(row=3, column=1, padx=2, pady=2, sticky="e")
104
105 self.frm_left_combobox_baudrate.current(3)
106 self.frm_left_combobox_parity.current(0)
107 self.frm_left_combobox_databit.current(3)
108 self.frm_left_combobox_stopbit.current(0)
109
110 def create_frm_right(self):
111 '''
112 上半部分右邊窗口:
113 分為4個部分:
114 1、Label顯示和重置按鈕和發送按鈕
115 2、Text顯示(發送的數據)
116 3、Label顯示和十六進制選擇顯示和清除接收信息按鈕
117 4、Text顯示接收到的信息
118 '''
119 self.frm_right_reset = pytk.PyLabelFrame(self.frm_right)
120 self.frm_right_send = pytk.PyText(self.frm_right,
121 width=50,
122 height=size_dict["send_text_height"],
123 font=("Monaco", 9))
124 self.frm_right_clear = pytk.PyLabelFrame(self.frm_right)
125 self.frm_right_receive = pytk.PyText(self.frm_right,
126 width=50,
127 height=size_dict["receive_text_height"],
128 font=("Monaco", 9))
129
130 self.frm_right_reset.grid(row=0, column=0, padx=1, sticky="wesn")
131 self.frm_right_send.grid(row=1, column=0, padx=1, sticky="wesn")
132 self.frm_right_clear.grid(row=2, column=0, padx=1, sticky="wesn")
133 self.frm_right_receive.grid(row=3, column=0, padx=1, sticky="wesn")
134
135 self.frm_right_receive.tag_config("green", foreground="#228B22")
136
137 self.create_frm_right_reset()
138 self.create_frm_right_clear()
139
140 def create_frm_right_reset(self):
141 '''
142 1、Label顯示和重置按鈕和發送按鈕
143 '''
144 self.frm_right_reset_label = pytk.PyLabel(self.frm_right_reset,
145 text="Data Send" + " "*size_dict["reset_label_width"],
146 font=font)
147 self.new_line_cbtn_var = tk.IntVar()
148 self.send_hex_cbtn_var = tk.IntVar()
149 self.frm_right_reset_newLine_checkbtn = pytk.PyCheckbutton(self.frm_right_reset,
150 text="New Line",
151 variable=self.new_line_cbtn_var,
152 font=font)
153 self.frm_right_reset_hex_checkbtn = pytk.PyCheckbutton(self.frm_right_reset,
154 text="Hex",
155 variable=self.send_hex_cbtn_var,
156 font=font)
157 self.frm_right_reset_btn = pytk.PyButton(self.frm_right_reset,
158 text="Reset",
159 width=10,
160 font=font,
161 command=self.Reset)
162 self.frm_right_send_btn = pytk.PyButton(self.frm_right_reset,
163 text="Send",
164 width=10,
165 font=font,
166 command=self.Send)
167
168 self.frm_right_reset_label.grid(row=0, column=0, sticky="w")
169 self.frm_right_reset_newLine_checkbtn.grid(row=0, column=1, sticky="wesn")
170 self.frm_right_reset_hex_checkbtn.grid(row=0, column=2, sticky="wesn")
171 self.frm_right_reset_btn.grid(row=0, column=3, padx=5, pady=5, sticky="wesn")
172 self.frm_right_send_btn.grid(row=0, column=4, padx=5, pady=5, sticky="wesn")
173
174 def create_frm_right_clear(self):
175 '''
176 3、Label顯示和十六進制顯示和清除接收信息按鈕
177 '''
178 self.receive_hex_cbtn_var = tk.IntVar()
179 self.frm_right_clear_label = pytk.PyLabel(self.frm_right_clear,
180 text="Data Received"+ " "*size_dict["clear_label_width"],
181 font=font)
182 self.frm_right_threshold_label = pytk.PyLabel(self.frm_right_clear,
183 text="Threshold:",
184 font=font)
185 self.thresholdStr = tk.StringVar()
186 self.frm_right_threshold_entry = pytk.PyEntry(self.frm_right_clear,
187 textvariable=self.thresholdStr,
188 width=6,
189 font=font)
190 self.frm_right_hex_checkbtn = pytk.PyCheckbutton(self.frm_right_clear,
191 text="Hex",
192 variable=self.receive_hex_cbtn_var,
193 relief="flat",
194 font=font)
195 self.frm_right_clear_btn = pytk.PyButton(self.frm_right_clear,
196 text="Clear",
197 width=10,
198 font=font,
199 command=self.Clear)
200
201 self.frm_right_clear_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
202 self.frm_right_threshold_label.grid(row=0, column=1, padx=5, pady=5, sticky="wesn")
203 self.frm_right_threshold_entry.grid(row=0, column=2, padx=5, pady=5, sticky="wesn")
204 self.frm_right_hex_checkbtn.grid(row=0, column=3, padx=5, pady=5, sticky="wesn")
205 self.frm_right_clear_btn.grid(row=0, column=4, padx=5, pady=5, sticky="wesn")
206
207 self.thresholdStr.set(1)
208 self.thresholdStr.trace('w', self.GetThresholdValue)
209
210 def create_frm_status(self):
211 '''
212 下半部分狀態欄窗口
213 '''
214 self.frm_status_label = pytk.PyLabel(self.frm_status,
215 text="Ready",
216 font=font)
217 self.frm_status_label.grid(row=0, column=0, padx=5, pady=5, sticky="wesn")
218
219 def Toggle(self):
220 pass
221
222 def Open(self, event):
223 pass
224
225 def Reset(self):
226 self.frm_right_send.delete("0.0", "end")
227
228 def Send(self):
229 pass
230
231 def Clear(self):
232 self.frm_right_receive.delete("0.0", "end")
233
234 def GetThresholdValue(self, *args):
235 try:
236 self.thresholdValue = int(self.thresholdStr.get())
237 except:
238 pass
239
240
241 if __name__ == '__main__':
242 '''
243 main loop
244 '''
245 root = tk.Tk()
246 if g_default_theme == "dark":
247 root.configure(bg="#292929")
248 combostyle = ttk.Style()
249 combostyle.theme_use('alt')
250 combostyle.configure("TCombobox", selectbackground="#292929", fieldbackground="#292929",
251 background="#292929", foreground="#FFFFFF")
252 root.title("Serial-Tool")
253 SerialToolUI(master=root)
254 root.resizable(False, False)
255 root.mainloop()
View Code
======================
界面邏輯主程序
main.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import time
5 import datetime
6 import threading
7 import binascii
8 import platform
9 import logging
10
11 from UI import SerialTool
12 from COM import SerialHelper
13
14 if platform.system() == "Windows":
15 from serial.tools import list_ports
16 elif platform.system() == "Linux":
17 import glob, os, re
18
19 import Tkinter as tk
20 import ttk
21
22 logging.basicConfig(level=logging.DEBUG,
23 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
24 datefmt='%a, %d %b %Y %H:%M:%S')
25
26 class MainSerialToolUI(SerialTool.SerialToolUI):
27 def __init__(self, master=None):
28 super(MainSerialToolUI, self).__init__()
29 self.ser = None
30 self.receive_count = 0
31 self.receive_data = ""
32 self.list_box_serial = list()
33 self.find_all_serial()
34
35 def __del__(self):
36 if platform.system() == "Linux":
37 try:
38 self.ser.SetStopEvent()
39 except:
40 pass
41
42 def find_all_serial(self):
43 '''
44 獲取到串口列表
45 '''
46 if platform.system() == "Windows":
47 try:
48 self.temp_serial = list()
49 for com in list_ports.comports():
50 strCom = com[0] + ": " + com[1][:-7].decode("gbk").encode("utf-8")
51 self.temp_serial.append(strCom)
52 for item in self.temp_serial:
53 if item not in self.list_box_serial:
54 self.frm_left_listbox.insert("end", item)
55 for item in self.list_box_serial:
56 if item not in self.temp_serial:
57 index = list(self.frm_left_listbox.get(0, self.frm_left_listbox.size())).index(item)
58 self.frm_left_listbox.delete(index)
59
60 self.list_box_serial = self.temp_serial
61
62 self.thread_findserial = threading.Timer(1, self.find_all_serial)
63 self.thread_findserial.setDaemon(True)
64 self.thread_findserial.start()
65 except Exception as e:
66 logging.error(e)
67 elif platform.system() == "Linux":
68 try:
69 self.temp_serial = list()
70 self.temp_serial = self.find_usb_tty()
71 for item in self.temp_serial:
72 if item not in self.list_box_serial:
73 self.frm_left_listbox.insert("end", item)
74 for item in self.list_box_serial:
75 if item not in self.temp_serial:
76 index = list(self.frm_left_listbox.get(0, self.frm_left_listbox.size())).index(item)
77 self.frm_left_listbox.delete(index)
78 self.list_box_serial = self.temp_serial
79
80 self.thread_findserial = threading.Timer(1, self.find_all_serial)
81 self.thread_findserial.setDaemon(True)
82 self.thread_findserial.start()
83 except Exception as e:
84 logging.error(e)
85
86 def Toggle(self):
87 '''
88 打開關閉串口
89 '''
90 if self.frm_left_btn["text"] == "Open":
91 try:
92 self.currentStrCom = self.frm_left_listbox.get(self.frm_left_listbox.curselection())
93 if platform.system() == "Windows":
94 self.port = self.currentStrCom.split(":")[0]
95 elif platform.system() == "Linux":
96 self.port = self.currentStrCom
97 self.baudrate = self.frm_left_combobox_baudrate.get()
98 self.parity = self.frm_left_combobox_parity.get()
99 self.databit = self.frm_left_combobox_databit.get()
100 self.stopbit = self.frm_left_combobox_stopbit.get()
101 self.ser = SerialHelper.SerialHelper(Port=self.port,
102 BaudRate=self.baudrate,
103 ByteSize=self.databit,
104 Parity=self.parity,
105 Stopbits=self.stopbit)
106 self.ser.start()
107 if self.ser.alive:
108 self.frm_status_label["text"] = "Open [{0}] Successful!".format(self.currentStrCom)
109 self.frm_status_label["fg"] = "#66CD00"
110 self.frm_left_btn["text"] = "Close"
111 self.frm_left_btn["bg"] = "#F08080"
112
113 self.thread_read = threading.Thread(target=self.SerialRead)
114 self.thread_read.setDaemon(True)
115 self.thread_read.start()
116
117 except Exception as e:
118 logging.error(e)
119 try:
120 self.frm_status_label["text"] = "Open [{0}] Failed!".format(self.currentStrCom)
121 self.frm_status_label["fg"] = "#DC143C"
122 except Exception as ex:
123 logging.error(ex)
124
125 elif self.frm_left_btn["text"] == "Close":
126 try:
127 self.ser.stop()
128 self.receive_count = 0
129 except Exception as e:
130 logging.error(e)
131 self.frm_left_btn["text"] = "Open"
132 self.frm_left_btn["bg"] = "#008B8B"
133 self.frm_status_label["text"] = "Close Serial Successful!"
134 self.frm_status_label["fg"] = "#8DEEEE"
135
136 def Open(self, event):
137 '''
138 雙擊列表打開/關閉串口
139 '''
140 self.Toggle()
141
142 def Clear(self):
143 self.frm_right_receive.delete("0.0", "end")
144 self.receive_count = 0
145
146 def Send(self):
147 '''
148 向已打開的串口發送數據
149 如果為Hex發送,示例:"31 32 33" [即為字符串 "123"]
150 '''
151 if self.ser:
152 try:
153 # 發送新行
154 if self.new_line_cbtn_var.get() == 0:
155 send_data = str(self.frm_right_send.get("0.0", "end").encode("gbk")).strip()
156 else:
157 send_data = str(self.frm_right_send.get("0.0", "end")).strip() + "
"
158
159 # 是否十六進制發送
160 if self.send_hex_cbtn_var.get() == 1:
161 self.ser.write(send_data, isHex=True)
162 else:
163 self.ser.write(send_data)
164 except Exception as e:
165 self.frm_right_receive.insert("end", str(e) + "
")
166 logging.error(e)
167
168 def SerialRead(self):
169 '''
170 線程讀取串口發送的數據
171 '''
172 while self.ser.alive:
173 try:
174 n = self.ser.l_serial.inWaiting()
175 if n:
176 self.receive_data += self.ser.l_serial.read(n).replace(binascii.unhexlify("00"), "")
177 if self.thresholdValue <= len(self.receive_data):
178 self.receive_count += 1
179
180 # 接收顯示是否為Hex
181 if self.receive_hex_cbtn_var.get() == 1:
182 self.receive_data = self.space_b2a_hex(self.receive_data)
183 self.frm_right_receive.insert("end", "[" + str(datetime.datetime.now()) + " - "
184 + str(self.receive_count) + "]:
", "green")
185 self.frm_right_receive.insert("end", self.receive_data + "
")
186 self.frm_right_receive.see("end")
187 self.receive_data = ""
188
189 except Exception as e:
190 logging.error(e)
191 self.receive_data = ""
192 self.ser.stop()
193 self.ser = None
194
195 def find_usb_tty(self, vendor_id=None, product_id=None):
196 '''
197 發現串口設備
198 '''
199 tty_devs = list()
200 for dn in glob.glob('/sys/bus/usb/devices/*') :
201 try:
202 vid = int(open(os.path.join(dn, "idVendor" )).read().strip(), 16)
203 pid = int(open(os.path.join(dn, "idProduct")).read().strip(), 16)
204 if ((vendor_id is None) or (vid == vendor_id)) and ((product_id is None) or (pid == product_id)) :
205 dns = glob.glob(os.path.join(dn, os.path.basename(dn) + "*"))
206 for sdn in dns :
207 for fn in glob.glob(os.path.join(sdn, "*")) :
208 if re.search(r"/ttyUSB[0-9]+$", fn) :
209 tty_devs.append(os.path.join("/dev", os.path.basename(fn)))
210 except Exception as ex:
211 pass
212 return tty_devs
213
214 def space_b2a_hex(self, data):
215 '''
216 格式化接收到的數據字符串
217 示例:123 --> 31 32 33
218 '''
219 new_data_list = list()
220 new_data = ""
221
222 hex_data = binascii.b2a_hex(data)
223 temp_data = ""
224 for index,value in enumerate(hex_data):
225 temp_data += value
226 if len(temp_data) == 2:
227 new_data_list.append(temp_data)
228 temp_data = ""
229 for index,value in enumerate(new_data_list):
230 if index%25 == 0 and index != 0:
231 new_data += "
"
232 new_data += value
233 new_data += " "
234
235 return new_data
236
237 if __name__ == '__main__':
238 '''
239 main loop
240 '''
241 root = tk.Tk()
242 root.title("Serial Tool")
243 if SerialTool.g_default_theme == "dark":
244 root.configure(bg="#292929")
245 combostyle = ttk.Style()
246 combostyle.theme_use('alt')
247 combostyle.configure("TCombobox", selectbackground="#292929", fieldbackground="#292929",
248 background="#292929", foreground="#FFFFFF")
249 MainSerialToolUI(master=root)
250 root.resizable(False, False)
251 root.mainloop()
View Code
項目地址:Serial-Tool
僅根據自己需要寫的串口工具,需要其他功能的話請自行添加,或者告知我添加。
總結
以上是生活随笔為你收集整理的串口调试工具(Python2.7+pyserial+Tkinter)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红魔电竞机械键盘来了:行业独创屏显交互系
- 下一篇: 代驾强行涉水致领克03趴窝 平台称自然灾