当前位置: 首页 > news >正文

【双MCU项目复盘与优化】03 - ESP32-S3驱动INMP441

摘要:本文复盘了 V3 智控面板中 ESP32-S3 驱动 INMP441 数字麦克风的硬件连接、I2S 外设配置与数据读取逻辑,并指出 V4 需要将驱动分层以提高复用性


1. V3 INMP441 驱动复盘

1.1 信号链路回顾

  • 声波信号需要经过如下处理,才能被ESP32-S3 所使用:
声波信号 → 麦克风 → 微弱电压信号 → 放大/滤波等预处理 → ADC采样 → 数字信号(I2S协议格式) → ESP32-S3
  • 而 INMP441 是一款高性能、低功耗、数字输出、全向型的MEMS麦克风,内置了一个MEMS传感器、信号调理、一个模数转换器、抗混叠滤波器、电源管理以及一个行业标准的 24 位 I2S 接口
  • INMP441 可以直接把上述过程的中间过程在内部完成,把处理好的数据信号按照标准的 I2S 模式发送给 MCU

1.2 ESP32-S3 的 I2S 外设

  • 硬件资源: 2 个 I2S 外设,通过配置这些外设,可以借助 I2S 驱动来输入和输出采样数据
  • 通信协议
    • 标准 I2S 协议
    • PDM 协议
  • 外设功能
    • 可用作系统主机或从机
    • 可用作发射器或接收器
    • DMA 控制器支持流数据采样,CPU 无需单独复制每个采样数据
  • 每个控制器都有独立的 RX 和 TX 通道,连接到不同 GPIO 管脚,能够在不同的时钟和声道配置下工作
  • 注意
    • 尽管在一个控制器上 TX 通道和 RX 通道的内部 MCLK 相互独立,但输出的 MCLK 信号只能连接到一个通道
    • 如果需要两个互相独立的 MCLK 输出,必须将其分配到不同的 I2S 控制器上

1.3 硬件连接与外设配置

  • 本项目使用 I2S0 外设驱动 INMP441 模块
  • 硬件连接如下:
INMP441 引脚 含义 ESP32-S3 接线
SD I2S 的 DOUT 信号输出 10
L/R 左右声道选择 GND,输出左声道
WS I2S 的 LRCLK 信号输入 21
SCK I2S 的 BCLK 信号输入 9
  • I2S0 外设配置如下
配置项 设定值 说明
采样率 16000Hz 满足语音应用的基本要求
数据位宽 32 bit INMP441 输出 24 bit 有效数据,但 I2S 帧固定为 32 bit
通道模式 MONO(单声道) 只用到一个麦克风
槽位掩码 I2S_STD_SLOT_LEFT 仅接收左声道数据
I2S 主/从 Master ESP32-S3 产生 BCLK 和 WS
DMA 帧数 512 每个 DMA 帧包含 512 个 32 bit 样本
DMA 描述符 6 DMA 链描述符数量,影响缓冲区管理
引脚配置 BCLK、WS、DIN 已指定,MCLK、DOUT 未使用 INMP441 不需要 MCLK,DOUT 是输出脚,本端只用 DIN 接收数据
  • 初始化代码如下:
#define _SAMPLE_RATE_HZ (16000)
#define _DMA_FRAME_NUM (512) // 每DMA帧32位样本数
#define _DMA_DESC_NUM (6)static i2s_chan_handle_t _rx_handle = NULL;bool bsp_i2s_init(void)
{    if (_rx_handle != NULL)
        return false;    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(HW_I2S_NUM_INMP441, I2S_ROLE_MASTER);
    chan_cfg.dma_desc_num = _DMA_DESC_NUM;
    chan_cfg.dma_frame_num = _DMA_FRAME_NUM;
    esp_err_t ret = i2s_new_channel(&chan_cfg, NULL, &_rx_handle);
    if (ret != ESP_OK)
    {
        _rx_handle = NULL;
        return false;
    }    i2s_std_clk_config_t clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(_SAMPLE_RATE_HZ);
    i2s_std_slot_config_t slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(
        I2S_DATA_BIT_WIDTH_32BIT, // 必须32位
        I2S_SLOT_MODE_MONO);    slot_cfg.slot_mask = I2S_STD_SLOT_LEFT; // L/R接地 ⇒ 有效数据在左声道    i2s_std_gpio_config_t gpio_cfg = {
        .mclk = I2S_GPIO_UNUSED,
        .bclk = HW_PIN_INMP441_BCLK,
        .ws = HW_PIN_INMP441_WS,
        .dout = I2S_GPIO_UNUSED,
        .din = HW_PIN_INMP441_SD,
        .invert_flags = {.mclk_inv = false, .bclk_inv = false, .ws_inv = false},
    };    i2s_std_config_t std_rx_cfg = {.clk_cfg = clk_cfg, .slot_cfg = slot_cfg, .gpio_cfg = gpio_cfg};    ret = i2s_channel_init_std_mode(_rx_handle, &std_rx_cfg);
    if (ret != ESP_OK)
    {
        i2s_del_channel(_rx_handle);
        _rx_handle = NULL;
        return false;
    }    ret = i2s_channel_enable(_rx_handle);
    if (ret != ESP_OK)
    {
        i2s_del_channel(_rx_handle);
        _rx_handle = NULL;
        return false;
    }
    return true;
}

1.4 数据读取

  • 数据手册中的时序图如下:
博客园图片
  • 同时参考例程代码,可知

    • INMP441 输出的 I2S 数据为 32 bit 帧,其中有效数据是 24 bit
    • 低 8 bit 为填充零或无效
  • 所以在读取的时候,需要先右移 8 个 bit,丢弃低 8bit 的无效位,同时可以再右移 6 位,相当于除以 64,将数据进行了压缩,适合常见音频处理库。最后的效果就是右移 14bit

  • 若需保留 24 bit 精度,可改为右移 8 位存入 int32_t 数组

  • 代码如下:

/***
* @brief 读取I2S多个uin32_t数据
* @param buf 缓冲区
* @param buf_len 缓冲区长度
* @param timeout_ms 读取超时
* @return  int32_t类型的样本数
*/
int bsp_i2s_read(int16_t *buf, size_t buf_len, uint32_t timeout_ms)
{
    if (_rx_handle == NULL || buf_len == 0 || timeout_ms == 0)
        return -1;    int32_t *temp = heap_caps_malloc(buf_len * sizeof(int32_t),
                                     MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);    if (temp == NULL)
        return -1;    size_t bytes_read = 0;
    esp_err_t ret = i2s_channel_read(_rx_handle, temp, buf_len * sizeof(int32_t), &bytes_read, timeout_ms);
    if (ret != ESP_OK)
    {
        free(temp);
        return -1;
    }    size_t samples = bytes_read / sizeof(int32_t);  // 样本数
    for (size_t i = 0; i < samples; i++)
    {
        buf[i] = (int16_t)(temp[i] >> 14); // 参考 VUMeterDemo 例程
    }    free(temp);
    return (int)samples;
}

2. V4 优化方向

  • V4 应该在原有的 bsp_i2s 的基础上分离出 inmp441 的驱动逻辑为 dri_inmp441 库,保留原有的 i2s 库运用逻辑为新的 bsp_i2s 库,供 drv_i2s 调用
  • 这样分层后,bsp_i2s 只负责 I2S 硬件配置与原始数据读写,dri_inmp441 处理 INMP441 特有的数据格式转换(如右移 14 位),便于未来更换麦克风型号或复用 I2S 驱动
http://www.rkmt.cn/news/1530986.html

相关文章:

  • 从零打造火星探测车:JPL开源火星车完整建造指南
  • 石家庄莫奈包包回收,这些细节决定你能卖多少 - 奢侈品回收测评
  • AI Agent是下一代AI变革!懂与不懂的差距正在快速拉大,普通人如何抓住机遇?从概念到源码,系统拆解AI Agent核心原理
  • 2026六安装修公司深度测评推荐|本土装企实测避坑干货分享 - 信息热点
  • 2026年哈尔滨免费咨询律所推荐:专业视角下的客观评测与选型指南 - 信息热点
  • 终极字体合并解决方案:5分钟解决魔兽世界字体乱码问题
  • 二手车上门验车第三方平台怎么选?异地验车哪家靠谱? - 信息热点
  • 2026年6月液位计仪表公司哪家靠谱,金属套温度计仪表/液位控制器仪表/磁性翻板液位仪表,液位计仪表厂家推荐 - 品牌推荐师
  • 2026武汉婚姻纠纷找谁?六大离婚律师专业推荐榜单 - 信息热点
  • 石家庄哪里回收名表?这份实测榜单请收好 - 奢侈品回收测评
  • 武汉高净值人群必看:2026离婚律师TOP8权威推荐,攻克股权分割、隐性财产追踪难关 - 信息热点
  • 步进电机失速检测:基于反电动势积分的PXD10 SSD模块实战指南
  • 重新定义卡通渲染:如何用lilToon着色器打造专业级角色视觉体验
  • QCMA终极指南:3步实现PS Vita跨平台内容管理
  • 深入解析FlexPWM模块:从输入捕获到故障保护的电机控制实战指南
  • 武汉离婚律师推荐排行榜:2026年婚姻家事领域TOP5权威榜单 - 信息热点
  • XBanner深度解析:从设计哲学到实现原理的Android轮播框架技术内幕
  • PyTorch-RL模型设计模式:CNN与MLP网络架构的最佳实践
  • 深入解析NXP PXS20微控制器ECSM模块:ECC内存保护与错误注入实战
  • 深入解析WCT1011B双ADC架构:从同步采样原理到寄存器配置实战
  • drawio-desktop:企业级跨平台图表解决方案的技术实现与部署指南
  • 终极指南:如何用BongoCat桌面互动猫咪让你的电脑操作变得有趣
  • 6月15号
  • 04_Kubernetes (K8s) 与 Docker 的区别
  • 深入解析FlexCAN内存映射与消息缓冲区:汽车CAN总线通信核心配置指南
  • 3步搞定大模型部署:为什么vLLM能让你10倍提升推理性能?
  • 终极Klipper配置教程:如何让你的3D打印机性能翻倍
  • TypeScript类型测试神器推荐:基于gh_mirrors/ut/utilities的完整实践教程
  • KS-Downloader:3分钟掌握快手无水印视频批量下载技巧
  • 椎角的概念以及和方位、俯仰的关系