STM32 BootLoader 刷新项目 (十三) Python上位机介绍
大家好,这是我们STM32 BootLoader的最后一篇文章了,讲述用Python写的上位机,也更新了半年时间了,谢谢大家的支持,到目前为止,已经更新了12篇文章了,想必大家对BootLoader已经有了个基本的了解,下面是Python上位机的全部源码,有需要的兄弟可以借鉴一下,水平有限。
以下是将完整Python代码中的每一行进行解释后的代码,注释全部用中文描述原代码的含义,并对每个函数、常量及代码块作详细中文说明:
1. 全局宏定义
import serial # 导入用于串口通信的模块
import struct # 导入结构化数据处理的模块
import os # 导入操作系统相关功能的模块
import sys # 导入系统功能模块
import glob # 导入文件路径操作模块
# 常量定义 - Flash 操作状态
Flash_HAL_OK = 0x00 # Flash 操作成功
Flash_HAL_ERROR = 0x01 # Flash 操作错误
Flash_HAL_BUSY = 0x02 # Flash 操作繁忙
Flash_HAL_TIMEOUT = 0x03 # Flash 操作超时
Flash_HAL_INV_ADDR = 0x04 # Flash 操作地址无效
# Bootloader命令定义
COMMAND_BL_GET_VER = 0x51 # 获取Bootloader版本
COMMAND_BL_GET_HELP = 0x52 # 获取支持的命令
COMMAND_BL_GET_CID = 0x53 # 获取芯片ID
COMMAND_BL_GET_RDP_STATUS = 0x54 # 获取读保护状态
COMMAND_BL_GO_TO_ADDR = 0x55 # 跳转到指定地址
COMMAND_BL_FLASH_ERASE = 0x56 # Flash擦除命令
COMMAND_BL_MEM_WRITE = 0x57 # Flash写入命令
COMMAND_BL_EN_R_W_PROTECT = 0x58 # 启用读写保护
COMMAND_BL_MEM_READ = 0x59 # 内存读取命令
COMMAND_BL_READ_SECTOR_P_STATUS = 0x5A # 读取扇区保护状态
COMMAND_BL_OTP_READ = 0x5B # 读取OTP(一次性可编程)区域
COMMAND_BL_DIS_R_W_PROTECT = 0x5C # 禁用读写保护
COMMAND_BL_MY_NEW_COMMAND = 0x5D # 用户自定义命令
# 各命令的长度定义
COMMAND_BL_GET_VER_LEN = 6 # 获取Bootloader版本命令长度
COMMAND_BL_GET_HELP_LEN = 6 # 获取支持的命令长度
COMMAND_BL_GET_CID_LEN = 6 # 获取芯片ID命令长度
COMMAND_BL_GET_RDP_STATUS_LEN = 6 # 获取读保护状态命令长度
COMMAND_BL_GO_TO_ADDR_LEN = 10 # 跳转地址命令长度
COMMAND_BL_FLASH_ERASE_LEN = 8 # Flash擦除命令长度
COMMAND_BL_MEM_WRITE_LEN = 11 # Flash写入命令长度
COMMAND_BL_EN_R_W_PROTECT_LEN = 8 # 启用读写保护命令长度
COMMAND_BL_READ_SECTOR_P_STATUS_LEN = 6 # 读取扇区保护状态命令长度
COMMAND_BL_DIS_R_W_PROTECT_LEN = 6 # 禁用读写保护命令长度
COMMAND_BL_MY_NEW_COMMAND_LEN = 8 # 用户自定义命令长度
# 全局变量
verbose_mode = 1 # 是否输出详细日志
mem_write_active = 0 # 写内存操作标志
2. 文件操作
# ----------------------------- 文件操作部分 ----------------------------------------
# 计算文件长度
def calc_file_len():
size = os.path.getsize("user_app.bin") # 获取文件 user_app.bin 的大小
return size # 返回文件大小
# 打开文件
def open_the_file():
global bin_file # 声明全局变量 bin_file
bin_file = open('user_app.bin', 'rb') # 以二进制只读方式打开文件 user_app.bin
# 读取文件 - 占位函数
def read_the_file():
pass # 暂未实现
# 关闭文件
def close_the_file():
bin_file.close() # 关闭文件句柄
上面文件操作这部分代码主要是针对BootLoader刷写过程中要打开写入的.bin文件。
3. 实用工具部分
# ----------------------------- 实用工具部分 ----------------------------------------
# 地址转换为字节
def word_to_byte(addr, index, lowerfirst):
value = (addr >> (8 * (index - 1)) & 0x000000FF) # 提取地址的某一字节
return value # 返回字节值
# CRC32校验计算
def get_crc(buff, length):
Crc = 0xFFFFFFFF # 初始化CRC值
for data in buff[0:length]: # 遍历缓冲区中所有字节
Crc = Crc ^ data # 异或操作
for i in range(32): # 遍历每一位
if(Crc & 0x80000000): # 检测最高位
Crc = (Crc << 1) ^ 0x04C11DB7 # CRC计算多项式
else:
Crc = (Crc << 1) # 左移操作
return Crc # 返回计算结果
这部分主要是给后面代码做一些实用类的函数,方便后面调用,主要是两个,一个是将地址转化为字节。一个是用作CRC校验。
4. 串口部分
# ----------------------------- 串口部分 ----------------------------------------
# 列出所有可用的串口
def serial_ports():
"""列出系统中的所有串口名称"""
if sys.platform.startswith('win'): # Windows系统
ports = ['COM%s' % (i + 1) for i in range(256)] # 枚举所有可能的COM端口
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): # Linux或Cygwin系统
ports = glob.glob('/dev/tty[A-Za-z]*') # 查找所有TTY设备
elif sys.platform.startswith('darwin'): # macOS系统
ports = glob.glob('/dev/tty.*') # 查找所有TTY设备
else:
raise EnvironmentError('Unsupported platform') # 不支持的系统
result = []
for port in ports:
try:
s = serial.Serial(port) # 打开串口
s.close() # 关闭串口
result.append(port) # 将可用串口加入结果列表
except (OSError, serial.SerialException): # 捕获异常
pass
return result # 返回可用串口列表
# 配置串口
def Serial_Port_Configuration(port):
global ser # 声明全局变量 ser
try:
ser = serial.Serial(port, 115200, timeout=2) # 打开串口,波特率115200,超时时间2秒
except:
print("\n Oops! That was not a valid port")