【ESP32 在線語音】ESP32的I2S音頻數據開發
實驗:https://www.bilibili.com/opus/1126928057651691553
INMP441 數據手冊:https://www.digikey.cn/htmldatasheets/production/1431884/0/0/1/inmp441-datasheet.html
I2S的應用

注意:MAX98357是否能播放PCM數據,要確保PCM的(采樣率、位深度、聲道數)和MAX98357一樣
如果不一樣者可以通過ffmpeg轉換
開發流程

頭文件
#include "driver/i2s.h"
i2s_pin_config_t結構體
配置 I2S 外設的引腳的結構體
typedef struct {
int mck_io_num;
int bck_io_num;
int ws_io_num;
int data_out_num;
int data_in_num;
} i2s_pin_config_t;
結構體字段說明:
mck_io_num: MCLK 輸出引腳(主時鐘)
ESP32 只支持 GPIO0/GPIO1/GPIO3,如果不使用 MCLK 輸出,可以設置為 I2S_PIN_NO_CHANGE
bck_io_num: BCK 或 SCK(Bit Clock,比特時鐘)引腳號,
I2S 每傳輸一位數據都會在 BCK 上產生一次時鐘脈沖,必填,若不連接通常設為 -1(但多數場景必需)
ws_io_num: WS、LRCK 或 LRCLK(Word Select/Left-Right Clock,左右聲道選擇時鐘)引腳號,
用于指示當前傳輸的是左聲道還是右聲道數據,必填,典型音頻 CODEC 必需。
data_out_num: 數據輸出引腳號(I2S TX,MCU 向外設發送音頻數據)
作為主機播放音頻時需要。
不用可設為 -1。
data_in_num: 數據輸入引腳號(I2S RX,MCU 從外設接收音頻數據)
作為主機采集/錄音時需要。
不用可設為 -1。
設置外設GPIO的引腳
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
參數說明:
i2s_num:I2S 外設端口號
I2S_NUM_0
I2S_NUM_1
pin:指向 i2s_pin_config_t 的指針
返回值
- ESP_OK:設置成功。
- ESP_ERR_INVALID_ARG:參數非法(如 GPIO 不支持、端口號錯誤、與硬件限制不符)。
- ESP_FAIL 或其他錯誤碼:路由失敗或驅動未初始化等
i2s_driver_config_t結構體
用于配置 I2S 驅動的工作模式、采樣率、數據位寬、DMA 緩沖等
typedef struct {
i2s_mode_t mode;
uint32_t sample_rate;
i2s_bits_per_sample_t bits_per_sample;
i2s_channel_fmt_t channel_format;
i2s_comm_format_t communication_format;
int intr_alloc_flags;
int dma_buf_count;
int dma_buf_len;
bool use_apll;
bool tx_desc_auto_clear;
int fixed_mclk;
i2s_mclk_multiple_t mclk_multiple;
i2s_bits_per_chan_t bits_per_chan;
#if SOC_I2S_SUPPORTS_TDM
i2s_channel_t chan_mask;
uint32_t total_chan;
bool left_align;
bool big_edin;
bool bit_order_msb;
bool skip_msk;
#endif // SOC_I2S_SUPPORTS_TDM
} i2s_driver_config_t;
結構體說明:
mode:I2S 工作模式與方向、主從設置
I2S_MODE_MASTER | I2S_MODE_TX(主機發送/播放)
I2S_MODE_MASTER | I2S_MODE_RX(主機接收/錄音)
sample_rate:采樣率(Hz)
8000
16000
44100
48000
96000
bits_per_sample:每個通道的有效采樣位數
16
24
32
channel_format:聲道格式與排列方式
I2S_CHANNEL_FMT_RIGHT_LEFT(標準立體聲左右通道),也可能有僅左/僅右、或多聲道(TDM)場景的設置
communication_format:通信協議格式/時序兼容性
I2S 標準、左對齊、右對齊、MSB/LSB 對齊等模式標志
intr_alloc_flags:中斷分配標志
ESP_INTR_FLAG_LEVELx
ESP_INTR_FLAG_IRAM
dma_buf_count:DMA 緩沖區塊的數量(描述符個數
越大越平滑(降低中斷頻率、減小欠載/溢出風險),但占用內存更多。典型 4~16
dma_buf_len:每個 DMA 緩沖中“幀”的數量
一幀是一次 WS 周期內所有聲道樣本的集合
use_apll:是否使用 APLL 作為 I2S 主時鐘源
tx_desc_auto_clear:在 TX 欠載(無數據可發)時是否自動清空 TX 描述符
有助于避免噪聲/爆音;開啟后遇到數據斷流時輸出靜音而不是隨機數據
fixed_mclk:固定 MCLK 輸出頻率(Hz)
若 use_apll=true 且 fixed_mclk>0,則 MCLK 固定為該值;此時 mclk_multiple 設置不再生效。
常用于對某些 CODEC 需要特定 MCLK(如 12.288 MHz、24.576 MHz)
mclk_multiple:MCLK 與采樣率的倍數關系
bits_per_chan:每通道“總線傳輸位寬”(對齊位寬)
字段僅在芯片支持 TDM
chan_mask:使能的通道位掩碼
total_chan:總通道(時隙)數
left_align:使能左對齊(Left-Justified)時序
big_edin:使能“big endian”輸入模式
bit_order_msb:使能 MSB-first 位序
skip_msk:啟用“跳過掩碼”模式:若開啟,只發送/接收已啟用通道的數據;否則 DMA 緩沖中所有通道的數據都會按總通道數發送/接收
安裝/初始化 I2S 驅動的函數
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue);
參數說明:
i2s_num:I2S 端口號i2s_config:指向 I2S 配置結構體的指針queue_size:若需要事件隊列,設置隊列容量(隊列元素個數)。設置為 0 表示不創建隊列i2s_queue:若需要隊列,傳入 QueueHandle_t* 的指針地址,用于返回創建好的隊列句柄;若不需要隊列,可傳 NULL,或 queue_size 設為 0
返回值
- SP_OK:成功
- ESP_ERR_INVALID_ARG:參數非法(如配置超限、不支持的模式/位寬)
- ESP_ERR_NO_MEM:內存不足(DMA/隊列/驅動資源申請失?。?/li>
- ESP_FAIL 或其他:初始化底層硬件失敗
卸載/釋放 I2S 驅動
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
參數說明
i2s_num:I2S 端口號(如 I2S_NUM_0、I2S_NUM_1)
返回值
- ESP_OK:卸載成功
- ESP_ERR_INVALID_ARG:端口號非法或對應驅動未安裝
- 其他錯誤碼:底層釋放失?。ㄉ僖姡?/li>
將音頻數據寫入外設設置
esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait);
參數說明:
i2s_num: I2S 端口號src: 待發送的數據緩沖區指針size: 要寫入的字節數src_bits: 實際寫入的字節數輸出指針;可為 NULL(不關心返回的寫入量)bytes_written: 實際寫入的字節數輸出指針;可為 NULL(不關心返回的寫入量)ticks_to_wait: 寫入阻塞的最長 Tick 數
portMAX_DELAY:一直等到有空間
0:不阻塞,若無空間立即返回超時
pdMS_TO_TICKS(ms):按毫秒轉換
返回值
- ESP_OK:調用成功。注意不代表 size 全部寫入,實際寫入量看 bytes_written。
- ESP_ERR_INVALID_ARG:參數非法(如 src 為 NULL、size 為 0、端口未啟用 TX)
- ESP_FAIL:驅動未安裝或處于錯誤狀態
- ESP_ERR_TIMEOUT:在 ticks_to_wait 內 DMA 無可用空間(常見于非阻塞或等待時間太短)
讀取音頻數據
esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);
參數說明:
i2s_num: I2S 端口號(如 I2S_NUM_0、I2S_NUM_1)dest: 目標緩沖區指針,函數會將讀取到的字節寫入此處size: 期望讀取的字節數bytes_read:實際讀取到的字節數輸出指針;可為 NULL(不關心實際讀取量)ticks_to_wait: 阻塞等待可讀數據的最長 Tick 數
portMAX_DELAY:一直等到有數據
0:非阻塞,若無數據立即返回超時
pdMS_TO_TICKS(ms):按毫秒轉換
返回值
- ESP_OK:調用成功(不保證讀取滿 size,需查看 bytes_read)
- ESP_ERR_INVALID_ARG:參數非法(dest 為 NULL、size 為 0、端口未啟用 RX 等)
- ESP_FAIL:驅動未安裝或硬件狀態異常
- ESP_ERR_TIMEOUT:在指定等待時間內沒有足夠數據可讀(常見于非阻塞或等待時間過短)

浙公網安備 33010602011771號