# stm32-mnist **Repository Path**: tinytaro/stm32-mnist ## Basic Information - **Project Name**: stm32-mnist - **Description**: 基于STM32的手写数字识别 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: bare-ops - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-17 - **Last Updated**: 2026-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # STM32 触屏手写数字识别 在 STM32F407IGH6 + 4.3 寸触摸屏上跑通"手写 → int8 推理 → 屏显识别结果"的完整嵌入式 AI 实验工程。 ![演示动画](tutorial/demo.gif) > **算子全部手写**:conv/pool/FC/requantize 全部手写(约 300 行纯 C,与导出脚本 numpy 镜像逐位一致),softmax 用 M4F 硬件 FPU 浮点实现,不依赖任何第三方 NN 库。 - **PC 训练**:PyTorch LiteCNN(3 epoch),MNIST 测试集准确率 **0.9763**(纯 CPU 几分钟) - **板端推理**:全 int8 手写算子,量化自校验与 PyTorch float **top-1 agreement = 1.000** - **真机实测**:规范书写识别正确、置信度 98%、单次推理 **19ms**(pre 6ms + cnn 13ms) - 固件体积:FLASH ~38KB,无需外部存储 | 编译 | cnn | total | FLASH | |---|---|---|---| | 全工程 -O0(Debug) | 129ms | 150ms | 45928B | | 全工程 -Os(Release) | 67ms | 72ms | 34584B | | cnn_model.c 单独 -O3(当前配置) | **13ms** | **19ms** | 38400B | ⚠ cnn_model.c 单独用 **-O3** 编译(CMake 已配好 `set_source_files_properties`)——低优化级别不展开 int8 内积循环,cnn 会从 13ms 恶化到 67~129ms,详见指导书 §8.5。 详细实验步骤与全部真机调试结论见 **[tutorial/实验指导书.md](tutorial/实验指导书.md)**(约 2000 行,从 CubeMX 工程生成一路到验收)。 ## 硬件平台 | 部件 | 说明 | |---|---| | 主控 | STM32F407IGH6 @168MHz(HSE 8M,PLLM=4/N=168/P=2) | | 显示 | 4.3" 800×480 TFT,控制器 **NT35510**,FSMC NE4 @0x6C000000,16 位 8080 时序 | | 触摸 | **GT911** 电容屏,I2C1 @0x5D(PB6/PB7),INT=PI2(内部下拉) | | 蜂鸣器 | 无源,PB9 = TIM4_CH4 PWM 2kHz 方波驱动 | | 按键 | KEY1=PH2(识别)、KEY2=PH3(清屏),低有效外部上拉 | | 调试串口 | USART6 → CH340E → USB-C,115200-8-N-1 | | 背光 | 底板 12V 恒流恒亮(模组无调光引脚) | 引脚级细节见 [hardware/硬件分析.md](hardware/硬件分析.md);核心板/底板原理图 PDF 也在 `hardware/` 下(屏与触控芯片的原厂 datasheet 不随仓库分发,见文末 License 说明)。 ## 目录结构 ``` ├── Core/ 固件(CubeMX 生成 + 手写驱动) │ ├── Src/lcd.c NT35510 驱动(16 位命令编码、完整初始化序列、横屏 MADCTL=0xA0) │ ├── Src/touch.c GT911 驱动(16 位寄存器、坐标校准 SWAP_XY/INVERT_X) │ ├── Src/gui.c 手写板(影子画布 + 分离刷插值绘制) │ ├── Src/preprocess.c 笔迹预处理(包围盒→20px→质心居中→膨胀→int8) │ ├── Src/cnn_model.c 手写算子推理编排(conv→pool→conv→pool→FC→softmax) │ ├── Src/key.c 按键消抖扫描 │ └── Src/model_weights.c 量化权重(自动生成,勿手改) ├── pc/ PC 端训练 / 量化导出 / 自检脚本 │ ├── mnist_cnn_train.py 训练(best acc 0.9763) │ ├── export_header.py 量化导出 + numpy 逐位自校验(写入 ../Core) │ └── dbg_selftest.py 开机自检图案的 PC 端镜像对照 ├── tutorial/ 实验指导书(教材本体) └── hardware/ 核心板/底板原理图(PDF) / 引脚分析 ``` ## 快速开始 ### 1. 构建 & 烧写(需 STM32CubeCLT 工具链) ```powershell cmake --preset Release # 测耗时必须用 Release(-Os);Debug 是 -O0,实测 cnn=129ms、端到端 150ms cmake --build build/Release STM32_Programmer_CLI -c port=SWD -w build\Release\testsim.elf -rst ``` ### 2. 训练 & 导出权重(需 Python + PyTorch/torchvision) ```powershell cd pc python download_mnist.py # 网络好可跳过;数据集在 .gitignore 中,不入库 python mnist_cnn_train.py # → model_lite.pt python export_header.py # 自校验 agreement=1.000 后写入 ../Core/Inc/model.h + Src/model_weights.c ``` 重新构建烧写即可。 ### 3. 上板验证 1. 上电串口应打印开机自检:`selftest: digit=1 prob=[-128,127,...]`(固定竖条图案,量化链路健康的金标准) 2. 画板写数字(占板 2/3 以上、笔画稍粗)→ 按 KEY1 → 蜂鸣一声,屏显 DIGIT/CONF/TIME 3. KEY2 清屏;串口同步打印 input28 可视化(检查笔迹被预处理成什么样) ## 核心技术要点(全部真机验证) - **NT35510 16 位命令编码**:DCS 命令在高字节(`0x1100` 而非 `0x0011`),白屏问题的实测根因;横屏 `MADCTL=0xA0`,MV=1 后 0x2A/0x2B 覆盖范围对调 - **GT911 寄存器布局**:16 位地址高字节在前(`I2C_MEMADD_SIZE_16BIT`);点数据 `0x814F`=TrackID、`0x8150~53`=XY 小端;配置坐标系是竖屏 480×800 → `SWAP_XY=1 + INVERT_X=1` - **requantize 数学**:`requantize(v,m,shift) = rounding_div(pow2_rounding_mult(v<