4 个 GPIO 搞定 4 路麦克风同步采集:ESP-IDF I2S TDM 实战指南
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
基于 ESP-IDF 框架,用 I2S TDM(时分复用)模式只需 4 个 GPIO 就能完成 4 路麦克风同步采集,录音直接以 WAV 存进 SD 卡。下面把 TDM 复用原理、接线对照、采样率与增益等关键参数怎么定、以及从装环境到出数据的最小路径一次讲清。
4 个 GPIO 收 4 路麦:这套方案省掉了什么
传统做法是"一路麦克风一根数据线",4 个麦就要 4 根 I2S 数据线,GPIO 直接不够用。TDM 方案只留一根 DIN 数据线,4 路音频在同一根线上轮流走。
好处很直接:
- 省引脚:MCLK、BCK、WS、DI 共 4 个 GPIO 就够,剩下的脚给 SD 卡和 I2C 控制口
- 天然同步:4 个通道共用同一个位时钟,通道间偏差在微秒以内,做声源定位不需要额外对齐
- 可扩展:官方示例说明最多可级联 4 颗 ES7210 组成 16 通道阵列,仍然只占一个 I2S 口(参考 examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/README.md 的级联接法)
4 路麦数据怎么挤进一根线:I2S TDM 时分复用原理
普通 I2S 一个 WS 周期只传左右两个声道,而 TDM 把同一个 WS 周期切成 4 个时间片(slot),每个麦克风占一片:
| Slot 0 | Slot 1 | Slot 2 | Slot 3 |
|---|---|---|---|
| MIC1 | MIC2 | MIC3 | MIC4 |
ESP32 这边不需要任何软件调度,I2S 外设按 slot 顺序把 16bit 数据依次搬进 DMA 缓冲区,读出来就是 4 通道交错的原始采样。驱动细节可以看 components/esp_driver_i2s/include/driver/i2s_tdm.h,slot 掩码、格式(Philips/MSB/PCM)都在里面定义。
物料清单与 GPIO 接线速查(ES7210 四麦方案)
物料不多,列一张表:
| 物料 | 数量 | 说明 |
|---|---|---|
| ESP32 开发板(S3/C3 等 TDM 支持的芯片) | 1 | 支持 TDM 的目标芯片见示例 README |
| ES7210 四通道音频 ADC 模块 | 1 | 自带 4 路 MIC 输入 |
| 驻极体麦克风 | 4 | 接到 ES7210 的 MIC1~4 |
| SPI 接口的 SD 卡 + 卡座 | 1 | 存 WAV 录音 |
🔌 接线对照表(以 ESP32 的 Kconfig 默认引脚为例,S3/P4/H4 各有默认值,idf.py menuconfig里都能改):
| 信号 | 用途 | 默认 GPIO |
|---|---|---|
| MCLK | 主时钟,ES7210 时钟源 | 0 |
| BCK | 位时钟 | 1 |
| WS | 帧同步/声道切换 | 10 |
| DI | 4 路 TDM 数据输入 | 8 |
| SDA / SCL | I2C 配置 ES7210 | 3 / 2 |
| SPI CLK / MOSI / MISO / CS | SD 卡读写 | 5 / 7 / 6 / 4 |
从零跑通:环境安装到第一条录音三步走
原则是先跑通,再调参。官方示例 examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm/ 已内置esp_codec_dev组件依赖,直接复制就能编译。
第一步,克隆 ESP-IDF、装好工具链,再把示例拷出来:
git clone https://gitcode.com/GitHub_Trending/es/esp-idf cd esp-idf && ./install.sh && . ./export.sh cp -r examples/peripherals/i2s/i2s_codec/i2s_es7210_tdm my_mic_array cd my_mic_array idf.py set-target esp32s3第二步,idf.py menuconfig进入Example Configuration→Example IO Configuration,按你的板子核对一遍 GPIO 号。引脚和你板子对不上时只改这里,不用动代码。
第三步,编译烧录:
idf.py build flash monitor串口里按顺序看到Create I2S receive channel→Configure ES7210 codec parameters→Card size: xxxxMB→Recording: 1/10s走到10/10s,录音就完成了。
预期效果:SD 卡里多出一个RECORD.WAV,48kHz / 16bit / 4 声道,丢进 Audacity 能看到 4 条基本一致的波形。
关键配置怎么改:TDM 槽位、采样率与增益
真正要动的只有三处。核心是 I2S TDM 初始化,它决定了格式、时钟和引脚:
i2s_tdm_config_t tdm_cfg = { .slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG( I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), .clk_cfg = { .clk_src = I2S_CLK_SRC_DEFAULT, .sample_rate_hz = 48000, .mclk_multiple = I2S_MCLK_MULTIPLE_256 }, .gpio_cfg = { .mclk = 0, .bclk = 1, .ws = 10, .dout = -1, .din = 8 }, }; i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg);预期效果:I2S 进入 TDM 接收模式,dout = -1表示只收不发,4 个 slot 全启用。
然后是 ES7210 的 codec 配置,重点在mic_selected和时钟分频:
es7210_codec_cfg_t es7210_cfg = { .ctrl_if = ctrl_if, .master_mode = false, .mic_selected = ES7210_SEL_MIC1 | ES7210_SEL_MIC2 | ES7210_SEL_MIC3 | ES7210_SEL_MIC4, .mclk_src = ES7210_MCLK_FROM_PAD, .mclk_div = I2S_MCLK_MULTIPLE_256, }; const audio_codec_if_t *es7210_if = es7210_codec_new(&es7210_cfg); esp_codec_dev_set_in_gain(codec_handle, 30); // 30dB预期效果:串口打印format: standard i2s, bit width: 16, tdm mode enabled,4 个麦通道全部打开。
最后只是读数据写文件,循环体就这么点:
while (wav_written < wav_size) { i2s_channel_read(rx_chan, buf, sizeof(buf), &bytes_read, pdMS_TO_TICKS(1000)); fwrite(buf, bytes_read, 1, f); // 写进 RECORD.WAV wav_written += bytes_read; }预期效果:串口每秒打印一次Recording: n/10s,10 秒后自动停止并落盘。
参数推荐值与影响:
| 参数 | 推荐值 | 改大 / 改小会怎样 |
|---|---|---|
| 采样率 | 48000 Hz | 改小(如 16k)文件更小、CPU 更省,适合唤醒词场景;改大无实际收益 |
| 位宽 | 16 bit | 改 32 bit 动态范围更好,但带宽和存储翻倍 |
| TDM slot 掩码 | SLOT0~3 全选 | 只选 2 个 slot 时 ES7210 需切回普通 I2S 格式,否则数据错位 |
| MCLK 倍频 | 256 | ES7210 要求 MCLK = 采样率 × 256(48k 时 12.288MHz),改这里要同步改mclk_div |
| 麦克风增益 | 30 dB | 调高更灵敏但容易削顶失真;调低则底噪占比变大,建议从 30dB 试起 |
排坑清单:现象 → 原因 → 处置
| 现象 | 原因 | 处置 |
|---|---|---|
| 4 路全静默 | I2C 没配通 ES7210 | 核对 SDA/SCL 引脚和上拉电阻,串口应能看到ES7210:开头的配置日志 |
| 某个通道无声或串到别的声道 | slot 掩码与mic_selected不一致 | 两边保持相同通道数,格式都用默认 Philips |
| 录音有周期性"嘟嘟"声 | MCLK 不稳或走线过长 | 缩短时钟线,MCLK 上加 100nF 去耦电容 |
| SD 卡挂载失败 | 卡未格式化或 SPI 无上拉 | 重刷成 FAT32,确认 SPI 线路有上拉(代码日志也会提示这一点) |
| 波形削顶、大音量失真 | 增益过高 | esp_codec_dev_set_in_gain从 30dB 往下调到 20dB |
下一步玩法:从 4 通道继续扩展
跑通单颗 ES7210 之后,这几条路线值得试:
- 级联到 8 / 16 通道:README 里给了最多 4 颗 ES7210 通过 TDMIN/TDMOUT 链式级联的接法,一个 I2S 口扩成 16 通道阵列,是做声源定位的常规做法
- 实时音频处理:把
i2s_channel_read读出的 4 通道流接到你的算法(回声消除、降噪、波束成形),录音落盘改成管道输出即可 - 无线回传:加 Wi-Fi 或 BLE 把多通道音频流推到 PC 端分析,示例目录下的 i2s_usb 可以参考 USB 回传的写法
把 RECORD.WAV 拖进 Audacity 确认 4 条波形对齐之后,这套 4 麦同步采集链路就算真正立住了,剩下的只是往上叠算法的事。
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考