K210固件代码部署
277.3 K210固件代码部署
import sensor # 导入摄像头传感器模块,用于初始化摄像头和采集图像。
import image # 导入图像处理模块,用于裁剪、缩放和人脸对齐。
import lcd # 导入 LCD 模块,用于在 K210 屏幕上显示摄像头画面。
import KPU as kpu # 导入 KPU 神经网络加速模块,并使用 kpu 作为别名。
import time # 导入时间模块,后面用它创建帧率时钟。
from Maix import FPIOA, GPIO # 导入 K210 引脚功能映射和 GPIO 类。
import gc # 导入垃圾回收模块,用于回收循环中产生的临时对象。
from fpioa_manager import fm # 导入 FPIOA 管理器,用它把外部 IO 映射为 UART 功能。
from board import board_info # 导入开发板引脚信息,完整脚本后面会使用板载按键定义。
import utime # 导入适用于 MicroPython 的时间模块。
from machine import UART # 导入硬件 UART 类,用于和 STM32 通信。
from machine import Timer # 导入硬件定时器类,完整脚本保留了定时发送测试代码。
Serial_A_RxBuf = bytearray() # 创建串口接收缓冲区;课程源码保留了该变量,但本脚本后续未实际使用它。
fm.register(GPIO.GPIOHS9,fm.fpioa.UART2_TX) # 把外部 IO9 映射为 K210 UART2 的发送端 TX。
fm.register(GPIO.GPIOHS10,fm.fpioa.UART2_RX) # 把外部 IO10 映射为 K210 UART2 的接收端 RX。
task_fd = kpu.load(0x100000) # 从 Flash 的 0x100000 地址加载人脸检测模型。
task_ld = kpu.load(0x200000) # 从 Flash 的 0x200000 地址加载五点人脸关键点模型。
task_fe = kpu.load(0x300000) # 从 Flash 的 0x300000 地址加载人脸特征提取模型。
# task_fd = kpu.load("/sd/FaceDetection.smodel") # 备用方案:从 SD 卡加载人脸检测模型;课程项目未启用此行。
# task_ld = kpu.load("/sd/FaceLandmarkDetection.smodel") # 备用方案:从 SD 卡加载人脸关键点模型;课程项目未启用此行。
# task_fe = kpu.load("/sd/FeatureExtraction.smodel") # 备用方案:从 SD 卡加载人脸特征提取模型;课程项目未启用此行。
uart_A = UART(UART.UART2, 115200, 8, None, 1, timeout=1000, read_buf_len=4096) # 以 115200、8N1 初始化 UART2,并设置超时和接收缓冲区。
上方只摘录视频实际讲解的
face.py开头部分,代码顺序和有效语句均保持课程源码原样,只替换为适合初学者的逐行注释。按照本项目笔记约定使用c代码围栏,但这些代码实际属于 MaixPy(MicroPython),不是 C 语言,也不是 STM32 端代码。
一、K210 的固件烧写
本节部署过程包含三个不同层次,必须先区分:
| 层次 | 文件 | 写入位置与作用 |
|---|---|---|
| 机器码工具 | key_gen_v1.2.bin | 临时写到 Flash 起始地址,用于输出本机机器码 |
| MaixPy 运行固件 | maixpy_v0.6.2_85_g23d09fbcc_minimum_with_ide_support.bin | 写到 0x000000,提供 MicroPython 解释器和 MaixPy IDE 支持 |
| 人脸模型 | 3 个 .smodel 文件 | 分别写到 0x100000、0x200000、0x300000,供 KPU 按固定地址加载 |
| 项目脚本 | face.py,固化后命名为 boot.py | 先由 MaixPy IDE 临时执行;保存到板载文件系统后可在上电时自动运行 |
因此,“烧固件”“烧模型”“运行脚本”和“保存 boot.py”是四种不同操作。模型不是 Python 源码,face.py 也不是包含在人脸模型中的 K210 固件。
1.1 硬件连接
课程使用的是 Maix Bit 类 K210 开发板。烧录和 IDE 调试时,用一根具备数据传输能力的 USB Type-C 线连接开发板与电脑,板载 USB 转串口电路会在 Windows 中创建 COM 口。原稿所说的“手机充电线”不够准确:仅能充电、没有数据线芯的 Type-C 线无法完成烧录和 IDE 连接。
连接后打开 Windows“设备管理器 → 端口(COM 和 LPT)”,用插拔前后的变化确认开发板对应的 COM 口。视频中的 COM19 只是讲师电脑当时分配的端口号,换一台电脑或 USB 接口后都可能改变。
还要区分两组串口:
- 电脑调试串口:由开发板的 USB 转串口电路提供,供
kflash_gui、串口终端和 MaixPy IDE 使用; - 项目通信串口 UART2:脚本把 K210 的 IO9/IO10 映射为 TX/RX,运行时与 STM32 通信,并不是电脑上显示的 COM 口。
同一时刻只能由一个 Windows 程序占用电脑调试串口。切换 kflash_gui、MaixPy IDE 和串口终端前,应先断开或关闭前一个程序;通常不必物理拔掉 USB 线。若端口仍未释放,再重新插拔数据线。
1.2 烧写步骤
本课程的完整顺序是:
- 烧录机器码工具,读取当前 K210 的机器码;
- 在 MaixHub 中用该机器码获取与本机绑定的人脸识别模型;
- 烧录 MaixPy 运行固件和 3 个人脸模型;
- 用 MaixPy IDE 测试
face.py,再保存为开发板上的boot.py。
其中前两个步骤通常只为取得本机模型执行一次;更换 K210 后,应重新读取新板的机器码并重新获取模型。
1.2.1 烧录获取设备号固件
课程把 MaixHub 所需的标识称为“设备号”“机器码”或“密钥”。它用于生成与当前 K210 绑定的加密模型,不能用讲师或另一块板的机器码替代。本项目归档里甚至把讲师的模型压缩包明确命名为“你们不能用”,因此必须以自己的开发板输出为准。
重要风险:Sipeed 官方 MaixPy FAQ 明确提示,烧录 key_gen.bin 后,K210 的 JTAG 调试功能会被永久关闭。课程文件名是 key_gen_v1.2.bin,属于同类机器码生成固件。在执行此步骤前,应先确定该芯片以后是否还需要 JTAG 调试;已经关闭后不能靠重新刷 MaixPy 固件恢复。
读取机器码的步骤如下:
- 解压课程提供的
kflash_gui工具包,运行其中的kflash_gui.exe。 - 添加
固件/key_gen_v1.2.bin,把烧录地址设为0x000000,烧录位置选择 Flash。 - 选择实际的 COM 口。开发板型号可先用自动识别;若高速下载失败,应选择准确板型,降低下载波特率或改用低速模式。
- 单击“下载”,等待工具明确提示成功。下载时摄像头画面停住,是因为机器码工具已经替换了地址 0 处原先运行的 MaixPy 固件,而不是“摄像头损坏”或“模型一定被打乱”。
- 关闭
kflash_gui,在 MaixPy IDE 中打开串行终端,选择相同 COM 口并使用115200波特率;必要时按一下开发板复位键,使启动输出重新打印。 - 完整复制终端输出的机器码并妥善保存。复制时不要漏字符、夹带空格或错选相邻日志。
1.2.2 设备固件
课程归档中的最终运行固件为:
固件/maixpy_v0.6.2_85_g23d09fbcc_minimum_with_ide_support.bin
文件名中的 minimum_with_ide_support 表示它是支持 MaixPy IDE 的精简运行固件。它提供 MaixPy/MicroPython 运行环境,但不包含本项目的 3 个人脸模型,也不等于项目脚本;模型和脚本还需要按后续步骤分别部署。
这套固件版本与课程脚本、旧版 .smodel 模型和 MaixPy IDE 0.2.5 配套。不要仅因官网出现更新版本就单独替换其中一个组件;固件、模型格式、脚本 API 和 IDE 版本不匹配时,可能出现 KPU 加载失败或 IDE 无法连接。
1.2.3 人脸识别模型固件
课程文档给出的模型页面是 MaixHub 模型库。登录后选择课程使用的人脸识别模型,下载时输入自己开发板的机器码,等待平台生成并下载压缩包。网站界面和模型名称可能调整,应以课程配套说明和当前页面提示为准。
解压后的包共有 4 个文件,而不是“只有 3 个文件”:
| 文件 | 类型与作用 |
|---|---|
FaceDetection.smodel | 人脸检测模型,定位画面中的人脸区域 |
FaceLandmarkDetection.smodel | 人脸五点关键点模型,定位双眼、鼻尖和嘴角 |
FeatureExtraction.smodel | 人脸特征提取模型,把对齐后的人脸转换为特征向量 |
main.py | 官方示例脚本,不是模型文件 |
3 个 .smodel 文件与申请时填写的机器码绑定。课程归档中的 王峰的设备识别模型 你们不能用FaceRecognization.zip 只用于查看文件组成,不能直接作为其他 K210 的可用模型。
1.2.4 K210 固件烧写
最终运行环境需要一次写入 1 个 MaixPy 固件和 3 个模型。先关闭 MaixPy IDE 的串口连接和所有串口终端,再打开 kflash_gui。
视频建议在正式写入前执行一次“擦除 → 整片擦除”。该操作会删除整颗 Flash 中的旧固件、模型、boot.py 和其他文件,属于有损操作;只应在确认目标开发板、已备份需要保留的脚本和数据后执行。它有助于排除旧文件系统或旧地址内容造成的冲突,但不是每次更新脚本都必须整片擦除。
整片擦除完成后,按照下表添加文件和地址:
| 顺序 | 文件 | Flash 地址 | 本课程中的作用 |
|---|---|---|---|
| 1 | maixpy_v0.6.2_85_g23d09fbcc_minimum_with_ide_support.bin | 0x000000 | MaixPy 运行固件 |
| 2 | FaceDetection.smodel | 0x100000 | 人脸检测 |
| 3 | FaceLandmarkDetection.smodel | 0x200000 | 五点关键点检测 |
| 4 | FeatureExtraction.smodel | 0x300000 | 人脸特征提取 |
0x100000、0x200000、0x300000 分别是 1 MiB、2 MiB、3 MiB 的偏移地址,相邻起始地址间隔 1 MiB。地址不是随便排序用的标签,而是模型在 Flash 中的真实位置;face.py 中的 kpu.load() 必须使用完全相同的地址。文件顺序本身不如“文件与地址的对应关系”重要,但按表中顺序添加最不容易配错。
确认烧录位置为 Flash、COM 口正确且 4 个地址无误后再下载。下载期间不要拔线、复位或断电;等待工具报告成功后再关闭。课程固件启动后出现红色背景和清晰状态文字,可作为这套资料下的初步启动迹象,但它不能单独证明 3 个模型地址和 face.py 的全部功能都正确,仍需在 IDE 中实际运行脚本验证。
1.2.5 打开人脸识别脚本
- 关闭
kflash_gui,确认其已释放 COM 口,再打开 MaixPy IDE。 - 选择“文件 → 打开文件”,打开课程归档
K210固件代码/face.py。刚启动 IDE 时编辑区可能是空白,这是正常现象。 - 单击左下角的连接按钮,选择开发板实际对应的 COM 口并确认;若连接失败,先检查串口占用、数据线、板型和是否确实烧入带
ide_support的固件。 - 连接后,摄像头预览区仍可能保持空白,直到脚本开始运行。空白预览不等于摄像头损坏。
1.2.6 运行人脸识别脚本
单击运行三角按钮后,MaixPy IDE 会把当前脚本发送给开发板并立即执行,摄像头采集、KPU 推理和 LCD/IDE 画面随之开始工作。这个动作是临时执行脚本,不是重新烧录 K210 固件,也不会自动把 face.py 永久保存为开机程序。
若临时运行正常,再选择“工具 → 将打开的脚本保存到开发板的 boot.py”,按提示确认。boot.py 位于开发板内部文件系统中,MaixPy 会在下次上电时自动执行它。保存后应断开 IDE、重新上电,并检查开发板在不依赖电脑点击运行按钮的情况下能否独立启动。
再次执行整片擦除会连同 boot.py 一起删除,因此重刷完整固件和模型后,需要重新保存项目脚本。调试时若只在 IDE 中点击运行而没有保存 boot.py,断电重启后脚本不会自动恢复运行。
1.3 人脸识别脚本功能介绍
face.py 是 MaixPy/MicroPython 脚本,主要完成摄像头采集、人脸检测、关键点定位、特征提取与比较,并通过 UART2 和 STM32 交换命令。原稿把它写成“C 语言脚本”是错误的。
UART2 引脚映射
K210 的 FPIOA 允许把芯片内部外设功能映射到可选的外部 IO。fm.register(pin, function) 的第一个参数表示外部 IO,第二个参数表示要映射的内部功能。课程源码意图把 IO9/IO10 用作 UART2:
| K210 | 方向 | STM32F103ZE | 说明 |
|---|---|---|---|
| IO9 / UART2_TX | K210 → STM32 | PA3 / USART2_RX | 发送识别结果和操作结果 |
| IO10 / UART2_RX | STM32 → K210 | PA2 / USART2_TX | 接收录入、删除命令 |
| GND | 双方参考地 | GND | 必须直接共地 |
TX 必须接对方 RX,RX 必须接对方 TX。两端均使用 3.3 V 逻辑电平,不能把 5 V 信号直接接到 IO9、IO10、PA2 或 PA3。课程源码在 fm.register() 的第一个参数位置使用 GPIO.GPIOHS9 和 GPIO.GPIOHS10;在该版本中它们的数值对应 9 和 10,应理解为外部 IO9/IO10,而不是把“GPIOHS 通道”与“外部焊盘”混为一谈。
模型加载地址
task_fd = kpu.load(0x100000):从 1 MiB 偏移加载人脸检测模型;task_ld = kpu.load(0x200000):从 2 MiB 偏移加载人脸关键点模型;task_fe = kpu.load(0x300000):从 3 MiB 偏移加载特征提取模型。
源码中 3 条 /sd/*.smodel 语句被注释,表示课程方案不从 SD 卡读取模型,而是从预先烧入的 Flash 地址读取。这里应理解为“课程方案未使用 SD 卡”,不能仅凭视频口述断定所有 Maix Bit 硬件都没有 SD 卡接口。
项目串口协议
UART2 参数为 115200、8 位数据位、无校验、1 位停止位(8N1)。课程脚本和项目功能说明定义了以下 4 字节帧:
| 方向 | 帧内容 | 含义 |
|---|---|---|
| K210 → STM32 | AF 05 00 FA | 人脸录入成功 |
| K210 → STM32 | AF 02 编号 FA | 人脸识别成功,第三字节是人脸编号 |
| K210 → STM32 | AF 01 00 FA | 人脸删除成功 |
| STM32 → K210 | A1 02 00 1A | 开始录入人脸 |
| STM32 → K210 | A1 01 02 1A | 删除全部已录入人脸 |
课程源码的接收逻辑调用 uart_A.read(5),但协议表和实际判断只定义、检查前 4 个字节;而且随后直接访问 temp[0]~temp[3],没有先验证长度。由于串口设置了 1000 ms 超时,4 字节数据可能在超时后返回并被处理,但这种写法可能引入等待,并在短帧时产生索引错误。本节应保持课程源码原样,不在文首擅自修改;调试时若命令响应慢或脚本异常,应把接收长度与帧长不一致列入排查范围。
人脸特征保存在运行内存中的 record_ftrs 列表,没有写入 Flash。即使 face.py 已保存为 boot.py,开发板复位或断电后,之前录入的人脸特征仍会丢失;“脚本固化”和“人脸数据持久化”是两回事。
1.4 项目功能介绍
从 MaixHub 下载包中的 main.py 是通用示例,课程的 face.py 在此基础上针对门禁项目进行了修改:
| 项目 | 下载包中的示例 main.py | 课程项目 face.py |
|---|---|---|
| 模型来源 | 有效代码从 /sd/ 加载 3 个模型 | 从 Flash 的 0x100000/0x200000/0x300000 加载 |
| 人脸录入触发 | 使用板载 BOOT 按键中断 | 接收 STM32 的 A1 02 00 1A 命令 |
| 与 STM32 通信 | 没有项目 UART2 协议 | 增加 IO9/IO10、115200 8N1 和收发帧 |
| 相似度阈值 | 85 | 70 |
| 结果反馈 | 主要在画面显示 | 除画面显示外,还向 STM32 回传录入、识别和删除结果 |
示例 main.py 中被注释的 Flash 方案使用 0x300000/0x400000/0x500000,而课程最终 face.py 使用 0x100000/0x200000/0x300000。原稿所谓“编译大小约 3~5 兆”是对画面的误解,这些十六进制数是 Flash 加载地址,不是编译后文件大小。采用哪一套地址都必须让烧录表与脚本完全一致,本项目只能按课程最终脚本的 1/2/3 MiB 布局操作。
常见问题可按下表排查:
| 现象 | 重点检查 |
|---|---|
| Windows 没有新增 COM 口 | Type-C 线是否支持数据、USB 驱动、USB 接口和设备管理器 |
kflash_gui 找不到或打不开串口 | MaixPy IDE/终端是否占用端口、COM 口是否选错、是否需要重新插拔 |
| 高速下载失败 | 选择准确开发板型号,降低下载波特率或切换低速模式 |
| 烧录后 IDE 无法连接 | 是否烧入带 minimum_with_ide_support 的固件、COM 口和板型是否正确 |
| 脚本提示模型加载失败 | 3 个模型是否属于本机、文件与 0x100000/0x200000/0x300000 是否一一对应 |
| 点击运行有画面,重启后不运行 | 当前脚本只被临时执行,尚未保存为开发板上的 boot.py |
| 整片擦除后脚本消失 | 整片擦除已删除内部文件系统,需要重新保存 boot.py |
| STM32 收不到 K210 数据 | IO9→PA3、IO10←PA2、GND 共地、115200 8N1 和协议帧 |
至此,K210 侧的固件、模型和项目脚本已经部署完成。下一节编写的是 STM32 端业务代码;本节不提前补写尚未在视频中实现的 STM32 程序。