当前位置:   article > 正文

STM32U575测评 使用这块开发板测试HC-SR04模块的串口通信功能,并尝试移植TinyMaix实现在单片机上的实时手写数字的识别。

stm32u575
  1. 简单介绍与体验请添加图片描述
    STM32U575ZIT6的主频有160Mhz,拥有17个定时器,4个I2C,6个UART,3个SPI以及其他一共22个通信用的外设。这块开发板上集成了ST-LINKv3,因此这个开发板使用起来非常方便,程序的下载速度体验也挺不错。

  2. 工程文件与开发环境的准备
    AltAlt
    在这里插入图片描述
    因为这款单片机由于没有标准库,于是最近一段时间接触了一下STM32CudeMX,然后使用HAL库来开发相应的程序。准备好Keil环境之后,再VScode里面下载Keil Assistant,就可以实现再VScode中编写代码,编译烧录进STM的单片机里了。先写个流水灯程序测试测试。

  3. HC_SR04的串口通信功能的测试
    AltAlt
    先用这个开发板来测试HC-SR04的串口通信,因为我之前在网上找相关的教程,都是关于如何使用GPIO测量高电平时间来测算距离的,看到这个模块上有UART,I2C,和One-Wire,就想找时间试试。于是利用这次评测这个开发板的机会来顺便测试测试这个功能。请添加图片描述
    请添加图片描述
    经过查找资料只要将这个模块红框内的10K电阻补上就能使用串口进行通信了。
    之后再CubeMX里面启动串口,设置好对应设置就行了,其中波特率要设置到9600。
    之后使用HAL_UART_Transmit发送0xA0,再用HAL_UART_Receive接收三个数据就能完成一次测量。
    请添加图片描述
    在Keil的Option中勾选上Use MicroLIB,之后在自动生成的uart.c里面添加一段

    int fputc(int ch, FILE* f)
    {
      if (HAL_UART_Transmit(&huart1, (uint8_t *)&ch, sizeof((uint8_t *)&ch), 1000) != HAL_OK)
      {
        return EOF;
      }
      return ch;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    来实现printf打印到串口
    请添加图片描述
    简单完善代码让单片机使用串口读取HC-SR04的数据,并把数据通过USART1发动到电脑。

  4. 使用这块开发板驱动老王家的一款128*128像素4位灰度的OLED屏幕为之后手写数字识别的显示做准备。

    因为老王提供的代码使用了U8G2的库,因为我不太了解,并想着学习学习显示模块的驱动的全流程,于是自己写了一套简陋但能满足我现在功能的驱动。先是用软件SPI驱动屏幕
    Alt
    经过测试,刷新速度也还不错,但考虑到后面要运行一个模型,我还是打算使用硬件SPI+DMA的方法驱动屏幕。因为这款单片机的DMA是GPDMA,所以配置页面和DMA的配置页面有些区别,但总体操作都是差不多的,配置成Circular Mode,选择Request的来源,设置好地址自增,之后就用HAL_SPI_Transmit_DMA来开启搬运就行了。经过测试这款屏幕的驱动芯片SSD1327无法支持40Mhz及以上的SPI,于是用的20Mhz的SPI,经过计算一秒内能刷新2441帧画面,远超这个屏幕一百多Hz的刷新率。

  5. 移植TinyMaix
    根据这个博主使用轻量级AI推理框架TinyMaix实现手写数字识别完成TinyMaix的移植,并将推理部分的Demo的程序进行简单封装,方便外部调用。

    
    void mnist_main_LoadModel(void);
    void mnist_main_ImgProcess(void);
    void mnist_main_UnloadModel(void);
    void mnist_main_GetResule(uint8_t *ID, float *Confidence);
    tm_mdl_t mdl;
    tm_mat_t in_uint8 = {3, 28, 28, 1, {(mtype_t *)mnist_pic}};
    tm_mat_t in = {3, 28, 28, 1, {NULL}};
    tm_mat_t outs[1];
    tm_err_t res;
    void mnist_main_LoadModel(void)
    {
        res = tm_load(&mdl, mdl_data, NULL, layer_cb, &in);
        if (res != TM_OK)
        {
            TM_PRINTF("tm model load err %d\r\n", res);
        }
    }
    
    void mnist_main_ImgProcess(void)
    {
        res = tm_preprocess(&mdl, TMPP_UINT2INT, &in_uint8, &in);
        res = tm_run(&mdl, &in, outs);
    //    parse_output(outs);
    }
    
    void mnist_main_GetResule(uint8_t *ID,float *Confidence)
    {
        float *data = outs[0].dataf;
        float maxp = 0;
        int maxi = -1;
        for (int i = 0; i < 10; i++)
        {
            if (data[i] > maxp)
            {
                maxi = i;
                maxp = data[i];
            }
        }
        *ID = maxi;
        *Confidence = maxp;
    }
    
    void mnist_main_UnloadModel(void)
    {
        tm_unload(&mdl);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    程序里面将mnist_pic作为tm_mat_t in_uint8 的数据部分,之后使用tm_preprocess把图片数据的uint转换成int,转化成tm_mat_t in 加载模型后直接将in 作为输入,进行计算,因此改变mnist_pic的原始数据就能改变进行计算的图片的内容。
    Alt测试将mnist_pic的内容映射成4位灰度显示到屏幕上。
    视频流打算使用电脑端处理视频内容,将原始视频转化成28*28的灰度在这里插入图片描述
    然后通过串口发送到单片机内,进行推理。为了让单片机能专注推理,接收图片也采用串口和DMA配合,直接将数据存进mnist_pic数组里面。

  6. 最终结果
    在这里插入图片描述
    这个帧率是用定时器计算的每秒钟主循环循环的次数,也就是说这款单片机每秒可用这个TinyMaix进行400次推理。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/683309
推荐阅读
相关标签
  

闽ICP备14008679号