这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » STM32H747I-DISCO开发指南【语音识别智能控制助手】

共3条 1/1 1 跳转至

STM32H747I-DISCO开发指南【语音识别智能控制助手】

菜鸟
2025-11-30 23:49:10     打赏

一、硬件介绍

1、产品特点

STM32H747I-DISCO开发板基于Arm的STM32H747XIH6微控制器拥有Cortex-M7内核(带双精度浮点单元,运行频率高达 480 MHz) 和 Cortex-M4内核(带单精度浮点单元,运行频率高达 240 MHz)的双核性能,板载配备2MB的Flash存储器和1MB的RAM、4英寸TFT LCD触摸显示屏(480x800) 具有MIPI DSI接口等;

image-20251109210717816

image-20251109210717816.png


规格参数

image.png

24 MHz 晶振(X1),用于USB OTG HS PHY 和摄像头模块;

25 MHz 晶振(X2),用于主时钟发生器和以太网 PHY;

32.768 kHz 晶体(X3),用于RTC;

25 MHz 晶振(X4),仅用于STLINK-V3E;


硬件框图

image-20251110230635570.png


image-20251110230635570



2、功能引脚示意图 / 原理图

主要原理图

image-20251109215821403.png


二、功能硬件

1、数字MEMS麦克风

硬件介绍

STM32H747I-DISCO板上的U21(MP34DT05-A) 是一款MEMS数字全向麦克风,默认通过PDM(脉冲密度调制)输出;

麦克风(配置对应焊桥)也可以连接到U12(WM8994ECS/R,音频编解码器),音频编解码器为麦克风提供PDM时钟;


特性

单电源电压;

低功耗;

AOP:122.5 dBSPL;

64db 信噪比;

全向性灵敏度:-26 dBFS ±3 dB 的灵敏度;

PDM 输出;


SAI 接口

SAI 接口是一种串行音频接口,具有灵活性高、配置多样等特点,可支持多种音频协议;

SAI 接口可配置为支持 I2S 标准、LSB 或 MSB 对齐、PCM/DSP、TDM 和 AC’97 等协议,将音频模块配置为发送器时,SAI 接口可提供 SPDIF 输出;SAI通过两个完全独立的音频子模块来实现这种灵活性和可配置性, 每个模块都有自己的时钟发生器和 I/O 线控制器等;

MP34DT05-A 输出 1-bit PDM流,时钟频率通常为 1.024 MHz ~ 3.072 MHz; DFSDM 内部数字滤波器进行抽取,输出多比特 PCM;


抽取因子和相应频率

image-20251127232012680

image-20251127232012680.png



硬件引脚连接

CLK → 连接到 STM32 的 PE2 (SAI4_CK1);

DOUT → 连接到 STM32 的 PC1 (SAI4_D1);

image-20251123204608304

image-20251123204608304.png



原理图

image-20251118170116678.png


image-20251118170116678


2、LCD屏幕

硬件介绍

4 英寸 TFT-LCD 的分辨率为 480x800 像素,可显示高达 16.7M 种颜色,LCD 与微控制器之间的接口是一个 2-Lane MIPI 信号,带 MIPI DSI 接口;

image-20251125112458684.png

image-20251125112458684

特性

4 英寸 TFT 彩色 LCD

480(RGB)x800 像素

16.7M 色彩显示

最多两路 MIPI/DSI 数据

电容触摸屏支持单点触摸和手势,或双点触摸

LCD 和触摸屏共用 2.8V-3.3V 电源,背光使用 5V 电源


原理图

image-20251109215321547.png


image-20251109215321547


image-20251125155244693


三、功能实现

通过使用 Edge Impulse 进行语音关键词识别模型训练;

将训练好的模型部署到开发板上,当板载麦克风检测到预设的关键词时,开发板会进行相应的动作(控制相关外设);


1、模型训练

打开 Edge Impulse ,上传相关的语音数据,进行关键词训练;

image-20251130204828022.png




主要关键词如下:

Hello  STM32

打开绿灯、打开橙灯、打开红灯

打开蓝灯、打开所有灯、关闭所有灯


最后,模型训练结果 准确率为 96.7%;

image-20251130204434550

image-20251130204434550.png

image-20251130204556444.png


image-20251130204556444


导出训练好的模型

Quantized (int8) / Unoptimized (float32) :所需资源以及运行效果如下;

image-20251130215231946.png


image-20251130215231946

部署训练好的模型

然后点击下方的 build,进行构建 / 下载;

将导出的 xxx.pack(Arm Keil MDK CMSIS-Pack)导入到 keil 中;


2、创建工程

1、工程配置

打开 keil ,选择之前创建好的项目,在此基础上进行相关的开发;


2、pack库配置

1、导入训练好的 xxx.pack / 相关依赖 EI-SDK.pack ;

image-20251130215435463.png



image-20251130215435463

2、开启相关依赖 pack;

image-20251130215622343

image-20251130215622343.png


image-20251130220038006


将相关的 输入原始特征 复制 到静态缓冲区 float features[] 中;

image-20251130225008949.png



image-20251130225008949

三、代码编写

效果:通过板载麦克风识别到的不同语音关键词,LCD屏幕和板载LED灯将执行相应的动作;

主要相关代码:

mian.c:

#include "main.h"



int main(void)
{

  MPU_Config();
  CPU_CACHE_Enable();
  HAL_Init();

  SystemClock_Config();

  //初始化板载LED  
  BSP_LED_Init(LED1);
  BSP_LED_Init(LED2);
  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);


  // 初始化LCD
  BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
  UTIL_LCD_SetFuncDriver(&LCD_Driver);


  AudioRecord(); // 语音识别

 
  while (1)
  {
    HAL_Delay(500);
  }
}



AudioRecord.c:

#include "main.h"
#include "ei_run_classifier.h"
#include "ei_classifier_porting.h"

static const float features[] = {
    -13, -25, -30, -15, 25, 15, -51, -85, -68, 1, 69, 79, 31, 20....,
};


static const Led_TypeDef ledOrder[4] = {LED1, LED2, LED3, LED4};

#define EI_WIN_SIZE (EI_CLASSIFIER_RAW_SAMPLE_COUNT)

static int16_t s_ei_ring[EI_WIN_SIZE * 2]; 
static volatile size_t s_ei_ring_count = 0;
static volatile size_t s_ei_ring_head = 0; 


static inline void EI_PushPCM(const int16_t *src, size_t n)
{
  for (size_t i = 0; i < n; ++i)
  {
    s_ei_ring[s_ei_ring_head] = src[i];
    s_ei_ring_head = (s_ei_ring_head + 1) % (EI_WIN_SIZE * 2);
    if (s_ei_ring_count < EI_WIN_SIZE * 2)
      s_ei_ring_count++;
  }

  static size_t EI_CopyWindowToFloat(float *out)
  {
    if (s_ei_ring_count < EI_WIN_SIZE)
      return 0;
    size_t start = (s_ei_ring_head + (EI_WIN_SIZE * 2) - EI_WIN_SIZE) % (EI_WIN_SIZE * 2);
    for (size_t i = 0; i < EI_WIN_SIZE; ++i)
    {
      int16_t v = s_ei_ring[(start + i) % (EI_WIN_SIZE * 2)];
      out[i] = (float)v / 32768.0f;
    }
    return EI_WIN_SIZE;
  }

  static uint16_t s_circle_x[4];
  static uint16_t s_circle_y[4];
  static uint16_t s_circle_r = 30;
  static uint8_t s_prev_led_state[4] = {0xFF, 0xFF, 0xFF, 0xFF};

  static void StatusCircles_Init(void);
  static void StatusCircles_Refresh(void);


void AudioRecord(void)
{
  uint32_t channel_nbr = 2;
  uint32_t x_size, y_size;
  BSP_LCD_GetXSize(0, &x_size);
  BSP_LCD_GetYSize(0, &y_size);
  /* 清屏 */
  UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);
  StatusCircles_Init();
    
  AudioFreq_ptr = AudioFreq + 6;
  AudioOutInit.Device = AUDIO_OUT_DEVICE_AUTO;
  AudioOutInit.ChannelsNbr = channel_nbr;
  AudioOutInit.SampleRate = *AudioFreq_ptr;
  AudioOutInit.BitsPerSample = AUDIO_RESOLUTION_16B;
  AudioOutInit.Volume = VolumeLevel;

  AudioInInit.Device = AUDIO_IN_DEVICE_DIGITAL_MIC;
  AudioInInit.ChannelsNbr = channel_nbr;
  AudioInInit.SampleRate = *AudioFreq_ptr;
  AudioInInit.BitsPerSample = AUDIO_RESOLUTION_16B;
  AudioInInit.Volume = VolumeLevel;

  BSP_AUDIO_IN_Init(1, &AudioInInit);
  BSP_AUDIO_IN_GetState(1, &InState);
  BSP_AUDIO_IN_RecordPDM(1, (uint8_t *)&recordPDMBuf, 2 * AUDIO_IN_PDM_BUFFER_SIZE);

  // 推理
  static float ei_window[EI_WIN_SIZE];

    
  while (1)
  {
    if (EI_CopyWindowToFloat(ei_window) == EI_WIN_SIZE)
    {
      signal_t signal;
      if (numpy::signal_from_buffer(ei_window, EI_WIN_SIZE, &signal) == 0)
      {
        if (run_classifier(&signal, &features, false) == EI_IMPULSE_OK)
        {
          size_t top_i = 0;
          float top_s = 0.0f;
          for (size_t i = 0; i < features.classification_count; ++i)
          {
            if (features.classification[i].value > top_s)
            {
              top_s = features.classification[i].value;
              top_i = i;
            }
          }

          LED_Off(LED1);
          LED_Off(LED2);
          LED_Off(LED3);
          LED_Off(LED4);
          if (top_s >= 0.70f)
          {
            LED_On(ledOrder[top_i % 4]);
          }
          StatusCircles_Refresh();
        }
      }
    }
    HAL_Delay(5);
  }
}



四、程序烧录

1、连接USB数据线至开发板的STLINK-V3E接口;

2、分别选择 CM4 / CM7 程序,点击 Download 分别烧录程序到开发板上;



五、效果演示


























关键词: STM32H747I-DISCO    

高工
2025-12-01 07:39:42     打赏
2楼

声音收集要收集多少条呀?


高工
2025-12-01 09:18:53     打赏
3楼

语料要符合什么样的标准?录制环境的混响要求怎么样?噪声水平怎么样?还有录制灵敏度需要如何设置?

另外,怎么判断录制好的语料是自己想要的?


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]