안녕하세요. 해당 시리즈에서는 ESP32, MAX98357A, SD카드를 이용해서 SD카드에있는 음원파일을 출력해보고 최종적으로는 ESP32대신 STM32를 이용해서 Speaker 보드를 만들어보겠습니다.
① ESP32와 MAX98357A 소개, 그리고 PCM 개념
ESP32는 ESP32 WROOM 32를 이용했고 앰프는 MAX98357A를 이용합니다.

ESP32와 MAX98357A는 I2S 통신을 합니다.
I2S 통신은 오디오 데이터를 PCM 형태로 주고받는 인터페이스입니다. PCM(Pulse Code Modulation)은 아날로그 소리를 일정 주기마다 디지털 숫자로 저장한 것을 의미합니다.
PCM 변환 과정은 3단계입니다.
1. 샘플링(Sampling)
- 아날로그 파형을 일정한 시간 간격으로 잘라서 측정 (예시: 샘플레이트 8kHz면 1초에 8000번 측정)
2. 양자화(Quantization)
- 샘플링 값(연속 실수)을 가장 가까운 정수 단계로 반올림 예시 : 16bit면 65,536 단계)
3. 부호화(Encoding)
- 양자화된 정수를 2진수 코드로 표현
② I2S 통신의 필수 핀과 역할
I2S 통신으로 PCM데이터를 주고받을때 필수 핀 3가지가 있습니다.
1. BCLK (Bit Clock)
- 데이터 비트 하나 보낼 때마다 한 번씩 토글되는 클럭
2. LRCK(Word Select, WS, LRC)
- Left/Right 채널 구분 (Left : Low, Right : High)
3. SD (Serial Data)
- PCM 데이터
③ I2S 파형 분석: 샘플레이트와 비트 뎁스
실제 I2S 파형을 보고 ①, ②번의 내용을 확인해보겠습니다.
I2S통신은 처음 통신할때 칩에다가 현재 샘플레이트, 비트뎁스를 보내지않고 클럭의 패턴이 그 정보를 담고있습니다.
파형 : samplerate : 8kHz, bit depth : 8bit, PCM DATA : 500

④440Hz 사각톤 생성 예제
440Hz 사각톤 파를 생성하는 예제입니다. 아두이노 코드입니다.
440Hz이므로 1초에 440번 반복합니다. 한 주기의 간격은 1/440= 2.27ms 입니다.
샘플레이트가 8000Hz이므로 1샘플 간격은 1/8000 = 125us 입니다.
한 주기 안에 샘플은 2.27ms/125us = 18.18 --> 약 18개가 들어갑니다.
그래서 사각톤 파를 만들려면 18/2= 9 --> 9번 HIGH, 9번 LOW하면 됩니다.
아래의 코드에서 halfWavelength는 9가 되고 9번 HIGH, 9번 LOW를 하게 됩니다.
#include <ESP_I2S.h>
#define I2S_LRC 25
#define I2S_BCLK 5
#define I2S_DIN 26
const int frequency = 440; // frequency of square wave in Hz
const int amplitude = 500; // amplitude of square wave
const int sampleRate = 8000; // sample rate in Hz
i2s_data_bit_width_t bps = I2S_DATA_BIT_WIDTH_16BIT;
i2s_mode_t mode = I2S_MODE_STD;
i2s_slot_mode_t slot = I2S_SLOT_MODE_STEREO;
const unsigned int halfWavelength = sampleRate / frequency / 2; // half wavelength of square wave
int32_t sample = amplitude; // current sample value
unsigned int count = 0;
I2SClass i2s;
void setup() {
Serial.begin(115200);
Serial.println("I2S simple tone");
i2s.setPins(I2S_BCLK, I2S_LRC, I2S_DIN);
// start I2S at the sample rate with 16-bits per sample
if (!i2s.begin(mode, sampleRate, bps, slot)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
if (count % halfWavelength == 0) {
// invert the sample every half wavelength count multiple to generate square wave
sample = -1 * sample;
}
// Left channel, the low 8 bits then high 8 bits
i2s.write(sample);
i2s.write(sample >> 8);
// Right channel, the low 8 bits then high 8 bits
i2s.write(sample);
i2s.write(sample >> 8);
// increment the counter for the next sample
count++;
}

(LEFT 500 / RIGHT 500) * 9프레임 = 1.125 ms
(LEFT -500 / RIGHT -500) * 9프레임 = 1.125 ms
→ 반복
출력에대한 파형측정은 아래의 글에 있습니다.
https://wowon.tistory.com/362
'PROJECT > Speaker' 카테고리의 다른 글
| Speaker 만들기 3편 (회로도작성, SD카드에있는 WAV파일 버튼으로 재생) (0) | 2026.01.04 |
|---|---|
| Speaker 만들기 2편 (SD카드에 있는 wav파일 재생) (0) | 2025.10.12 |