I2S协议详解:引脚定义与数据格式

I2S,全称 Inter-IC Sound,是数字音频设备之间传输音频数据的串行总线协议。说白了,它就是 Codec 和 SoC 之间“说话”的规矩。我调试过的杂音问题,十有八九都能追溯到 I2S 的时序或格式配置上。

这一节,我们就把 I2S 的引脚定义和三种主流数据格式彻底讲透。你把这些搞明白了,排查杂音时至少能少走一半弯路。

I2S 的四条核心引脚

标准的 I2S 总线只需要四条线。嗯,就这么简单,但每条线的角色必须分清楚。

引脚名称 方向 作用
BCLK (Bit Clock) 主→从 位时钟,每个脉冲对应一个数据位
LRCLK (Left/Right Clock) 主→从 帧时钟,高电平左声道,低电平右声道
DIN (Data In) 从→主 Codec 输出数据给 SoC(录音路径)
DOUT (Data Out) 主→从 SoC 发送数据给 Codec(播放路径)
我的习惯: 画原理图时,我会在 BCLK 和 LRCLK 旁边标注上预期的频率值。比如 48kHz 采样率、16bit 数据、双声道,BCLK 就是 48k × 16 × 2 = 1.536MHz。这个数字记在心里,示波器上一测就知道有没有跑偏。

BCLK 和 LRCLK 的关系

这两个时钟是 I2S 的“心跳”。BCLK 负责节拍,LRCLK 负责区分左右声道。

举个例子:采样率 48kHz,16bit 精度,双声道。那么:

  • LRCLK 频率 = 48kHz(每秒切换 48000 次左右声道)
  • BCLK 频率 = 48k × 16 × 2 = 1.536MHz
  • 每个 LRCLK 周期内,BCLK 的脉冲数 = 32 个(左右各 16 个)

我在项目中遇到过一种情况:Codec 输出的声音像“卡带”一样断断续续。查了半天,发现是 SoC 的 I2S 控制器把 BCLK 配成了 1.5MHz,跟 Codec 要求的 1.536MHz 差了 2.3%。这种微小偏差,人耳听久了就会觉得“声音发飘”。

注意: BCLK 和 LRCLK 必须由同一个时钟源产生。如果 SoC 和 Codec 各自用自己的晶振,哪怕标称值一样,实际频率也会有微小差异。时间长了,数据就会溢出或欠载,产生“咔哒”声。我曾经被这个问题折磨了两天。

标准 I2S 格式

标准 I2S 格式,也叫 Philips 格式,是最常用的。它的核心规则是:数据在 BCLK 的下降沿变化,在上升沿被采样;LRCLK 变化后的第二个 BCLK 上升沿开始传输最高位(MSB)。

为什么是第二个上升沿?因为第一个上升沿留给 LRCLK 的建立时间。这个细节,很多 datasheet 不会明说,但你在示波器上能看得清清楚楚。

// 标准 I2S 时序示意(16bit 数据)
// LRCLK 高 = 左声道,低 = 右声道
// 数据在 BCLK 下降沿变化,上升沿采样

BCLK:   __    __    __    __    __    __    __    __
       |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
LRCLK: |_____|     |_____|     |_____|     |_____|
       | 左声道  |  右声道  |  左声道  |  右声道  |
DIN:   X  MSB ... LSB  X  MSB ... LSB  X  MSB ...
       ^
       |-- 第二个 BCLK 上升沿开始传 MSB
关键点: 标准 I2S 格式下,MSB 不是在 LRCLK 变化后立即出现,而是延迟了一个 BCLK 周期。这个“延迟一位”的特性,是区分标准 I2S 和左对齐格式的核心标志。

左对齐格式(Left-Justified)

左对齐格式,顾名思义,数据跟 LRCLK 的变化“对齐”了。MSB 在 LRCLK 变化后的第一个 BCLK 上升沿就开始传输。

这种格式在早期的音频 Codec 里比较常见。我调试过一款老旧的音频 ADC,它只支持左对齐。当时我按标准 I2S 配的 SoC,结果读出来的数据全是乱的,左声道和右声道的数据混在一起。

// 左对齐格式时序示意
// MSB 在 LRCLK 变化后的第一个 BCLK 上升沿开始

BCLK:   __    __    __    __    __    __    __    __
       |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
LRCLK: |_____|     |_____|     |_____|     |_____|
       | 左声道  |  右声道  |  左声道  |  右声道  |
DIN:   MSB ... LSB  MSB ... LSB  MSB ... LSB  MSB ...
       ^
       |-- 第一个 BCLK 上升沿就开始传 MSB
避坑指南: 我曾经在配置一颗 AKM 的 Codec 时,datasheet 上写的是“I2S compatible”,结果实际用的是左对齐。后来我养成了一个习惯:拿到新 Codec,先看 datasheet 里的时序图,数一数 LRCLK 变化后到 MSB 出现之间有几个 BCLK 周期。一个周期就是左对齐,两个周期就是标准 I2S。

右对齐格式(Right-Justified)

右对齐格式,也叫日本格式或 Sony 格式。它的特点是:数据的 LSB(最低位)跟 LRCLK 的变化边界对齐。也就是说,数据在 LRCLK 周期的末尾才传完。

这种格式对字长要求比较严格。如果 SoC 和 Codec 配置的字长不一致,数据就会错位。比如 SoC 发 16bit 数据,但 Codec 按 24bit 去解析,那 Codec 就会把 SoC 发的数据当成高 16 位,低 8 位补零。结果就是音量变小,而且有底噪。

// 右对齐格式时序示意(16bit 数据)
// LSB 与 LRCLK 变化边界对齐

BCLK:   __    __    __    __    __    __    __    __
       |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
LRCLK: |_____|     |_____|     |_____|     |_____|
       | 左声道  |  右声道  |  左声道  |  右声道  |
DIN:   X  MSB ... LSB  X  MSB ... LSB  X  MSB ...
                                    ^
                                    |-- LSB 跟 LRCLK 变化对齐
注意: 右对齐格式下,如果数据位宽小于 LRCLK 周期内的 BCLK 数,高位会填充 0。比如 16bit 数据放在 32 BCLK 的帧里,前 16 个 BCLK 传的是 0,后 16 个 BCLK 才是有效数据。这个特性在调试时很容易被忽略。

三种格式的对比

特性 标准 I2S 左对齐 右对齐
MSB 起始位置 LRCLK 变化后第 2 个 BCLK LRCLK 变化后第 1 个 BCLK LRCLK 变化后第 1 个 BCLK
LSB 对齐方式 不强制对齐 不强制对齐 与 LRCLK 变化边界对齐
兼容性 最广泛 部分老 Codec Sony/日本厂商常用
调试难度 低 中 高(字长敏感)

用 SVG 理清三种格式的差异

下面这张图,把三种格式的时序差异画在一起。你一看就明白为什么格式配错会导致杂音。

I2S 三种数据格式对比 BCLK 1 2 3 4 5 6 7 8 9 10 11 12 13 14 LRCLK 左声道 右声道 标准 I2S MSB D14 D13 ... LSB 延迟1位 左对齐 MSB D14 D13 ... LSB 立即开始 右对齐 0 0 ...填充0... MSB D14 ... LSB 对齐边界 🔍 调试要点 • 标准 I2S:MSB 延迟 1 个 BCLK,兼容性最好,优先选用 • 左对齐:MSB 立即开始,老 Codec 常见,注意 datasheet 时序图 • 右对齐:LSB 对齐帧边界,字长必须严格匹配,否则音量异常

调试时的实用建议

说了这么多理论,最后给几条实战建议:

  1. 先确认格式:拿到 Codec 的 datasheet,直接翻到 I2S 时序图。数一数 LRCLK 变化后到 MSB 出现之间有几个 BCLK。一个就是左对齐,两个就是标准 I2S。右对齐的话,LSB 位置会标出来。
  2. 示波器看波形:把 BCLK 和 LRCLK 同时抓下来。用光标测量 LRCLK 周期,反推采样率对不对。再用光标量 BCLK 频率,算一下位宽是否匹配。
  3. 数据格式不匹配的典型症状:声音有“金属感”或“机器人声”,通常是 MSB 位置错了。声音变小且有底噪,通常是字长不匹配。左右声道串扰,通常是 LRCLK 极性反了。
  4. 我的习惯:调试新板子时,我会先配成标准 I2S,16bit,48kHz。这是最通用的配置。如果不出声,再逐一排查格式、位宽和时钟极性。不要一上来就调复杂的格式。
总结一句话: I2S 的格式问题,本质上就是“数据位跟时钟边沿的对齐关系”。你把这个对齐关系搞清楚了,90% 的 I2S 相关杂音都能找到根因。