《APM32芯得》系列內容為用戶使用APM32系列產品的經驗總結,均轉載自21ic論壇極海半導體專區,全文未作任何修改,未經原文作者授權禁止轉載。
1. 為什么要做GUI與打包EXE
更友好、更直觀
如果我們給同事展示一個命令行,他們可能會有點“嚇人”的感覺,擔心忘記或輸錯參數。而一個 UI 界面則是一目了然,“選擇固件→點擊下載”這樣的流程幾乎零學習成本。
無需安裝Python
經常在產線或測試環境中,電腦系統可能很久不會升級,也沒有裝Python。要想讓他們去裝Python+庫依賴,就比較麻煩。而如果能打包成EXE,所有Python解釋器、第三方模塊都內置其中,對外只需要雙擊文件即可啟動GUI。一旦配置好,就可以在任何Windows機器上復用。
可延伸的封裝思路
有了GUI后,我們還可以更進一步添加“固件版本管理”“設備自動識別”“燒寫統計”等功能,把它變成一個靈活的產線工具。
2. 實現GUI的思路與技術選型
在Python里做GUI并不復雜,一般常見選項是
Tkinter(Python 標準庫自帶,輕量基礎)
PyQt/PySide(功能強大,界面美觀,但相對體量大)
wxPython、Kivy等其他選項
對于“簡單的產線燒寫工具”來說,Tkinter足夠勝任,所以本篇使用Tkinter 作演示。
3. 設計功能需求:“又簡單又夠用” 為了在界面上實現基本的燒寫操作,我們梳理了下面幾項功能:
1. 選擇自定義腳本:用戶可以選擇自定義腳本,因為G32R501核心DCS功能需要特定的腳本進行KEY寫入,這個我們需要關注。
2.選擇固件:用戶能通過文件對話框,選擇.hex或.bin格式固件。
3.擦除操作:一鍵擦除Flash,讓G32R501的存儲空間干凈如新。
4.下載操作:把選定的固件文件下載到目標芯片中,并可通過進度提示或成功/失敗信息告訴用戶結果。
5.仿真器識別:如果電腦插著多個調試器或多個板子,可以列出來讓用戶選。
4. 代碼層級:分文件設計
以下是示例代碼,思路供參考。我們可以根據項目規模或個人習慣決定是否拆分成多個.py文件。這里分拆成若干功能模塊,好處是層次更清晰,也便于后續維護。
4.1 文件結構概覽 假設我們有個目錄PyOCDDownloadToolGUI,內部結構大概是:
PyOCDDownloadToolGUI/
├─ main.py # 程序入口 - 啟動GUI、Tkinter界面邏輯
├─ download_operation.py # 下載功能
├─ erase_operation.py # 擦除功能
├─ file_selector.py # 打開文件對話框
├─ get_debuggers.py # 獲取當前CMSIS-DAP設備列表
└─ get_supported_targets.py # 獲取當前pyocd支持芯片列表
4.2 核心代碼演示
下面我們聚焦主要內容,展現部分代碼,以下兩段代碼演示了如何調用 pyocd 的命令行。
4.2.1 erase_operation.py(擦除功能)
"""
實現對目標芯片的全擦除函數erase_chip()。
若用戶勾選了自定義腳本路徑,則在命令行中附加 --script=<腳本路徑>。
"""
import subprocess
import sys
def erase_chip(target_name, user_script=None):
"""
Perform chip erase using pyOCD command.
- target_name: e.g. 'g32r501dxx'
- user_script: path to user script, or None if not used
Return the command output for logging or error info.
"""
cmd = ["pyocd", "erase", "--chip", "--target", target_name]
if user_script:
cmd.append(f"--script={user_script}")
try:
if sys.platform.startswith("win"):
# Windows專用
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = 0 # 0 對應 SW_HIDE
result = subprocess.run(
cmd,
startupinfo=si,
capture_output=True,
text=True,
check=False
)
else:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=False
)
return result.stdout + result.stderr
except Exception as e:
return f"Error executing erase_chip: {e}"
4.2.2 download_operation.py (下載功能)
"""
實現下載固件函數 download_firmware(),
針對 .bin 文件可附加 --format bin 和 --base-address 參數;
針對 .hex 文件則直接 pyocd load -t
"""
import subprocess
import sys
def download_firmware(target_name, file_path, file_type, user_script=None, base_address=None):
"""
Download firmware to target chip using 'pyocd load'.
- target_name: e.g. 'g32r501dxx'
- file_path: absolute path of the firmware
- file_type: 'bin' or 'hex'
- user_script: if not None, specify '--script=xxx'
- base_address: for .bin format, required if user wants to specify
Return the command output for logging.
"""
cmd = ["pyocd", "load", "-t", target_name]
# If user_script is specified
if user_script:
cmd.append(f"--script={user_script}")
# If it's bin, add extra options
if file_type == "bin":
cmd.extend(["--format", "bin"])
# If user provided base address
if base_address is not None:
cmd.extend(["--base-address", str(base_address)])
# Finally, add the firmware file path
cmd.append(file_path)
try:
if sys.platform.startswith("win"):
# Windows專用
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = 0 # 0 對應 SW_HIDE
result = subprocess.run(
cmd,
startupinfo=si,
capture_output=True,
text=True,
check=False
)
else:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
check=False
)
return result.stdout + result.stderr
except Exception as e:
return f"Error executing download_firmware: {e}"
最終啟動效果:

5. 打包成EXE:PyInstaller“一鍵搞定”
這是本篇文章最重要的部分:如何把這個GUI打包成一個單獨可執行文件。
5.1 為什么選用PyInstaller
使用簡單:只需寫一個spec文件,或者直接pyinstaller xxx.py就能包裝出dist文件夾。
依賴收集:它會自動收集.py文件、第三方依賴、.dll文件等,打包到一起。
常規方案:是Python社區里最常見、成熟度高的打包工具之一。
5.2 PyInstaller打包步驟
(1) 命令行打包GUI
只需在命令行(在main.py同級目錄下啟動)中執行以下命令:
pyinstaller --onefile --noconsole --name PyOCDDownloadToolGUI main.py
命令解釋:
--onefile:生成一個單文件 EXE,啟動時會自解壓到臨時目錄里。
--noconsole:不彈出額外的命令行窗口,讓界面更干凈;如果想看調試信息,可以去掉此參數。
--name PyOCDDownloadToolGUI:指定生成的 EXE 文件名;如省略則默認與腳本同名。
main.py:我們的 GUI 入口腳本。
執行完該命令后,PyInstaller 會在當前目錄下生成一個 dist 文件夾,里面就有 PyOCDDownloadToolGUI.exe。
(2) 打包 PyOCD 本身
PyOCD也帶有pyocd.exe命令行工具。如果我們把它也打包到和PyOCDDownloadToolGUI.exe同一目錄,下次就可以不再額外安裝pyocd或python。
打包方法如下:
1. 從GitHub(https://codeload.github.com/pyocd/pyOCD/zip/refs/tags/v0.37.0)下載pyOCD的源碼壓縮包 (例如v0.37.0)。
2. 解壓后,在根目錄找到pyocd.py和pyocd.spec文件。
3. 將這兩個文件復制到我們已經完成了G32R501適配工作的本地pyocd所在目錄的父目錄里(注意:這個目錄與pyocd同級,而不是放到它的子目錄下)。比如默認Python的site-packages路徑:
C:Users<用戶名>AppDataLocalProgramsPythonPython312Libsite-packagespyocd
4. 在存放pyocd.spec的目錄啟動cmd,輸入命令:
pyinstaller pyocd.spec
5. 打包完成后,會在dist文件夾下生成一個針對pyocd的可執行文件及其相關資源。
6. 運行與演示
當我們完成打包后,distPyOCDDownloadToolGUI下會出現PyOCDDownloadToolGUI.exe。
把這整個文件夾 + 我們打包好的pyocd.exe文件夾,拷貝到一臺沒有Python的Windows 電腦上,插上G32R501開發板 + 調試器,直接雙擊 PyOCDDownloadToolGUI.exe,理論上就能彈出我們的燒寫GUI。
試著點擊“Download/Erase/Verify”按鈕,即可正常工作。
注:文章作者在原帖中提供了代碼文件,有需要請至原文21ic論壇
原文地址:https://bbs.21ic.com/icview-3467862-1-1.html
-
燒寫
+關注
關注
0文章
59瀏覽量
14857 -
GUI
+關注
關注
3文章
697瀏覽量
43459 -
python
+關注
關注
57文章
4876瀏覽量
90022
原文標題:APM32芯得 EP.67 | G32R501與PyOCD的進階應用:一鍵GUI+打包EXE,讓燒寫更優雅
文章出處:【微信號:geehysemi,微信公眾號:Geehy極海半導體】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
如何將Python GUI程序打包成EXE可執行文件
評論