MAX98357 I2S功放模块测试

之前购买了一个MAX98357 I2S功放模块,这次编写简单的代码进行测试。

硬件连接如下:

MAX98357ESP32S3用途
SPK+/- 连接喇叭 连接喇叭正负极,喇叭输出
DIN  48从 ESP32S3 发送的 I2S数据
BCLK45从 ESP32S3 发送的 I2S Clock
LRC 35从 ESP32S3 发送的 I2S 左右声道选择信号
GNDGND
VCC5V供电

按照上述方案连接好后,烧录如下代码:

#include <I2S.h>
const int frequency = 440; // frequency of square wave in Hz
const int amplitude = 32000; // amplitude of square wave
const int sampleRate = 8000; // sample rate in Hz
const int bps = 16;

const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave

short sample = amplitude; // current sample value
int count = 0;

i2s_mode_t mode = I2S_PHILIPS_MODE; // I2S decoder is needed
// i2s_mode_t mode = ADC_DAC_MODE; // Audio amplifier is needed

// Mono channel input
// This is ESP specific implementation -
//   samples will be automatically copied to both channels inside I2S driver
//   If you want to have true mono output use I2S_PHILIPS_MODE and interlay
//   second channel with 0-value samples.
//   The order of channels is RIGH followed by LEFT
//i2s_mode_t mode = I2S_RIGHT_JUSTIFIED_MODE; // I2S decoder is needed

void setup() {
  Serial.begin(115200);
  Serial.println("I2S simple tone");
  delay(5000);

    //setAllPins(int sckPin, int fsPin, int sdPin, int outSdPin, int inSdPin);
  I2S.setAllPins(45        , 35       , 48       , 48          , -1);

  // start I2S at the sample rate with 16-bits per sample
  if (!I2S.begin(mode, sampleRate, bps)) {
    
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }
}

void loop() {

   while (Serial.available()) {
    char c = Serial.read();
    if (c == '3') {
      ESP.restart();
    }
    // 主机端发送 l, 回复 z 用于识别串口
    if (c == '1') {
      Serial.print('z');
    }
    // 主机端发送 l, 回复 z 用于识别串口
    if (c == '2') {
      Serial.printf("getSckPin:%d getFsPin:%d getDataPin:%d",
                      I2S.getSckPin(),
                      I2S.getFsPin(),
                      I2S.getDataPin());
    }    
  }

  
    if (count % halfWavelength == 0 ) {
      // invert the sample every half wavelength count multiple to generate square wave
      sample = -1 * sample;
    }

    if(mode == I2S_PHILIPS_MODE || mode == ADC_DAC_MODE){ // write the same sample twice, once for Right and once for Left channel
      I2S.write(sample); // Right channel
      I2S.write(sample); // Left channel
    }else if(mode == I2S_RIGHT_JUSTIFIED_MODE || mode == I2S_LEFT_JUSTIFIED_MODE){
      // write the same only once - it will be automatically copied to the other channel
      I2S.write(sample);
    }

    // increment the counter for the next sample
    count++;
}

测试的视频在下面可以看到:

特别注意: MAX98357 的 SD 必须接 3.3V .

=============================================================

2025年6月7日

Arduino IIS 方面有很大改动,这里贴一个可以工作的版本(ESP32 3.2.0,频率不对,但是至少有声音):

#include <driver/i2s_std.h>
#include <driver/i2s_common.h>
#include <driver/i2s.h>

#define SAMPLE_RATE 16000
#define BITS_PER_SAMPLE I2S_DATA_BIT_WIDTH_32BIT

static IRAM_ATTR bool i2s_tx_callback(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx)
{
  Serial.println("g");
  return false;
}

i2s_chan_handle_t amp_handle;
void setup() {
  Serial.begin(115200);
  // 配置AMP输出

  // 1. 通道配置
  i2s_chan_config_t amp_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
  i2s_new_channel(&amp_chan_cfg, &amp_handle, NULL);

  // 2. 标准模式配置
  i2s_std_config_t amp_std_cfg = {
    .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
    .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(BITS_PER_SAMPLE, I2S_SLOT_MODE_MONO),
    .gpio_cfg = {
      .mclk = I2S_GPIO_UNUSED,
      .bclk = GPIO_NUM_35,
      .ws = GPIO_NUM_45,
      .dout = GPIO_NUM_48,
      .din = I2S_GPIO_UNUSED,
      .invert_flags = {
        .mclk_inv = false,
        .bclk_inv = false,
        .ws_inv = false,
      },
    },

  };

  // 3. 初始化标准模式
  ESP_ERROR_CHECK(i2s_channel_init_std_mode(amp_handle, &amp_std_cfg));


  // 4. 注册事件回调
  i2s_event_callbacks_t cbs = {
    .on_recv = NULL,
    .on_recv_q_ovf = NULL,
    .on_sent = i2s_tx_callback,
    .on_send_q_ovf = NULL,
  };
  i2s_channel_register_event_callback(amp_handle, &cbs, NULL);


  // 5. 启用通道
  ESP_ERROR_CHECK(i2s_channel_enable(amp_handle));


  Serial.println("I2S Init Done");
}

void loop() {
  // 示例音频数据(正弦波)
  static int16_t audio_data[128];
  static float phase = 0;
  for (int i = 0; i < 128; i += 2) {
    audio_data[i] = 32767 * sin(phase);   // 左声道
    audio_data[i + 1] = -audio_data[i];   // 右声道
    phase += 0.1;
  }

  // 发送音频数据
  size_t bytes_written;
  i2s_channel_write(amp_handle, audio_data, sizeof(audio_data),
                    &bytes_written, portMAX_DELAY);
  Serial.println(bytes_written);
  delay(10);
}