你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【NUCLEO-C562RE】MNIST 数字识别

[复制链接]
无垠的广袤 发布时间:2026-10-30 21:16

【NUCLEO-C562RE】MNIST 数字识别

本文介绍了 NUCLEO-C562RE 开发板结合 TinyMatrix 机器学习库、MNIST 数据集以及 Arduino IDE 实现数字识别的板端部署,包括流程图、关键代码、网页面板设计、效果演示等。

项目介绍

开发板结合 TinyMatrix 库和 MNIST 数据集,实现手写数字识别,将结果串口打印的项目设计。

  • 准备工作:硬件连接、TinyMatrix 库、示例工程;
  • 工程测试:流程图、工程代码、效果演示、手写面板的网页设计;

cover_mnist.jpg

TinyMatrix

TinyMaix 是针对小算力小内存的芯片设计的轻量级推理框架。

使用 TinyMatrix 可将 MNIST 部署在 2KB 内存的单片机上运行,并对多种架构的单片机提供了支持和优化,包括 RISC-V、ARM Cortex-M 等。

关键特性

  • 核心代码少;
  • 低内存消耗;
  • 支持 INT8/FP32/FP16 模型,支持 tflite 模型转换;
  • 支持多种芯片架构的指令优化: ARM SIMD/NEON/MVEI,RV32P, RV64V;
  • 友好的用户接口,只需要 load/run 模型;
  • 支持全静态的内存配置 (无需malloc);
  • MaixHub 在线模型训练支持;

详见:sipeed/TinyMaix .

例程获取

下载 mnist_arduino 示例工程。

详见:TinyMaix/examples/mnist_arduino .

硬件连接

使用 TypeC-USB 数据线连接 NUCLEO-C562RE 开发板和主机 USB 接口;

connect_pwm_led.jpg

环境搭建

logo_arduino_ide.jpg

logo_stm32cubeprog.jpg

添加 URL

  • 打开 Arduino IDE ,菜单栏 File - Preference 首选项,设置;

arduino_add_url.jpg

  • 添加额外板卡管理链接并保存;
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
  • 回到 Arduino IDE 主界面,自动更新下载 STM32 板卡数据文件 package_stm_index.json;
  • 等待所有工具及 SDK 下载部署完成,展开侧边工具栏 Board Manager 标签,搜索并安装 STM32 MCU based board by STMicroeletronics 最新版;

arduino_board_install.jpg

详见:STM32duino .

流程图

flowchart_mnist.jpg

代码

Arduino IDE 打开 tinymatrix.ino 工程文件,代码如下

#include "stdio.h"
#include "tinymaix.h"
#include "num_test.h" // 存放目标数字图片数组

#define  TM_GET_US()       ((uint32_t)(micros()))

#define TM_DBGT_INIT()     uint32_t _start,_finish;uint32_t _time;_start=TM_GET_US();
#define TM_DBGT_START()    _start=TM_GET_US();
#define TM_DBGT(x)         {_finish=TM_GET_US();\
                            _time = (_finish-_start);\
                            Serial.print("===use ");Serial.print(_time);Serial.print("us\n");\
                            _start=TM_GET_US();}

#include <stdint.h>
#define MDL_BUF_LEN (960)
#define LBUF_LEN (360)
const uint8_t mdl_data[920] PROGMEM={\
// ... ...
};

// 28x28 = 784 bytes, 灰度 0~255
//const uint8_t mnist_pic0[28*28] PROGMEM = {};

tm_err_t layer_cb(tm_mdl_t* mdl, tml_head_t* lh)
{   //dump middle result
    return TM_OK;
    int h = lh->out_dims[1];
    int w = lh->out_dims[2];
    int ch= lh->out_dims[3];
    mtype_t* output = TML_GET_OUTPUT(mdl, lh);
    Serial.print("Layer ");Serial.print(mdl->layer_i);Serial.print(" callback ========\n");
    for(int y=0; y<h; y++){
       Serial.print("[");
        for(int x=0; x<w; x++){
            Serial.print("[");
            for(int c=0; c<ch; c++){
                Serial.print(output[(y*w+x)*ch+c]);Serial.print(",");
            }
            Serial.print("],");
        }
        Serial.print("],\n");
    }
    Serial.print("\n");
    return TM_OK;
}

static void parse_output(tm_mat_t* outs)
{
    tm_mat_t out = outs[0];
    float* data  = out.dataf;
    float maxp = 0;
    int maxi = -1;
    for(int i=0; i<10; i++){
        //TM_PRINTF("%d: %.3f\n", i, data[i]);
        Serial.print(i);Serial.print(": ");Serial.print(int(data[i]*100));Serial.print("\n");
        if(data[i] > maxp) {
            maxi = i;
            maxp = data[i];
        }
    }
    Serial.print("### Predict output is: Number ");Serial.print(maxi);Serial.print(", prob=");Serial.print(int(maxp*100));
    Serial.print("\n");
    return;
}


#define IMG_L   (28)
#define IMG_CH  (1)
#define CLASS_N (10)

static uint8_t mdl_buf[MDL_BUF_LEN];

void setup() {
    Serial.begin(115200);
    //printf_begin();
    TM_DBGT_INIT();
    Serial.print("mnist demo\n");
    tm_mdl_t mdl;
    const uint8_t *mnist_pic = mnist_pic5;
    for(int i=0; i<28*28; i++){
        Serial.print(pgm_read_byte(&mnist_pic[i])>>4, HEX);
        if(i%28==27)Serial.print("\n");
    }

    tm_mat_t in_uint8 = {3,IMG_L,IMG_L,IMG_CH, (mtype_t*)mnist_pic};
    tm_mat_t in = {3,IMG_L,IMG_L,IMG_CH, NULL};
    tm_mat_t outs[1];
    tm_err_t res;
    //tm_stat((tm_mdlbin_t*)mdl_data); 

    res = tm_load(&mdl, mdl_data, mdl_buf, layer_cb, &in);
    if(res != TM_OK) {
        TM_PRINTF("tm model load err %d\n", res);
        return ;
    }

    res = tm_preprocess(&mdl, TMPP_UINT2INT, &in_uint8, &in); 

    TM_DBGT_START();
    res = tm_run(&mdl, &in, outs);
    TM_DBGT("tm_run");
    if(res==TM_OK) parse_output(outs);  
    else TM_PRINTF("tm run error: %d\n", res);
    tm_unload(&mdl);                  
    return ;
}

void loop() {
  // put your main code here, to run repeatedly:

}

保存代码。

编译上传

参数配置

  • 菜单栏 Tool 选择目标开发板为 Nucleo-64;
  • 进一步在 Nucleo-64 开发板选择 C562RE 设备;
  • 调试方式选择 SWD;

arduino_mnist_config.jpg

编译上传

  • 点击工具栏 构建 按钮,编译工程,确认无报错;

arduino_mnist_build.jpg

  • 点击工具栏 上传 按钮,编译并上传固件至开发板;

arduino_mnist_upload.jpg

串口输出

工具栏右上角打开 Arduino IDE 自带的串口监视器,设置波特率 115200;

短按板载 RESET 键复位运行程序,串口打印 mnist demo 输出结果;

arduino_mnist_serial_print.jpg

或使用串口调试助手

mnist_print_num6.jpg

包括数组转换、耗时、0-9数字置信度、预测结果等信息。

网页面板设计

为了便于生成数组,设计网页手写面板,自动生成 28x28 数组,添加至 num_test.h 即可调用;

mnist_num_web_generate.jpg

详见:mnist_num_generate.html .

效果

在网页手写面板书写不同的数字,生成数组粘贴至 num_test.h 文件;

修改主程序中的 *mnist_pic 指针定义,编译上传,串口打印推理结果;

mnist_print_num4.jpg

尝试不同数字;

mnist_print_num5.jpg

识别结果准确,置信度高;

mnist_print_num8.jpg

总结

本文介绍了 NUCLEO-C562RE 开发板结合 TinyMatrix 机器学习库、MNIST 数据集以及 Arduino IDE 实现数字识别的板端部署,为相关产品在边缘 AI 领域的快速开发和应用设计提供了参考。

赞 收藏 评论0 发布时间:2026-10-30 21:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版