I2S 协议的基本事理是利用以下几条线来传输数据:MCLK:主时钟线,可选的旗子暗记,紧张用于为 I2S 从设备供应参考时钟。BCLK:位时钟线,用于数据线的位时钟。WS:字(槽)选择线,常日用于标识声道,除了 PDM 模式。DIN/DOUT:串行数据输入/输出线。(如果 din 和 dout 设置为相同的 GPIO,则数据会在内部回环)
I2S 外设还支持 LCD 模式,用于通过并行总线传输数据,一些 LCD 显示器和摄像头模块利用这种模式。
I2S 外设的每个掌握器都有以下特性,可以通过 I2S 驱动来配置:
作为系统主机或从机运行能够充当发送器或吸收器DMA 掌握器,许可流式传输采样数据,无需 CPU 复制每个数据样本每个掌握器可以以半双工通信模式运行。因此,两个掌握器可以组合起来建立全双工通信。I2S0 输出可以直接路由到数字仿照转换器(DAC)的输出通道(GPIO 25 和 GPIO 26),以产生直接的仿照输出,无需涉及任何外部 I2S 编解码器。I2S0 还可以用于传输 PDM(脉冲密度调制)旗子暗记。要在 ESP32 上利用 I2S,须要以下几个步骤:
安装 I2S 驱动程序。可以利用 ESP-IDF 编程指南 或 Arduino-ESP32 文档2中供应的 I2S API 来安装驱动程序。配置 I2S 参数。须要根据运用处景选择得当的通信模式(标准、TDM 或 PDM)、时钟源、采样率、数据位宽、声道数等参数。连接 I2S 引脚。须要将 ESP32 的 I2S 引脚(MCLK、BCLK、WS、DIN/DOUT)连接到相应的外部设备(如音频编解码器、麦克风、扬声器等)。读写 I2S 数据。您可以利用 I2S API 中供应的函数来读取或写入音频数据,或者利用 DMA 掌握器来实现数据流传输。以下是一个利用 ESP32 和 MAX98357A 来实现 I2S 的发送和吸收音频数据的示例代码:这段代码会从一个外部设备(如麦克风)读取音频数据,并将其发送到另一个外部设备(如扬声器)。
#include "driver/i2s.h"#define SAMPLE_RATE (44100)#define SAMPLE_BITS (16)#define CHANNELS (2)#define PIN_I2S_BCLK (26)#define PIN_I2S_LRC (25)#define PIN_I2S_DIN (33)#define PIN_I2S_DOUT (27)void app_main(void){ //配置I2S参数 i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX, //主机模式,发送和吸收 .sample_rate = SAMPLE_RATE, .bits_per_sample = SAMPLE_BITS, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //双声道 .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //中断优先级 .dma_buf_count = 6, .dma_buf_len = 60, .use_apll = false }; //配置I2S引脚 i2s_pin_config_t pin_config = { .bck_io_num = PIN_I2S_BCLK, //位时钟 .ws_io_num = PIN_I2S_LRC, //字选择 .data_out_num = PIN_I2S_DOUT, //数据输出 .data_in_num = PIN_I2S_DIN //数据输入 }; //安装I2S驱动程序 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); //设置I2S引脚 i2s_set_pin(I2S_NUM_0, &pin_config); //设置I2S时钟 i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, SAMPLE_BITS, CHANNELS); //创建一个缓冲区,用于存储音频数据 int buffer_size = 1024; char buffer = malloc(buffer_size); while (1) { //从I2S读取音频数据 int bytes_read = 0; i2s_read(I2S_NUM_0, buffer, buffer_size, &bytes_read, portMAX_DELAY); //将音频数据写入I2S int bytes_written = 0; i2s_write(I2S_NUM_0, buffer, bytes_read, &bytes_written, portMAX_DELAY); }}