I2C vs I2S vs SPI: Audio Interface Protocols Compared
Understanding the differences between I2C, I2S, and SPI for audio applications is essential for every embedded systems engineer. While I2C handles control registers, I2S carries actual audio data streams, and SPI handles high-speed data transfer — each protocol has distinct strengths and limitations. This comprehensive comparison helps Indian electronics engineers and Arduino/ESP32 makers choose the right interface for microphones, DACs, codecs, and audio processors.
Protocol Overview and History
These three protocols were developed for different purposes and operate at different abstraction levels in an audio system:
- I2C (Inter-Integrated Circuit): Developed by Philips (1982). Two-wire (SCL+SDA), multi-device bus. Used to configure audio chips — setting volume, EQ, mute, sample rate. Maximum speed 400kHz (Fast Mode) or 3.4MHz (High Speed). NOT used to carry audio data (too slow).
- I2S (Inter-IC Sound): Also Philips, developed specifically for audio data transfer between chips (1986). Three/four wire (SCK+WS+SD). Carries 16-32 bit stereo audio at 44.1-384kHz sample rates. Purpose-built for audio — synchronous, word-aligned.
- SPI (Serial Peripheral Interface): Motorola/Freescale (1979). Four-wire (SCK+MOSI+MISO+CS). General-purpose high-speed data transfer. Used in audio for SD card access (music files), flash memory (audio samples), and some ADC/DAC chips with SPI interface.
I2C in Audio Systems: Configuration Bus
I2C serves as the control plane in audio systems. You send register write commands to set up codec parameters, not audio samples. Think of it as the remote control for your audio chip.
// I2C Audio Codec Configuration Example
// Configuring WM8960 codec via I2C
// Note: WM8960 uses 9-bit register values via I2C 2-byte writes
#include <Wire.h>
#define WM8960_ADDR 0x1A // I2C address (AD0 pin = LOW)
// WM8960 register writes: [reg_addr <> 8)], [val & 0xFF]
bool wm8960_write(uint8_t reg, uint16_t val) {
Wire.beginTransmission(WM8960_ADDR);
Wire.write((reg <> 8) & 0x01)); // Register + MSB
Wire.write(val & 0xFF); // LSB
return Wire.endTransmission() == 0;
}
void setup() {
Wire.begin();
Wire.setClock(400000); // 400kHz Fast Mode
// Initialize WM8960
wm8960_write(0x0F, 0x000); // Reset chip
delay(100);
wm8960_write(0x19, 0x1FC); // Power Management 1: Enable VMID + VREF
wm8960_write(0x1A, 0x1F8); // Power Management 2: Enable DAC + Amp
wm8960_write(0x02, 0x179); // Left Headphone: 0dB volume
wm8960_write(0x03, 0x179); // Right Headphone: 0dB volume
wm8960_write(0x05, 0x000); // ADC/DAC Control
Serial.println("WM8960 configured via I2C");
// Now use I2S for the actual audio data
}
/* I2C Audio Device Address Cheat Sheet:
* WM8960: 0x1A
* PCM1802: 0x4A
* TDA7419: 0x44 (car audio equalizer)
* CS43L22: 0x4A (STM32 Discovery DAC)
*/
I2S Deep Dive: The Audio Data Standard
I2S is the data plane for digital audio — it carries the actual PCM samples that become sound. Understanding I2S signal lines is essential for any audio project:
- SCK (Serial Clock / BCLK): Bit clock. Frequency = sample_rate × bits_per_sample × channels. For 44.1kHz/16-bit stereo: 44100 × 16 × 2 = 1.41MHz
- WS (Word Select / LRCK): Frame sync / left-right clock. Frequency = sample rate (44.1kHz). LOW = left channel, HIGH = right channel
- SD (Serial Data): Audio samples, MSB first, transmitted after WS edge (1-bit delay = I2S standard)
- MCLK (Master Clock, optional): 256× or 512× the sample rate. Some codecs need MCLK as PLL reference. 44.1kHz × 256 = 11.29MHz
// I2S Format Variations (important for device compatibility)
//
// Standard I2S (Philips): Data starts 1 SCK after WS transition
// WS: ______|‾‾‾‾‾‾|___|‾‾‾‾‾‾ (L=low, R=high)
// SCK: |1|2|3|4|5|6|7|8|...
// SD: x[MSB....LSB][MSB.... (1-bit delayed)
//
// Left-Justified: Data starts on WS transition
// SD: [MSB....LSB][MSB.... (no delay)
//
// Right-Justified: Data ends on next WS transition
// SD: [padding][MSB....LSB] (LSB just before WS)
//
// PCM modes: Used by Bluetooth audio, voice codecs
// Short frame: Single SCK pulse per WS high period
//
// ESP32 I2S hardware supports: Standard I2S, Left-Justified, Right-Justified
// PDM mode also supported (for PDM MEMS mics)
// INMP441 uses Standard I2S
// PCM5102 uses Standard I2S
// WM8960 configurable (default Standard I2S)
// MAX98357A uses Standard I2S
Recommended Product
INMP441 I2S MEMS Microphone Module
Pure I2S output microphone — the perfect hands-on I2S learning tool for ESP32. Direct digital audio output, no analog chain required.
Category: Audio & Sound Modules
SPI for Audio: High-Speed Data Transfer
SPI is used in audio systems primarily for storage access (SD cards, SPI flash) and some high-speed ADC/DAC chips that choose SPI over I2S for its simpler framing protocol.
// SPI Audio Flash Memory Access
// Storing and streaming audio samples from W25Q64 flash (8MB)
// SPI at 40MHz → throughput: 40MB/s (enough for 16-bit/44.1kHz stereo)
#include <SPI.h>
#define FLASH_CS 10
#define FLASH_CLK 13
#define FLASH_DO 12 // MISO
#define FLASH_DI 11 // MOSI
// W25Q64 commands
#define CMD_READ 0x03
#define CMD_WRITE_EN 0x06
#define CMD_PAGE_PROG 0x02
void readAudioFromFlash(uint32_t addr, uint8_t *buf, uint32_t len) {
SPI.beginTransaction(SPISettings(40000000, MSBFIRST, SPI_MODE0));
digitalWrite(FLASH_CS, LOW);
SPI.transfer(CMD_READ);
SPI.transfer((addr >> 16) & 0xFF); // Address high byte
SPI.transfer((addr >> 8) & 0xFF); // Address mid byte
SPI.transfer(addr & 0xFF); // Address low byte
for (uint32_t i = 0; i < len; i++) {
buf[i] = SPI.transfer(0x00);
}
digitalWrite(FLASH_CS, HIGH);
SPI.endTransaction();
}
// WT588D voice module uses SPI-like serial to Arduino
// SD card for audio: Use SD.h library (uses SPI internally)
// MCP4921 DAC: SPI-controlled DAC for custom audio synthesis
Comprehensive Comparison Table
| Feature | I2C | I2S | SPI |
|---|---|---|---|
| Primary use in audio | Codec config/control | Audio data streaming | File storage/custom DAC |
| Wire count | 2 (SCL+SDA) | 3-4 (SCK+WS+SD+MCLK) | 4 (SCK+MOSI+MISO+CS) |
| Max speed | 3.4MHz (HS) | Up to ~25MHz (384kHz/32b) | Up to 80MHz (ESP32) |
| Multi-device | Yes (addresses) | Limited (daisy-chain) | Yes (CS per device) |
| Full duplex | No (half duplex) | Yes (separate TX/RX pins) | Yes (MOSI+MISO) |
| Audio latency | N/A (control only) | Sample-accurate (DMA) | Variable (software) |
| ESP32 hardware support | 2× I2C ports | 2× I2S ports | 4× SPI ports |
Real-World Use Cases and Device Examples
Typical Audio System: I2C + I2S Together
Most audio codec ICs (WM8960, ES8388, PCM1802) use BOTH I2C and I2S simultaneously:
- I2C: Sends configuration commands at startup (set gain, sample rate, power management)
- I2S: Continuously streams audio data during operation
ESP32 + INMP441 (I2S only)
The INMP441 MEMS microphone has only I2S output — no I2C config needed. It’s hardwired to 24-bit I2S format. This simplicity makes it the easiest digital microphone for ESP32 projects.
WT588D Voice Module (Custom Serial)
The WT588D module uses a proprietary 1-wire serial protocol that resembles SPI but is neither standard SPI nor I2C. This is common with specialized audio playback chips from Chinese manufacturers.
Recommended Product
WT588D-16P Voice/Sound Audio Player Module
Standalone audio player with simple 1-wire interface — contrast with I2S complexity for a practical understanding of different audio interface levels.
Category: Audio & Sound Modules
ESP32 Code Examples for Each Protocol
// ESP32: Using all three protocols in one audio project
// I2C: Configure ES8388 codec
// I2S: Stream audio data from/to ES8388
// SPI: Read MP3 files from SD card
#include <Wire.h>
#include <driver/i2s.h>
#include <SPI.h>
#include <SD.h>
// I2C for codec config
#define I2C_SDA 21
#define I2C_SCL 22
// I2S for audio data
#define I2S_BCLK 26
#define I2S_LRCK 25
#define I2S_DOUT 22 // To codec DAC input
#define I2S_DIN 19 // From codec ADC output
// SPI for SD card
#define SD_CS 5
#define SD_CLK 18
#define SD_MOSI 23
#define SD_MISO 19 // NOTE: may conflict with I2S DIN!
// In real designs, use different pins or SPI/I2S mux
void setup() {
// I2C setup
Wire.begin(I2C_SDA, I2C_SCL);
Wire.setClock(400000);
// Configure codec via I2C
// Wire.beginTransmission(0x10); ... (codec commands)
// I2S setup
i2s_config_t i2s_cfg = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX),
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = 8,
.dma_buf_len = 64
};
i2s_driver_install(I2S_NUM_0, &i2s_cfg, 0, NULL);
// SPI for SD card
SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_CS);
SD.begin(SD_CS);
Serial.println("I2C + I2S + SPI all initialized!");
}
void loop() {
// Read audio samples from SD (SPI) → send via I2S to codec
// Microphone via I2S → process → SD card (SPI)
}
Recommended Product
AI Thinker ESP32-A1S Audio Development Board
All-in-one board using all three protocols (I2C codec config + I2S audio data + SPI SD card) — ideal learning platform to understand protocol roles in a real audio system.
Category: Audio & Sound Modules
Frequently Asked Questions
Q: Can I use I2C to send audio data if I2S isn’t available?
A: Technically possible at very low quality. 400kHz I2C can carry approximately 8kHz/8-bit mono audio (minimum telephone quality) after protocol overhead. But I2C adds 8-bit addressing overhead per transaction and lacks the word-aligned synchronous streaming that audio requires. I2S at 44.1kHz/16-bit stereo needs 1.41MHz bit clock — far beyond I2C Fast Mode. Use I2S for audio always.
Q: What’s the difference between I2S and TDM (Time Division Multiplexing)?
A: TDM is an extension of I2S that carries more than 2 audio channels on a single data line. Instead of Left/Right only, TDM frames can carry 4, 8, 16 or more channels. Used in professional audio interfaces and multi-channel codecs. ESP32 I2S hardware supports TDM mode for multi-channel audio processing.
Q: Why does ESP32 I2S sometimes produce crackling audio?
A: Common causes: (1) DMA buffer underrun — increase dma_buf_count to 16, (2) CPU competing with I2S task — use FreeRTOS task pinned to Core 0, (3) WiFi interference on ESP32 ADC2 — use ADC1 pins only, (4) Sample rate mismatch — ensure APLL is enabled (use_apll=true), (5) Power supply noise — add 100µF + 100nF bypass caps on 3.3V line near I2S device.
Q: Can Arduino Uno use I2S?
A: Arduino Uno lacks hardware I2S. Software I2S is possible using bit-banging but produces very limited sample rates (max ~40kHz bit clock = 1.25kHz/16-bit mono — barely audible). For I2S audio, use ESP32 (hardware I2S), STM32 (SAI peripheral), or SAMD51 (I2S peripheral). ESP32 is the recommended choice for Indian hobbyists.
Q: Which protocol does Bluetooth audio use internally?
A: Bluetooth audio chips receive BT audio streams and output them via I2S to connected codecs/amplifiers. The Bluetooth A2DP protocol carries compressed audio (SBC, AAC, aptX) over RF; the chip decompresses it and outputs PCM audio via I2S to a DAC or amplifier. I2C is used to configure the BT chip. So all three protocols work together in a Bluetooth speaker.
Add comment