要使用这段代码和电路图实现 STM32 的固件下载,你需要按照以下步骤操作:
硬件连接:
-
连接 CH340C 与 STM32:
-
CH340C 是 USB 转串口芯片,它会将 PC 上的 USB 信号转换为串口信号。
-
根据电路图,将 CH340C 的 DTR 和 RTS 引脚 分别连接到 STM32 的 NRST 和 BOOT0 引脚。
-
NRST 用于复位 STM32,BOOT0 用于选择 STM32 启动方式,设置为高电平(BOOT0 = 1)时,STM32 会进入引导加载模式(ISP 模式)。
确保你已正确连接所有电源和地线,尤其是 3.3V 电源,确保 STM32 和 CH340C 都有稳定的电源供应。
-
软件准备:
代码
import serial
import time
import struct
import sys
ACK = 0x79
FLASH_BASE = 0x08000000
PAGE_SIZE = 256 # F0 / F1 通用,够用
TIMEOUT = 1
def xor_checksum(data: bytes):
c = 0
for b in data:
c ^= b
return c & 0xFF
def wait_ack(ser):
r = ser.read(1)
if not r or r[0] != ACK:
raise RuntimeError("No ACK")
def enter_isp(ser):
# pyserial: True = 有效 = 拉低
ser.dtr = True # NRST = 0
ser.rts = True # BOOT0 = 1
time.sleep(0.05)
ser.dtr = False # 释放复位
time.sleep(0.2)
def exit_isp(ser):
ser.rts = False # BOOT0 = 0
time.sleep(0.05)
ser.dtr = True # 再复位一次
time.sleep(0.05)
ser.dtr = False
def sync(ser):
ser.write(b'\x7F')
wait_ack(ser)
def send_cmd(ser, cmd):
ser.write(bytes([cmd, cmd ^ 0xFF]))
wait_ack(ser)
def send_addr(ser, addr):
b = struct.pack(">I", addr)
ser.write(b + bytes([xor_checksum(b)]))
wait_ack(ser)
def write_mem(ser, addr, data):
send_cmd(ser, 0x31) # Write Memory
send_addr(ser, addr)
ln = len(data) - 1
pkt = bytes([ln]) + data
ser.write(pkt + bytes([xor_checksum(pkt)]))
wait_ack(ser)
def main():
if len(sys.argv) != 4:
print("Usage:")
print(" python stm32_uart_download.py COM5 115200 app.bin")
sys.exit(1)
port = sys.argv[1]
baud = int(sys.argv[2])
binf = sys.argv[3]
try:
with open(binf, "rb") as f:
fw = f.read()
except FileNotFoundError:
print(f"错误: 找不到固件文件 '{binf}'")
sys.exit(1)
ser = serial.Serial(
port=port,
baudrate=baud,
timeout=TIMEOUT
)
print("[*] Enter ISP")
enter_isp(ser)
sync(ser)
print("[*] Downloading...")
addr = FLASH_BASE
for i in range(0, len(fw), PAGE_SIZE):
chunk = fw[i:i + PAGE_SIZE]
if len(chunk) < PAGE_SIZE:
chunk += b'\xFF' * (PAGE_SIZE - len(chunk))
write_mem(ser, addr + i, chunk)
print(f" 0x{addr + i:08X}")
print("[*] Done, reboot")
exit_isp(ser)
ser.close()
if __name__ == "__main__":
main()
-
安装 Python 和 pySerial:
-
你需要安装 Python 环境,如果还没有安装,可以从 Python官网 下载并安装 Python。
-
安装
pyserial,这是一个 Python 库,用于串口通信。你可以在命令行中运行以下命令来安装:pip install pyserial
-
-
准备固件文件:
- 确保你有目标固件文件(例如
app.bin)。这个文件包含了需要写入 STM32 的程序代码。
- 确保你有目标固件文件(例如
-
检查串口号:
- 你需要知道连接 CH340C 的串口号。你可以通过设备管理器或终端查看(例如在 Windows 中,你可以查看 "设备管理器" -> "端口 (COM)")。
使用步骤:
-
运行下载程序 :
打开命令行(在 Windows 上可以使用 cmd 或 PowerShell),并进入存放代码文件的目录。然后运行以下命令:
python stm32_uart_download.py COMx 115200 app.bin-
COMx替换为你实际连接 CH340C 的串口号(例如 COM5)。 -
115200是串口波特率,你可以根据需要调整,如果你不确定,115200 是常用的波特率。 -
app.bin是你准备好的固件文件名。
-
-
程序流程:
-
程序会首先进入 ISP 模式(通过控制
DTR和RTS引脚),然后同步与设备通信。 -
程序会分块(每块 256 字节)将固件文件写入 STM32 的 Flash 区域,过程中会等待每次写入的确认(ACK)。
-
完成下载后,程序会退出 ISP 模式,并重启 STM32。
-
-
检查下载状态:
-
如果一切正常,程序会输出下载进度,最后会显示
[*] Done, reboot,这表示固件已经成功写入并且 STM32 被重启。 -
如果出现任何问题(例如未收到 ACK),程序会抛出错误,告知你哪里出现了问题。
-
注意事项:
-
串口连接检查:确保串口没有被其他程序占用,例如其他的串口终端工具。你可以在任务管理器中查看是否有占用串口的程序。
-
固件文件检查:确认固件文件没有损坏,且符合目标 STM32 的存储区域要求。
-
电源稳定:确保在下载过程中电源稳定,避免出现中途掉电等问题。
错误处理:
-
如果程序无法进入 ISP 模式或没有正确下载固件,检查硬件连接和串口设置。
-
如果没有收到 ACK(
No ACK错误),尝试增加超时时间,或者确认 STM32 是否已正确进入 ISP 模式。
打包exe
"C:\Users\dana0\AppData\Roaming\Python\Python311\Scripts\pyinstaller.exe" --onefile --console stm32_isp.py
使用
python stm32_isp.py COMx 115200 app.bin
或者
stm32_isp.exe COMx 115200 app.bin