2. 使用ESP32的I2S接口采集麦克风音频

任务目标

配置ESP32的I2S外设,从INMP441数字麦克风采集音频数据,将原始采样值通过串口打印输出,验证I2S通信与数据读取链路正常。

硬件与接线

  • ESP32开发板(如ESP32-DevKitC)
  • INMP441数字麦克风模块
INMP441引脚ESP32引脚
SCK(位时钟)GPIO 26
WS(字选择)GPIO 25
SD(数据输出)GPIO 22
L/R(声道选择)GND(左声道)
VDD3.3V
GNDGND

实现代码

使用ESP-IDF的I2S驱动接口,配置为标准模式(Philips格式),从麦克风读取32位采样数据(24位有效数据左对齐),取高16位作为有效采样值打印。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "esp_log.h"

#define I2S_PORT         I2S_NUM_0
#define I2S_SCK          26
#define I2S_WS           25
#define I2S_SD           22
#define DMA_BUF_COUNT    8
#define DMA_BUF_LEN      1024

static const char *TAG = "I2S_MIC";

void i2s_init(void) {
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX,
        .sample_rate = 16000,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = DMA_BUF_COUNT,
        .dma_buf_len = DMA_BUF_LEN,
        .use_apll = false,
        .tx_desc_auto_clear = false
    };

    i2s_pin_config_t pin_config = {
        .bck_io_num = I2S_SCK,
        .ws_io_num = I2S_WS,
        .data_out_num = I2S_PIN_NO_CHANGE,
        .data_in_num = I2S_SD
    };

    i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_PORT, &pin_config);
}

void mic_read_task(void *arg) {
    int32_t sample = 0;
    size_t bytes_read = 0;

    while (1) {
        esp_err_t err = i2s_read(I2S_PORT, &sample, sizeof(sample), &bytes_read, portMAX_DELAY);
        if (err == ESP_OK && bytes_read == sizeof(sample)) {
            int16_t audio_val = (int16_t)(sample >> 14);  // 取高16位有效数据
            printf("%d\n", audio_val);
        } else {
            ESP_LOGE(TAG, "I2S read failed: %s", esp_err_to_name(err));
        }
        vTaskDelay(pdMS_TO_TICKS(10));  // 约100采样点/秒打印
    }
}

void app_main(void) {
    i2s_init();
    ESP_LOGI(TAG, "I2S initialized, reading from INMP441...");
    xTaskCreate(mic_read_task, "mic_read", 4096, NULL, 5, NULL);
}

编译与烧录

idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor

验证方法

  • 串口监视器持续输出数值,静音时数值在0附近小幅波动(±200以内)。
  • 对着麦克风说话或吹气,数值幅度明显增大(超过±1000),说明I2S数据采集有效。
  • 若输出恒为0或极大值,检查L/R引脚是否接GND、SCK/WS/SD接线是否正确。

通过标准:串口能持续打印随声音变化的采样值,静音与发声时数值范围有显著差异。