- I²S(Inter-IC Sound) 是一种专用于数字音频传输的串行总线标准,广泛用于微控制器(如 ESP32)与音频 DAC(如 PCM5102)之间传输音频数据。
I2S 主要信号线
信号线名称 | 全称/别名 | 功能描述 |
---|---|---|
BCLK | Bit Clock / SCK | 每一位数据的时钟,用于数据同步 |
LRCLK | Left-Right Clock / WS | 左右声道选择,High 表示右声道,Low 表示左声道 |
DATA | Serial Data / SD / DIN | 音频的实际数据流 |
MCLK | Master Clock (可选) | 主系统时钟(部分 DAC 可不接,PCM5102 内置 PLL 可省略) |

上传 wav到 SPIFFS(Thonny)
- 打开
视图 > 文件
- 拖拽
***.wav
到 MicroPython 设备(根目录) - 等待上传成功

python函数接口说明
python
# https://github.com/micropython/micropython/blob/master/ports/esp32/machine_i2s.c
from machine import I2S, Pin
audio = I2S(
0,
sck=Pin(9),
ws=Pin(10),
sd=Pin(11),
mode=I2S.TX,
bits=16,
format=I2S.STEREO,
rate=16000,
ibuf=40000
)
函数/参数 | 说明 |
---|---|
I2S(id, **kwargs) |
创建 I2S 对象。id 一般为 0 或 1 ,参数通过关键字传入。 |
id |
I2S 外设编号。ESP32 通常支持 0 或 1 (部分板子支持 2 )。 |
sck / bck |
Bit Clock(位时钟)引脚,接到 DAC 的 BCK 引脚。 |
ws / lrck |
Word Select / LRCK 引脚,接到 DAC 的 LCK 引脚。 |
sd |
Serial Data,引脚接到 DAC 的 DIN 。 |
mode |
I2S.TX (发送)或 I2S.RX (接收)。 |
bits |
采样精度,常用值为 16 、24 、32 。需与 WAV 文件位深一致。 |
format |
通道格式:I2S.MONO 或 I2S.STEREO 。 |
rate |
采样率(Hz),例如 16000、44100、48000 等。需与音频文件一致。 |
ibuf |
内部缓冲区大小(字节),越大越平稳但占用 RAM。 |
CODE实现
c
from machine import Pin, I2S
import ustruct
import time
# ======== 配置 I2S ========
SCK_PIN = 9 # Bit Clock (BCK)
WS_PIN = 10 # Word Select (LRCK)
SD_PIN = 11 # Data (DIN)
audio_out = I2S(
0, # I2S peripheral ID
sck=Pin(SCK_PIN),
ws=Pin(WS_PIN),
sd=Pin(SD_PIN),
mode=I2S.TX,
bits=16,
format=I2S.STEREO, # I2S.STEREO 或 I2S.MONO,取决于 WAV 文件
rate=16000, # 与音频采样率一致
ibuf=40000
)
# ===========================
# # ======== 解析 WAV 头部并跳过 ========
# def skip_wav_header(f):
# # 跳过 WAV 文件头部,找到数据段
# while True:
# chunk_id = f.read(4)
# if chunk_id == b'data':
# data_size = ustruct.unpack('<I', f.read(4))[0]
# return data_size
# else:
# f.read(ustruct.unpack('<I', f.read(4))[0])
import ustruct
def skip_wav_header(f):
# Read RIFF header
if f.read(4) != b'RIFF':
raise ValueError('Invalid WAV file: missing RIFF')
f.read(4) # Chunk size
if f.read(4) != b'WAVE':
raise ValueError('Invalid WAV file: missing WAVE')
# Search for 'data' chunk
while True:
chunk_id = f.read(4)
if len(chunk_id) < 4:
raise ValueError("Reached end of file before finding 'data' chunk")
chunk_size_bytes = f.read(4)
if len(chunk_size_bytes) < 4:
raise ValueError("Corrupted WAV file")
chunk_size = ustruct.unpack('<I', chunk_size_bytes)[0]
if chunk_id == b'data':
return chunk_size # return data size
else:
# skip over this chunk
f.read(chunk_size)
# ======== 播放 WAV 文件 ========
wav_file = "/music-16k-16bits-mono.wav"
with open(wav_file, "rb") as f:
# header = f.read(44) # 假设标准 44 字节 WAV header
# data_size = skip_wav_header(f)
# print("Data size:", data_size)
data_size = skip_wav_header(f) # 不要再提前读 44 字节
print("Data size:", data_size)
# 循环读取并播放音频数据
while True:
wav_data = f.read(1024)
if not wav_data:
break
audio_out.write(wav_data)
# ======== 释放 I2S ========
audio_out.deinit()