我有 ESP32-WROOM-32D 板和 MAX98357A I2S 板,我需要播放 8Khz 8bit PCM 音频。 pcm 音频缓冲区在标头 wavedata.h 中声明为常量缓冲区,如下所示
const uint8_t rawData[49428] = {0x52, 0x49, 0x46, 0x46,.......};
下面是我通过 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);
}
但我没有听到扬声器发出任何声音。
我也尝试过像下面这样
#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()
{
}
上面的代码也不起作用
请参阅下面的工作代码。我注意到的一点是 MAX98357A 至少需要 16 位音频才能播放 pcm
#include "driver/i2s.h"
#include "wavedata16.h"
#define I2S_SAMPLE_RATE (8000)
#define I2S_SAMPLE_BITS (I2S_BITS_PER_SAMPLE_16BIT)
#define I2S_CHANNEL_NUM (1)
#define I2S_BUFFER_SIZE (16)
#define PIN_LRC 12
#define PIN_BCLK 14
#define PIN_DIN I2S_PIN_NO_CHANGE
#define PIN_DOUT 26
void setup()
{
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER| I2S_MODE_TX),
.sample_rate = I2S_SAMPLE_RATE,
.bits_per_sample = I2S_SAMPLE_BITS,
.channel_format = I2S_CHANNEL_FMT_ALL_RIGHT,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 16,
.dma_buf_len = I2S_BUFFER_SIZE,
};
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_clk((i2s_port_t)0, I2S_SAMPLE_RATE, I2S_SAMPLE_BITS, (i2s_channel_t)1);
}
size_t written_bytes = 0;
void loop()
{
if (written_bytes >= ARRAY_LEN)
written_bytes = 0;
size_t bytes_to_write = sizeof(rawData) - written_bytes;
i2s_write(I2S_NUM_0, &rawData[written_bytes], bytes_to_write, &written_bytes, portMAX_DELAY);
}
另一种方法是使用 I2S 库,请参阅下面的代码
#include <Arduino.h>
#include <I2S.h>
#include "wavedata16.h"
#define I2S_SAMPLE_RATE 8000
#define I2S_SAMPLE_BITS 16
#define PIN_LRC 12
#define PIN_BCLK 14
#define PIN_DOUT 26
int count = 0;
void setup() {
I2S.setSckPin(PIN_BCLK);
I2S.setFsPin(PIN_LRC);
if (!I2S.begin(I2S_PHILIPS_MODE, I2S_SAMPLE_RATE, I2S_SAMPLE_BITS)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
if(count>=ARRAY_LEN)
count=0;
I2S.write(rawData[count]);
I2S.write(rawData[count]);
count++;
}
但是如果你想播放 8 位 PCM 缓冲区,有一个有点棘手的方法,请参阅下面的代码
#include <Arduino.h>
#include <I2S.h>
#include "wavedata.h"
#define I2S_SAMPLE_RATE 8000
#define I2S_SAMPLE_BITS 16
#define PIN_LRC 12
#define PIN_BCLK 14
#define PIN_DOUT 33
int count = 0;
void setup() {
I2S.setSckPin(PIN_BCLK);
I2S.setFsPin(PIN_LRC);
I2S.setDataPin(PIN_DOUT);
if (!I2S.begin(I2S_PHILIPS_MODE, I2S_SAMPLE_RATE, I2S_SAMPLE_BITS)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
if(count>=ARRAY_LEN)
count=0;
int16_t res = map(rawData[count],0,255,-32768,32767);
I2S.write(res);
I2S.write(res);
count++;
}
您能否通过示意图向我提供有关此问题的更多详细信息,因为我也面临同样的问题。 预先感谢。