介绍
INMP441 MEMS全向麦克风模块,I2S数字输出,支持64dB高信噪比,-26dBFS灵敏度,24位精度,低功耗1.4mA,适用于远场语音识别、智能音箱、AI语音助手等应用
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 (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 值。
暂无参考文献