INMP441

元器件
传感器
库存 600

介绍

INMP441 MEMS全向麦克风模块,I2S数字输出,支持64dB高信噪比,-26dBFS灵敏度,24位精度,低功耗1.4mA,适用于远场语音识别、智能音箱、AI语音助手等应用

规格参数

参数
功耗1.4mA (典型)
封装底部进音 LGA
信噪比64 dBA
灵敏度-26 dBFS (1kHz, 94dB SPL)
采样率8kHz~96kHz
工作电压1.8V~3.3V DC (典型3.3V)
模块尺寸16×12mm
通信接口I2S (Philips标准)
采样精度24-bit
频率响应60Hz~15kHz
声学过载点133 dB SPL

代码例程

INMP441 I2S 麦克风 — 代码例程 (ESP32 + STM32).md

# INMP441 I2S 麦克风 — 代码例程

## 一、ESP32 (Arduino Core) — 最简音频采集

ESP32 内置 I2S 外设,使用 Arduino 框架极其方便。

```cpp
// INMP441_ESP32_Record.ino
#include <driver/i2s.h>

// I2S 引脚定义
#define I2S_BCLK  14   // SCK
#define I2S_LRC   15   // WS
#define I2S_DIN   32   // SD

#define SAMPLE_RATE    16000   // 16kHz 语音识别常用
#define BUFFER_SIZE    512

int16_t i2sBuffer[BUFFER_SIZE];

void i2s_init() {
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,  // L/R接GND → 左通道
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 64,
        .use_apll = true,     // 使用APLL获得精准时钟
        .tx_desc_auto_clear = false,
        .fixed_mclk = 0
    };
    
    i2s_pin_config_t pin_config = {
        .bck_io_num = I2S_BCLK,
        .ws_io_num = I2S_LRC,
        .data_out_num = I2S_PIN_NO_CHANGE,
        .data_in_num = I2S_DIN
    };
    
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
    
    Serial.println("I2S 麦克风初始化完成!");
}

void setup() {
    Serial.begin(115200);
    i2s_init();
}

void loop() {
    size_t bytesRead;
    // 读取24bit数据到32bit缓冲区 — 使用32bit模式接收
    esp_err_t err = i2s_read(I2S_NUM_0, (char*)i2sBuffer, 
                              BUFFER_SIZE * sizeof(int16_t), &bytesRead, portMAX_DELAY);
    
    if (err == ESP_OK && bytesRead > 0) {
        int samplesRead = bytesRead / sizeof(int16_t);
        
        // 计算音量 RMS
        int64_t sum = 0;
        for (int i = 0; i < samplesRead; i++) {
            sum += (int64_t)i2sBuffer[i] * i2sBuffer[i];
        }
        float rms = sqrt(sum / (float)samplesRead);
        float db = 20 * log10(rms / 32768.0) + 94;  // 近似dB SPL
        
        Serial.printf("RMS: %.1f, 估算声压: %.1f dB\r\n", rms, db);
    }
    
    delay(100);
}
```

---

## 二、ESP32 — 双麦克风立体声

```cpp
// INMP441_Dual_ESP32.ino
#include <driver/i2s.h>

#define I2S_BCLK   14
#define I2S_LRC    15
#define I2S_DIN_L  32   // L/R → GND (左通道)
#define I2S_DIN_R  33   // L/R → VDD (右通道)

#define SAMPLE_RATE  44100
#define BUFFER_SIZE  1024

int32_t bufferL[BUFFER_SIZE];
int32_t bufferR[BUFFER_SIZE];

void dual_i2s_init() {
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,  // 双通道
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 128,
        .use_apll = true,
        .tx_desc_auto_clear = false,
        .fixed_mclk = 0
    };
    
    i2s_pin_config_t pin_config = {
        .bck_io_num = I2S_BCLK,
        .ws_io_num = I2S_LRC,
        .data_out_num = I2S_PIN_NO_CHANGE,
        .data_in_num = I2S_DIN_L   // 仅需一个DATA脚?不,第二个用 I2S_NUM_1
    };
    
    // ESP32 I2S0 和 I2S1 分别接两个麦克风
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
    
    Serial.println("双麦 I2S 初始化完成!");
}

void setup() {
    Serial.begin(115200);
    dual_i2s_init();
}

void loop() {
    size_t bytesRead;
    i2s_read(I2S_NUM_0, (char*)bufferL, BUFFER_SIZE * 4, &bytesRead, portMAX_DELAY);
    
    // 数据交替存放 L/R/L/R...
    int samplesRead = bytesRead / 8; // 每个样本 = L(4B) + R(4B)
    for (int i = 0; i < samplesRead; i++) {
        // 处理立体声数据...
    }
}
```

---

## 三、STM32 HAL — I2S DMA 音频采集

```c
// inmp441_stm32.c
#include "stm32f4xx_hal.h"

// 使用 SPI2 作为 I2S 外设
#define I2S_INSTANCE      SPI2
#define I2S_DMA_STREAM    DMA1_Stream3
#define I2S_DMA_CHANNEL   DMA_CHANNEL_0

#define BUFFER_SIZE       2048
int32_t audioBuffer[BUFFER_SIZE];
volatile uint8_t bufferReady = 0;

I2S_HandleTypeDef hi2s2;
DMA_HandleTypeDef hdma_spi2_rx;

/* -------- I2S + DMA 初始化 -------- */
void INMP441_Init(void) {
    // 1. 使能时钟
    __HAL_RCC_SPI2_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    // 2. GPIO 配置 (PB10=SCK, PB12=WS, PC3=SD)
    GPIO_InitTypeDef gpio = {0};
    gpio.Mode = GPIO_MODE_AF_PP;
    gpio.Pull = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio.Alternate = GPIO_AF5_SPI2;
    
    gpio.Pin = GPIO_PIN_10 | GPIO_PIN_12;
    HAL_GPIO_Init(GPIOB, &gpio);
    
    gpio.Pin = GPIO_PIN_3;
    HAL_GPIO_Init(GPIOC, &gpio);
    
    // 3. I2S 配置 (主机接收模式)
    hi2s2.Instance = SPI2;
    hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
    hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
    hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;  // 24bit → 32bit帧
    hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
    hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_16K;    // 16kHz
    hi2s2.Init.CPOL = I2S_CPOL_LOW;
    hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
    hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
    HAL_I2S_Init(&hi2s2);
    
    // 4. DMA 接收 (循环模式)
    hdma_spi2_rx.Instance = DMA1_Stream3;
    hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_spi2_rx);
    
    __HAL_LINKDMA(&hi2s2, hdmarx, hdma_spi2_rx);
    
    // 5. 启动 I2S DMA 接收
    HAL_I2S_Receive_DMA(&hi2s2, (uint16_t*)audioBuffer, BUFFER_SIZE);
}

/* -------- DMA 半满/全满中断回调 -------- */
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
    // 前半缓冲区就绪 (audioBuffer[0..BUFFER_SIZE/2-1])
    // 可在此处理或置标志位
    bufferReady = 1;
}

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
    // 后半缓冲区就绪 (audioBuffer[BUFFER_SIZE/2..BUFFER_SIZE-1])
    bufferReady = 2;
}

/* -------- 24bit → 32bit 符号扩展(如需要) -------- */
int32_t sign_extend_24bit(uint32_t raw) {
    // INMP441 是 24bit 补码,在 32bit 帧中低8位为0
    int32_t val = (int32_t)(raw >> 8);
    return val;
}

/* -------- 计算RMS -------- */
float calc_rms(int32_t *buf, int len) {
    int64_t sum = 0;
    for (int i = 0; i < len; i++) {
        int32_t val = sign_extend_24bit((uint32_t)buf[i]);
        sum += (int64_t)val * val;
    }
    return sqrtf(sum / (float)len);
}
```

### 主程序使用

```c
// main.c
int main(void) {
    HAL_Init();
    SystemClock_Config();
    INMP441_Init();
    
    float rms_value;
    
    while (1) {
        if (bufferReady == 1) {
            bufferReady = 0;
            rms_value = calc_rms(audioBuffer, BUFFER_SIZE / 2);
            printf("RMS: %.1f\r\n", rms_value);
        } else if (bufferReady == 2) {
            bufferReady = 0;
            rms_value = calc_rms(audioBuffer + BUFFER_SIZE/2, BUFFER_SIZE / 2);
            printf("RMS: %.1f\r\n", rms_value);
        }
        HAL_Delay(50);
    }
}
```

---

## 四、快速验证(示波器检测)

```cpp
// 最简测试:仅读I2S数据打印原始值
// 适用于任何支持I2S的平台
// 预期:安静环境输出接近 0x000000,吹气/说话时数值大幅波动
```

> **注意**:ESP32 的 `I2S_BITS_PER_SAMPLE_24BIT` 实际以 32bit 帧接收,需用 `int32_t` 缓冲区,并右移 8 位获得实际 24bit 值。

参考资料

暂无参考文献