You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过I2S在ESP32-WROOM-32D上播放8KHz 8bit PCM音频?

ESP32 + MAX98357A 播放8bit 8KHz PCM无声音问题排查

问题背景

使用ESP32-WROOM-32D开发板搭配MAX98357A I2S音频板,需播放存储在wavedata.h中的8KHz 8bit PCM音频,常量数组定义如下:

const uint8_t rawData[49428] = {0x52, 0x49, 0x46, 0x46,.......};

尝试两段代码均无声音输出,代码如下:

第一段Arduino I2S库代码

#include "wavedata.h"
#include <Arduino.h>
#include <I2S.h>

#define LRC_PIN             26
#define BCLK_PIN            27
#define DOUT_PIN            25
void setup()
{
    I2S.begin(I2S_PHILIPS_MODE, 8000, 8);
    I2S.setSckPin(BCLK_PIN);
    I2S.setFsPin(LRC_PIN);
    I2S.setDataPin(DOUT_PIN);
    
}
void loop()
{
    I2S.write_blocking(rawData,49428);
    delay(1000);
}

第二段ESP-IDF原生I2S代码

#include "driver/i2s.h"
#include "wavedata.h"

#define I2S_SAMPLE_RATE     (8000)
#define I2S_SAMPLE_BITS     (I2S_BITS_PER_SAMPLE_8BIT)
#define I2S_CHANNEL_NUM     (1)
#define I2S_BUFFER_SIZE     (512)
#define PIN_LRC             25
#define PIN_BCLK            14
#define PIN_DIN             I2S_PIN_NO_CHANGE
#define PIN_DOUT            25
#define MCK                 I2S_PIN_NO_CHANGE

void setup()
{
    
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER),
        .sample_rate = I2S_SAMPLE_RATE,
        .bits_per_sample = I2S_SAMPLE_BITS,
        .channel_format = I2S_CHANNEL_FMT_ALL_LEFT,
        .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S),
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 16,
        .dma_buf_len = I2S_BUFFER_SIZE,
        .use_apll = false,          // must be disabled in V2.0.1-RC1
        .tx_desc_auto_clear = true, // new in V1.0.1
        .fixed_mclk = I2S_PIN_NO_CHANGE,
    };
    i2s_pin_config_t pin_config = {
        .bck_io_num = PIN_BCLK,
        .ws_io_num = PIN_LRC,
        .data_out_num = PIN_DOUT,
        .data_in_num = PIN_DIN,
    };

    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
    i2s_set_sample_rates(I2S_NUM_0, I2S_SAMPLE_RATE);

    size_t written_bytes = 0;
    while (written_bytes < sizeof(rawData)) {
        size_t bytes_to_write = sizeof(rawData) - written_bytes;
        if (bytes_to_write > I2S_BUFFER_SIZE) {
            bytes_to_write = I2S_BUFFER_SIZE;
        }
        i2s_write(I2S_NUM_0, &rawData[written_bytes], bytes_to_write, &written_bytes, portMAX_DELAY);
    }

    i2s_driver_uninstall(I2S_NUM_0);
}

void loop()
{
}

问题排查与修正

第一段代码的问题

  1. I2S模式缺失发送配置:仅指定主模式未开启发送,需添加I2S_MODE_TX
  2. 引脚设置顺序错误:必须先配置引脚再初始化I2S,否则配置不生效
  3. 单声道参数缺失:初始化时未指定单声道,需补充对应参数

修正后的第一段代码:

#include "wavedata.h"
#include <Arduino.h>
#include <I2S.h>

#define LRC_PIN     26
#define BCLK_PIN    27
#define DOUT_PIN    25

void setup()
{
    // 先配置引脚
    I2S.setSckPin(BCLK_PIN);
    I2S.setFsPin(LRC_PIN);
    I2S.setDataPin(DOUT_PIN);
    // 开启主发送模式,指定采样率、位深、单声道
    I2S.begin(I2S_PHILIPS_MODE, 8000, 8, 1);
}

void loop()
{
    // 阻塞式写入整个音频缓冲区
    I2S.write_blocking(rawData, sizeof(rawData));
    delay(1000);
}

第二段代码的问题

  1. 引脚冲突:PIN_LRC和PIN_DOUT都设为25,导致信号混乱
  2. I2S模式未开启发送:.mode字段仅设置主模式,需添加I2S_MODE_TX
  3. 播放逻辑错误:一次性写完音频后立即卸载驱动,导致播放不完整且仅播放一次

修正后的第二段代码:

#include "driver/i2s.h"
#include "wavedata.h"

#define I2S_SAMPLE_RATE     8000
#define I2S_SAMPLE_BITS     I2S_BITS_PER_SAMPLE_8BIT
#define I2S_BUFFER_SIZE     512
// 修正引脚冲突,统一引脚定义
#define PIN_LRC             26
#define PIN_BCLK            27
#define PIN_DOUT            25
#define PIN_DIN             I2S_PIN_NO_CHANGE

void setup()
{
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_TX, // 开启主发送模式
        .sample_rate = I2S_SAMPLE_RATE,
        .bits_per_sample = I2S_SAMPLE_BITS,
        .channel_format = I2S_CHANNEL_FMT_ALL_LEFT, // 单声道左声道
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8, // 减少缓冲区数量,降低内存占用
        .dma_buf_len = I2S_BUFFER_SIZE,
        .use_apll = false,
        .tx_desc_auto_clear = true,
        .fixed_mclk = I2S_PIN_NO_CHANGE,
    };

    i2s_pin_config_t pin_config = {
        .bck_io_num = PIN_BCLK,
        .ws_io_num = PIN_LRC,
        .data_out_num = PIN_DOUT,
        .data_in_num = PIN_DIN,
    };

    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
    i2s_set_sample_rates(I2S_NUM_0, I2S_SAMPLE_RATE);
}

void loop()
{
    size_t total_written = 0;
    const size_t total_size = sizeof(rawData);
    // 循环播放整个音频缓冲区
    while (total_written < total_size) {
        size_t bytes_to_write = total_size - total_written;
        if (bytes_to_write > I2S_BUFFER_SIZE) {
            bytes_to_write = I2S_BUFFER_SIZE;
        }
        size_t bytes_written = 0;
        // 使用临时变量接收实际写入字节数
        i2s_write(I2S_NUM_0, &rawData[total_written], bytes_to_write, &bytes_written, portMAX_DELAY);
        total_written += bytes_written;
    }
    delay(1000);
}

额外注意事项

  • 硬件连接检查:确认MAX98357A的BCLK、LRC、DIN分别对应ESP32的指定引脚;VCC接3.3V/5V(依模块规格),GND共地,SD引脚需接高电平或悬空(避免静音)
  • PCM数据格式:rawData开头是0x52 0x49 0x46 0x46(RIFF头),需去除WAV文件头,仅保留纯PCM采样数据
  • 增益调节:若声音异常,可检查MAX98357A的增益设置电阻

内容的提问来源于stack exchange,提问作者Arun K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 18:25:00