这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【ESP-IDF系列】【ESP32】使用ESP-IDF驱动INMP441和MAX

共1条 1/1 1 跳转至

【ESP-IDF系列】【ESP32】使用ESP-IDF驱动INMP441和MAX98357结合I2S协议实现音频采集和播放

助工
2025-02-17 01:43:59     打赏

简介

本文将会介绍如何使用ESP32-S3使用I2S音频协议读取麦克风INMP441并且通过MAX98357模块将麦克风读取到的数据进行播放。在这篇文章中你将会学习到如何使用ESP-IDF的旧版API driver/i2s.h 库来实现上述功能。(新版本库的老版本的库功能上实际上没有什么不同,新版本的库只不过是将driver/i2s.h库按照了其中不同格式的I2S进行了拆分)


模块简介

1-ESP32S3开发板 


这块开发板已经被我开源到了立创开源广场,开源链接为:https://oshwhub.com/chongwang/christmas-tree-lights。 模块采用的是ESP32-S3-N4, 上图为旧版本的照片。 功能已经经过测试,目前的开源链接全部功能无误。 之后的系列教程中如果没有其他的需求等,会继续使用这个开发板进行测试。实际上使用其他版本的ESP32-S3模组也是可以的(个人没有经过测试)。在乐鑫官方的https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_cn.pdf数据手册中我们可以找到这块开发板的详细说明和介绍。但是由于我们这次使用的是它的I2S功能因此我们仅仅关注其I2S部分。

image.png

2-INMP441

INMP441 是一款高性能、低功耗的数字 MEMS 麦克风,采用 PDM 接口输出数字音频信号,信噪比高达 61 dB,频率响应范围为 60 Hz 至 15 kHz,能够提供清晰的音频捕捉。其工作电流低至 650 µA,封装尺寸仅为 3.76 mm x 4.72 mm x 1.0 mm,非常适合智能手机、平板电脑、耳机等对功耗和空间要求严格的消费电子设备。

2ab241ed57509ca97cdaf8d509b0d32.jpg

如果我们购买的成品模块如上图所示的话,那么它一共具备6个外部引脚。他们分别为


L/R : 左右声道切换,悬空或者接GND则为左声道, 在左声道的模式下其I2S数据的右声道数据都为0, 如果为右声道的话则左声道数据全为0

WS:WS引脚为Word select,在I2S通讯中负责区分左右声道和数据帧的开始

SCK:时钟信号

SD:I2S输出信号

VDD:电源

GND:GND

其中L/R 可以进行悬空,其他的线为必选。


3-MAX98357模块

MAX98357是一款高品质、低功耗的立体声音频放大器芯片,由Maxim Integrated生产。 该芯片具有内置的数字音频接口(I2S),可与各种数字音频设备配合使用。 MAX98357能够提供高达3.2W的输出功率,并具有优秀的失真和噪声性能。 此外,该芯片还支持多种电源电压,包括3.3V、5V和+/-5V等。 (数据介绍来自互联网)

28f8c4cb63681b5f6537840e73e7abd.jpg

如果是在某宝进行购买的话成品将和上述非常相似,大概可以驱动4欧到8欧的喇叭进行音频播放。它一共具备七个引脚。分别是

LRC : 接WS 引脚,进行左右声道识别

BCLK:时钟信号,可以和INMP441的连接在一起。

DIN:为I2S数据输入信号,接ESP32的I2S数据输出引脚。

GAIN:为输出增益引脚。这里不涉及使用

SO:为关断输出引脚,这里不涉及使用

GND: 电源地

VIN:3v3 或 5v5


代码部分及其讲解说明

在我们正式开始写代码之前最好来查阅ESP-IDF的官方文档https://docs.espressif.com/projects/esp-idf/zh_CN/v5.4/esp32s3/api-reference/peripherals/i2s.html

image.png

上图介绍了ESP32-S3的通讯模式和标准模式下的不同方式的通信时序等。

image.png

接下来我们快速使用ESP-IDF来新建一个工程。

image.png

在上述的选择模板处选择使用I2S的模板进行新建,此处仅仅是为了让其自动包含I2S相关的库。得益于ESP32的IO交换矩阵,我们可以使用任意的引脚来初始化I2S相关的PIN。因此首先删除原本的代码, 在程序中定义需要使用的引脚信息和我们需要的采样率信息等等


#define I2S_WS_GPIO 6   // LRCLK
#define I2S_SCK_GPIO 7  // BCLK
#define I2S_SD_GPIO 4   // INMP441 的 DOUT (数据输入)
#define I2S_DOUT_GPIO 5 // MAX98357 的 DIN (数据输出)
#define I2S_SAMPLE_RATE 44100 // 采样率
#define I2S_BUFFER_SIZE 512   // 缓冲区大小

接下来我们需要初始化I2S信息, 由于我们想要实现的效果为从INMP441接收数据,然后再将数据发送到MAX98357因此I2S的模式需要配置为双向的数据,且作为主机还需要将其配置为master模式。同时由于INMP441的声道选择引脚悬空,则为左声道因此。还需要配置为左声道模式。

i2s_config_t i2s_config = {       
 .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX), // 主模式,接收和发送        
 .sample_rate = I2S_SAMPLE_RATE,                                    // 采样率       
 .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,                      // 32 位数据        
 .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,                       // 单声道(左声道)        
 .communication_format = I2S_COMM_FORMAT_STAND_I2S,                 // 标准 I2S 格式        
 .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,                          // 中断优先级        
 .dma_buf_count = 8,                                                // DMA 缓冲区数量        
 .dma_buf_len = I2S_BUFFER_SIZE,                                    // DMA 缓冲区长度        
 .use_apll = false                                                  // 不使用 APLL    
 };

 i2s_pin_config_t pin_config = {        
    .bck_io_num = I2S_SCK_GPIO,    // 位时钟        
    .ws_io_num = I2S_WS_GPIO,      // 左右声道时钟        
    .data_out_num = I2S_DOUT_GPIO, // 数据输出(连接到 MAX98357 的 DIN)        
    .data_in_num = I2S_SD_GPIO     // 数据输入(连接到 INMP441 的 DOUT)    
 };


之后便是初始化I2S驱动

    // 初始化 I2S    
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);    
    i2s_set_pin(I2S_NUM_0, &pin_config);

对于数据的读取和写入我们则可以调用I2s_read() 来读取来自INMP441的数据。它一共接收五个数据, 分别是I2S端口(第几个I2S)、读取数据的缓冲区, 缓冲区的大小, 读取的数据大小和读取数据的延时。其I2s_wirte()方法也是相似只不过read方法是从INMP441读取数据到缓冲区,而wirte方法在当前的程序代码中是将数据从缓冲区进行读取然后写入到I2S总线上到MAX98357.

int32_t sample = 0;
size_t bytes_read = 0;
size_t bytes_written = 0;

定义上述全局变量用于数据的保存和写入。

  while (1)    {
          // 从 INMP441 读取音频数据        
          i2s_read(I2S_NUM_0, &sample, sizeof(sample), &bytes_read, portMAX_DELAY);
        // 将音频数据发送到 MAX98357        
        if (bytes_read > 0)        
        {            
           i2s_write(I2S_NUM_0, &sample, sizeof(sample), &bytes_written, portMAX_DELAY);        
        }    
 }

之后便可以完成上述所有的功能, 读取INMP441的数据到MAX98357.


完整接线图如下(并没有参考意义,因为得益于IO交换矩阵, 可以使用任意的PIN来初始化I2S)

0e0eefdef76079329803d2c726380dd.jpg

完整项目工程如下

Inmp441-esp32s3.zip

视频链接如下

https://www.bilibili.com/video/BV1tRwUe7Eo9/






关键词: ESP-IDF系列     ESP32     INMP441     M    

共1条 1/1 1 跳转至

回复

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