日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

matlab制作以太网数据接收上位机_Python制作串口通讯上位机

發布時間:2024/9/30 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 matlab制作以太网数据接收上位机_Python制作串口通讯上位机 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

????串口通訊具有簡單易用的特點廣泛應用于測試設備的通訊和數據傳遞、單片機與計算機的通訊等,本案例基于Python語言制作一個用于接收燃油質量流量計的串口通訊上位機,實現數據的讀取和保存。

1. 相關知識點:

1.1 Python GUI庫

GUI開發是開發具有用戶圖形界面的程序,在打包成可執行文件.exe之后,具有用戶界面的程序具有更好地交互性和易用性,Python中常用的GUI庫如下:

Tkinter:是Python內置的GUI庫,小巧簡單,著名的Python IDLE就是用tkinter實現的,在Windows, MacOS和Linux平臺均可使用,適合用于開發界面簡單的程序。

PyQt: 功能強大的GUI開發庫,具有方便的周邊工具支持,如QtDesigner, Eric等;但由于其功能強大,因此安裝較為繁瑣,運行也較為龐大,此外還需掌握一定的C++知識,PyQt同樣可應用于Windows,Mac OS和Linux平臺;該GUI庫適合開發界面復雜、功能強大的程序。

wxPython: wxPython則是tkinter和PyQt的一個折中選擇,功能也介于兩者之間,也具有與PyQt類似的可視化開發工具。

對于GUI庫的選擇,需要根據自己的需求而定,本例中由于制作的串口通訊上位機界面和功能都較為簡單,因此選擇最易上手的tkinter庫制作。

1.2 類和對象

?????? 面向對象的程序設計往往是GUI程序設計的基礎,讓程序具有更好地封裝性。類(class)是對象的一種抽象,描述了對象的特征,包括數據和操作;對象(object)是類的一個具體化,是由數據及能對其實施的操作所構成的封裝體。也就是說,類不占用內存,而對象占用內存。例如:“狗”這個概念即可看作一個類,而名叫“小黃”的這條狗則是“狗”這個類的具體化對象,它具有類的特征,占用“內存“。

? ?

?圖片來源:中國大學Mooc—用Python玩轉數據

1.3 串口通訊

?????? 串行接口簡稱串口(COM口),是采用串行通信方式的擴展接口。串行接口(Serial Interface)是指數據一位一位地順序傳送。其特點是通信線路簡單,只要一對傳輸線就可以實現雙向通信,從而大大降低了成本,特別適用于遠距離通信,但傳送速度較慢。目前常用的串口標準有RS-232、RS-422和RS-485,在功能上主要差別體現在抗干擾能力、最大傳輸速度和最大傳輸距離上。在目前計算機上使用串口通訊需要配備一根USB轉串口線(如下圖),在正確安裝通訊線的驅動后,可在計算機的設備管理器中看到相應的COM口。

????在Python編程語言中,pyserial庫封裝了串口通訊模塊,可以像文件讀寫一樣操作串口,如用read,write等函數,極大地簡化了串口的操作。使用pyserial之前需要對這個庫進行安裝,方法非常簡單,打開cmd命令提示符界面,輸入pip install pyserial等待片刻即可自動安裝好pyserial庫。

1.4 線程

線程(英語:thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。(上述內容摘抄自百度百科)

一個線程中可以對另一個線程進行操作,如創建、停止等,同一進程中的多個線程之間可以并發執行。Threading模塊是python眾多線程模塊中功能強大,易于使用的線程管理模塊,對線程的支持較為完善,絕大多數情況下,只需要使用 threading 這個高級模塊就夠了。

本例制作用于接收串口信號的GUI程序至少需要兩個線程,一個線程用于響應用于對于GUI程序的界面操作,如點擊按鈕,另一個線程用于不停地接收并顯示串口數據。

1.5 通訊協議

通訊協議指的是數據通訊的方式,即通訊雙方約定好的數據解讀方法,若通訊協議不正確會導致接收到的數據沒有被正確地“翻譯”而無法獲取所需的信息。正確的通訊協議包括了正確地數據線接線、正確的波特率和正確的數據格式等。本例中采用RS422的5線制接線方式,波特率為2400,1位起始位,8位數據位,1位校驗位(奇校驗),1位停止位。具體來說就是在起始位和停止位之間的8位數據位用于傳輸一個字符信息,典型地為ASCII碼字符,而一組完整的數據往往由多個ASCII碼字符組成,也就是需要進行多次傳輸才能完整地傳輸出一組完整信息。在本例中,數據格式如下圖所示,每位數據位之間間隔20 ms,每一組數據以回車結束;一組數據發送完后間隔50 ms:

? ? ? ?由于串口通訊的特性,數據只能一位一位地傳輸,因此我們讀取串口數據也需要從緩存區一位一位地讀取,可以根據每位數據傳輸的時間間隔來設定緩存區的讀取間隔,如在本例中可采用10 ms讀取一次的方式,讀取到有數據之后將數據傳送到程序中,并清空緩存區,等待下一次讀取。

2 串口通訊上位機制作流程

2.1 最終結果

?????? 首先看一下本例中制作的串口通訊上位機的最終結果,如下圖所示。該上位機程序包含四個功能模塊:左上角的串口通訊,左下角的原始數據顯示,右上角的實時數據顯示,右下角的文件保存。

????具體的使用流程和功能如下圖:啟動軟件后,首先需要選擇或者輸入串口號,這里利用下拉菜單動態識別可用串口;點擊開始采集之后,開始采集以及串口配置區域變為不可用,停止采集按鈕變為可用,同時左下角的數據接收框開始顯示接收到的原始數據,右上角的數據顯示框顯示轉換之后的數據信息;在想要保存采集數據時,設置好右下角區域的路徑、文件名、數據名和采集數量之后,點擊記錄數據即可將當前數據寫入到文件。在程序運行過程中,原始數據區域會不斷地接收信號,為了避免長時間的數據堆積導致運行速度變慢,在數據滿300行或者點擊清空內容按鈕時,該數據框實現一次清空操作;當然,也可手動點擊清空按鈕。

????在上面這張操作演示圖中,由于手邊沒有硬件設備,這里用了虛擬串口(左下軟件)和串口調試助手(左上軟件)來模擬實際的儀器所發送的串口數據;右上角軟件為本文開發的采集軟件,其用到的串口也事先由虛擬串口配置好了。右下角是保存數據所在的文件夾。

2.2 堆代碼的枯燥過程

2.2.1 類的定義

?????? 對于GUI編程,通常將界面的控件、變量和函數封裝成一個類,在使用時實例化一個該類的具體對象,進行相關的操作。通常而言,一個類的定義需要包含一個初始化函數和若干變量以及函數,在類的對象實例化時自動執行初始化函數中的內容;為了保證無論在類中哪個函數下定義的變量都具有整個類的作用域,往往需要在定義的變量前加self進行聲明。如self.x這個變量的作用域是整個類,而直接定義的變量x作用域只有當前函數中。在本例中類進行如下的定義。更具體地,在后面將分模塊、分功能對代碼進行解讀。

class myGUI: def__init__(self): #定義窗口界面、控件、變量、執行的操作 #Self.varname defReadUART(self): #串口讀取操作 defSavetofile(self): #保存文件的操作GUI = myGUI() #實例化對象

2.2.2 窗口和控件的定義

?????? 在Tkinter中,界面的生成需要依靠代碼實現,一個控件大約需要2-4行代碼即可,一般界面和控件的生成需要在初始化函數中完成,界面生成和部分控件的生成代碼如下:

def__init__(self): self.window = tk.Tk() self.window.title("油耗采集_byJianxiong Hua") self.APPlabel = ttk.Label(self.window, text = "FCM油耗采集軟件",font = ('黑體', 20)) self.APPlabel.grid(row = 1, column = 1, rowspan = 2, columnspan = 4,sticky = tk.N) self.frame_COMinf = tk.Frame(self.window) self.frame_COMinf.grid(row=3, column=1) self.RunInf = tk.StringVar(value = '請選擇串口號!') # TK變量,儲存提示信息 self.labelInf = ttk.Label(self.frame_COMinf, textvariable = self.RunInf) self.labelInf.grid(row = 3, column = 2, padx = 5, pady = 3)

????在上述代碼中,首先用self.window=tk.Tk()生成一個窗口,用于承載所有的控件,然后設置其title特性;然后以self.window為載體定義了一個叫做self.APPlabel的標簽(Label)控件,該控件僅用于顯示信息,可對其text內容和字體等進行設置,然后用grid函數將其固定(若不固定則不會顯示在window上);同理,接下來定義了一個名叫self.frame_COMinf的Frame框,然后以這個Frame又定義了一個用于顯示運行狀態信息的label。這里涉及到控件的變量傳遞:在Tkinter中控件之間傳遞變量需要用到TK變量,這里的tk.StringVar就是一個字符類型的TK變量,它與self.labelInf中的textvariable特征關聯起來了,在程序運行中若想要更改self.labelInf顯示的信息只需要修改對應的TK變量,這里是名叫self.RunInf的這個StringVar變量。更多的變量傳遞用法在后面有更詳細地介紹。

????除了label控件,還需要用到輸入框(Entry), 按鈕(Button), 下拉框(Combobox)等。值得一提的是,本例中的Entry, Button, Label和Combobox控件用的是ttk而非tk,二者在用法上幾乎相同,而ttk的界面顯示更加美觀,符合win7和win10的系統風格。下面以Combobox為例,再介紹一下控件的定義:

???????self.labelBaudrate?=?ttk.Label(self.frame_COMinf,?text?=?'波特率:') self.Baudrate = tk.IntVar(value = 2400) #定義TK中的整數變量,存儲波特率 self.comboBaudrate = ttk.Combobox(self.frame_COMinf, width = 12,textvariable = self.Baudrate) self.comboBaudrate["values"] = (100, 300, 600, 1200, 2400,4800, 9600, 14400, 19200, 38400, 56000) self.labelBaudrate.grid(row = 5, column = 1, padx = 5, pady = 3) self.comboBaudrate.grid(row = 5, column =2, padx = 5, pady = 3)

?????? 上述代碼中combobox默認的值為2400,若點擊下拉箭頭將出現數組中定義的100,300,……,56000等數值。

2.2.3 自動查詢可用串口號

?????? 自動查詢可用串口號即點擊串口的下拉框時動態刷新可用串口,要想實現該功能需要在初始化函數中定義combobox時將對應的函數與下拉框動作相綁定,然后將動態刷新串口功能在對應的函數中實現,具體如下:

def__init__(self): …… self.COM = tk.StringVar(value = '') #定義TK中的字符變量,存儲一個串口號 self.comboCOM = ttk.Combobox(self.frame_COMinf, width = 12, textvariable= self.COM, postcommand = self.Port_List) #單機下拉時觸發self.Port_List方法 self.comboCOM.grid(row = 4, column = 2, padx = 5, pady = 3) …… def Port_List(self): port_list = list(serial.tools.list_ports.comports()) port_serial = [] #*******以下提取COM口的端口號******* if len(port_list) <= 0: self.RunInf.set("未找到端口!") else: for i in range(len(port_list)): port_serial.append(list(port_list[i])[0]) self.comboCOM["values"] = port_serial

?????? 上述代碼中涉及到兩個函數,即__initial__()和Port_List(),前者為類的初始化函數,后者為動態獲取可用串口號并將其賦值給相應的下拉框的功能函數。該函數通過postcommand=self.Port_List語句與下拉框的下拉操作相綁定。

2.2.3 按鈕的執行函數綁定和串口打開

?????? 與下拉框綁定執行函數的方法類似,對于按鈕控件則必須綁定相應的函數,以執行點擊按鈕時的操作。這里以開始采集和停止采集按鈕為例進行說明,具體代碼如下:

def __init__(self): …… #開始和停止按鈕 self.buttonStart = ttk.Button(self.window, text = "開始采集", command = self.Start) self.buttonStart.grid(row = 8, column = 1, padx = 5, pady = 3, sticky =tk.E) self.buttonStop = ttk.Button(self.window, text = "停止采集", command = self.Stop) self.buttonStop.grid(row = 8, column = 3, padx = 5, pady = 3) self.buttonStop.configure(state = 'disabled') self.ser = serial.Serial() #串口變量 …… def Start(self): self.ser.port = self.COM.get() #端口號 self.ser.baudrate = self.Baudrate.get() #波特率 self.ser.timeout = 1 #超時設置,1s未讀取到數據則返回結果 strParity = self.Parity.get() #校驗形式 if (strParity == "NONE"): self.ser.parity = serial.PARITY_NONE elif (strParity=="ODD"): self.ser.parity = serial.PARITY_ODD elif(strParity=="EVEN"): self.ser.parity = serial.PARITY_EVEN elif(strParity=="MARK"): self.ser.parity = serial.PARITY_MARK elif(strParity=="SPACE"): self.ser.parity = serial.PARITY_SPACE strStopbits = self.Stopbits.get() #停止位 if (strStopbits == "1"): self.ser.stopbits = serial.STOPBITS_ONE elif (strStopbits == "1.5"): self.ser.stopbits =serial.STOPBITS_ONE_POINT_FIVE elif (strStopbits == "2"): self.ser.stopbits = serial.STOPBITS_TWO self.RunInf.set("串口打開失敗!") self.ser.open() #打開串口 if (self.ser.isOpen()): #判斷是否成功打開 self.buttonStart.configure(state = 'disabled') self.buttonStop.configure(state = 'normal') self.comboCOM.configure(state = 'disabled') self.comboBaudrate.configure(state = 'disabled') self.comboParity.configure(state ='disabled') self.comboStopbits.configure(state = 'disabled') self.RunInf.set("已成功打開串口") self.uartState = True self.ReadUART() #調用讀取串口的程序 def Stop(self): #關閉串口 self.t.cancel() #停止定時器 if (self.ser.isOpen()): self.ser.close() self.buttonStop.configure(state = 'disabled') self.buttonStart.configure(state = 'normal') self.comboCOM.configure(state = 'normal') self.comboBaudrate.configure(state = 'normal') self.comboParity.configure(state = 'normal') self.comboStopbits.configure(state = 'normal') self.RunInf.set("已關閉串口!") self.uartState = False

? ? ? ?這段代碼列出了兩個按鈕(開始采集和停止采集)的功能函數,具體通過定義Button控件時的command=self.Start/Stop屬性將Start/Stop函數與對應的按鈕進行了綁定,這樣在點擊按鈕時即可執行對應的函數。在initial函數中還需要聲明一個串口變量ser,然后再Start函數中對ser變量中的端口號port、波特率baudrate、校驗parity、停止位stopbits、超時時間等進行賦值,然后通過ser.open()打開串口,在判斷串口成功打開后,執行串口讀取函數self.ReadUART()。該函數涉及到線程的使用,在2.2.4節進行介紹。在Stop函數中需要執行的操作就簡單得多,即停止掉線程的定時器以結束串口讀取線程,然后關閉串口,更改按鈕等控件的狀態。Normal為可用狀態,disabled為不可更改的狀態(灰色)。

2.2.4 多線程

?????? 前面已經提到,線程是在一個主程序下并行執行的一些操作,在執行時不受主線程的影響,尤其是在主程序需要執行循環語句的情況下,往往需要啟動新的線程去執行其他任務。這里簡單介紹兩種基于python的多線程方法。

方法一:

import threadingimport timedef test_thread (): print(“testing thread”) time.sleep(0.5)thread1 = threading.Thread(target=test_thread)thread1.start()

?????? 方法一首先需要定義一個需要新線程執行的函數,這里是test_thread()函數,然后利用threading.Thread語句聲明一個線程,目標屬性為test_thread函數,再用start方法啟動該線程即可。線程啟動后即反復不停地執行test_thread()函數,在主程序停止時線程也停止。可以用相應方法

方法二:

import threadingdef test_thread (): print(“testing thread”) globaltimer1 timer1= threading.Timer(0.5, test_thread) timer1.start()timer1 = threading.Timer(0.5, test_thread)timer.start()

?????? 在方法二中,并沒有像方法一中那樣聲明線程對象,而是利用構建線程定時器的方法實現新線程的構建。在主程序中首先第一次構建線程定時器并啟動后,在執行函數中也需要構建線程定時器,這樣每次函數執行完畢后都會有一個線程定時器對象對函數自身進行調用,這樣也實現了線程的功能。這種方式較為靈活,用于簡單的線程操作,還可以用timer1.cancel()方法終止該線程。在本例中即采用的這種方式構建串口線程。

? ? 本例中的串口線程關鍵代碼如下:

def Start(self): …… #打開串口的操作 ……????self.ReadUART()??#調用讀取串口的程序def ReadUART(self): …… #讀取串口數據的操作 …… self.t=threading.Timer(0.005,self.ReadUART) self.t.start() #啟動定時器

????同理,檢測數據接收框長度并自動清零的線程構建如下:

def __init__(self):???????……??????#控件和變量的定義???????……???????self.MonitorText()??#啟動文本框監視器線程,到達一定數量后自動清零???????self.window.mainloop() def MonitorText(self): if len(self.OutputText.get('1.0',tk.END)) > 500: #超過一定長度后自動清零 self.OutputText.delete(1.0,tk.END) self.monitor=threading.Timer(0.1,self.MonitorText) self.monitor.start()

2.2.5 原始數據接收框

?????? 程序的左下角的文本框即為原始數據接收框,用于接收并顯示原始信號,這是一個簡單的控件、按鈕、線程的結合使用。點擊清空內容按鈕可清空接收框的內容,或者在接收框接收到的數據長度超過500時自動清空內容。具體代碼如下:

???def?__init__(self): …… #其他控件和變量的定義操作 …… #**********************數據接收框************ self.frame_Recv = ttk.Frame(self.window) self.frame_Recv.grid(row = 9, column = 1) self.labelRecvName = ttk.Label(self.frame_Recv, text = '接收到的原始數據:') self.labelRecvName.grid(row = 1, column = 1, padx = 5, pady = 1, sticky= tk.W) self.frameTransSon = tk.Frame(self.frame_Recv) #同一個frame用了grid不能用pack,因此建立一個子frame self.frameTransSon.grid(row = 10, column =1, rowspan = 6, columnspan =2, padx = 5, pady = 1) self.scrollbarTrans = tk.Scrollbar(self.frameTransSon) self.scrollbarTrans.pack(side = tk.RIGHT, fill = tk.Y) self.OutputText = tk.Text(self.frameTransSon, wrap = tk.WORD, width =30, height = 8, yscrollcommand = self.scrollbarTrans.set, font =('TimesNewRoman', 8)) self.OutputText.pack() self.buttonClearText = ttk.Button(self.frame_Recv, text = "清空內容", command = self.ClearText) self.buttonClearText.grid(row = 17, column = 1, columnspan = 2, padx =5, pady = 1, sticky = tk.N) ……???????self.MonitorText()??#啟動文本框監視器線程,到達一定數量后自動清零???????…… def ClearText(self): self.OutputText.delete(1.0,tk.END) def MonitorText(self): if len(self.OutputText.get('1.0',tk.END)) > 500: #文本超過一定長度后自動清零 self.OutputText.delete(1.0,tk.END) self.monitor=threading.Timer(0.1,self.MonitorText) self.monitor.start() #啟動定時器monitor

2.2.6 數據傳遞和計算

?????? 在本例的串口程序中,數據傳遞主要包括兩類,一類是控件間的數據傳遞,即將數據傳遞給控件用于顯示或者獲取控件上顯示的數據;另一類是讀取串口緩存區的數據,并做相應的類型轉換后進行相關的計算操作。

?????? 控件間的數據傳遞主要依靠的是一類叫做TK變量的特殊數據類型,其定義方式為a=tk.StringVar(value=’astring’),然后將該TK變量與相應控件的textvariable屬性相綁定,如label1=ttk.Label(window, textvariable=a)。如此一來,在程序中無論何時何處只要對變量a (TK變量)進行了修改,那么在label1上顯示的內容也會隨之更改。除了StringVar類型外,TK變量還有tk.DoubleVar,tk.IntVar等類型,在使用時應該注意給這些變量賦值時需要數據類型正確,否則會出錯。

?????? 對于TK變量值的修改和讀取與傳統的變量有所不同,需要用到set和get方法。例如將剛才定義的a變量進行值的修改,應寫為:a.set(‘this is a string’),要獲取a的數據則應寫為:b = a.get()。另外,除了TK變量外,對于包含內容的控件來說,也可以直接用get和set方法來獲取和修改對應控件的值。

?????? 對于第二類串口緩存區的變量,則需要用到python中的串口操作,用.read()函數讀取緩存區的變量,一般而言串口以SACII碼方式發送數據,因此需要將數據解碼,然后進行后續的操作。本例中的串口讀取部分代碼如下:

?? def?__init__(self): …… self.ser = serial.Serial() self.data = [] …… def ReadUART(self): if (self.uartState): try: ch = self.ser.read() self.RunInf.set("正在采集數據") ch =ch.decode('ASCII') #油耗儀中數據傳輸為ASCII,需要解碼 self.OutputText.insert(tk.END,ch) if ch == 'F': self.ch_flag = 1 #串口數據標志位為1,表示是需要的數據 if self.ch_flag == 0: self.data.clear() if self.ch_flag == 1: #如果是需要的數據則執行以下操作 if ch != 'T': #讀取到T為止 self.data.append(ch) if ch == 'T': #所需要的數據是T之前的5位 self.ch_flag =0 #把標志位置0 except: self.RunInf.set("發生錯誤!") self.t=threading.Timer(0.005,self.ReadUART) self.t.start() #啟動定時器

? ? ? ?在這部分代碼中,在初始化函數中聲明了一個串口操作變量ser,利用該變量可對串口進行操作(2.2.3中介紹了如何打開串口)。在ReadUART函數中用ser.read()方法進行串口讀取,一次讀取一個字符,然后用decode(‘ASCII’)函數進行解碼(內置的函數),將其插入到數據接收框中。接下來判斷讀取到的數據是否在后續計算中會用到,如果會用到則將其添加到data列表變量中(data.append(ch))。這樣一次讀取一個字符,然后該線程一直重復該過程即完成了串口數據的傳遞和計算。

2.2.7 文件保存

?????? 在本例中文件保存的邏輯如下:點擊保存按鈕后,在與之綁定的函數中將保存標志位置為1;由于串口線程獨立于主線程并且無限循環,因此在串口線程中檢測保存標志位是否為1,否則不保存,是1則保存當前的數據。具體地,保存數據時需要獲取路徑、文件名、寫入的內容、寫入的數量等參數,然后每保存一次,采集計數+1,直到保存的數量與設定的數量相等時,將保存標志位置0。具體代碼如下:

def ReadUART(self): if (self.uartState): try: ch = self.ser.read() self.RunInf.set("正在采集數據") …… if self.issave== 1: #判斷保存標志位 self.Savefile() #執行Savefile函數 self.testCount.set(int(self.testCount.get())+ 1) ifint(self.testCount.get()) == int(self.testNum.get()): self.testCount.set('0') self.issave = 0 self.buttonSavetofile.config(state = 'normal') self.data.clear() #接收完數據后清空 except: self.RunInf.set("發生錯誤!") self.t=threading.Timer(0.005,self.ReadUART) self.t.start() #啟動定時器 def Savefile(self): filepath = self.filePath.get() filename = self.fileName.get() wholename = os.path.join(filepath, filename) #完整的路徑+文件名(無后綴) condition = self.conditionName.get() if os.path.exists(filepath) == False: os.mkdir(filepath) with open(wholename+'.txt', 'a') as f1: ls = [condition + '\t' + str(self.AvgFuel.get()) + '\n'] f1.writelines(ls)#===========保存按鈕執行的函數============= def StartSave(self): self.issave = 1 self.buttonSavetofile.config(state = 'disabled')

2.2.8 生成可執行程序

?????? 生成exe需要用到pyinstaller,因此需要首先利用pip install pyinstaller安裝該庫,具體生成exe步驟:

1. 啟動命令提示符;

2. 在命令提示符中進入到包含.py文件和.co文件的文件夾;(直接輸入E:可進入磁盤,輸入cd 文件夾路徑即可進入文件夾)

3. 輸入pyinstaller -D-i ?圖標名稱.ico ?文件名稱.py --noconsole? (--noconsole作用是生成的exe文件在執行時不出現黑色的dos界面)

4. 在dist文件夾中即可找到生成的可執行文件,注意-D是生成一個包含多個文件的文件夾,若將-D替換為-F即可生成只有一個exe的可執行文件,但其啟動速度比-D的文件夾形式更慢.

在后臺回復“FCM”或“串口GUI”或“串口程序”可獲取本例的完整代碼、可執行程序、虛擬串口軟件和串口調試助手的下載鏈接。

留言區

總結

以上是生活随笔為你收集整理的matlab制作以太网数据接收上位机_Python制作串口通讯上位机的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。