4. I2S总线协议:数字音频的“高速公路”

做音频嵌入式开发,I2S 是你绕不开的协议。说白了,它就是数字音频芯片之间传数据的标准接口。我最早接触 I2S 是在一个便携播放器项目里,当时 Codec 和 MCU 之间老是对不上声音,查了半天才发现是左右对齐模式配错了。从那以后,我对 I2S 的时序就格外上心。

这一节,咱们就把 I2S 的物理层、时序、三种常见模式、TDM 以及时钟关系彻底讲透。

4.1 物理层与信号线

I2S 总线通常只需要 3 根核心信号线,外加一根可选的主时钟线。你想想看,比起并行接口,这布线省了多少事。

信号线 全称 作用
SCK Serial Clock (位时钟) 每个脉冲传输 1 bit 数据
WS Word Select (帧时钟) 区分左/右声道,高电平=左声道,低电平=右声道
SD Serial Data 数据线,串行传输音频采样值
MCLK Master Clock (主时钟) 可选,用于 Codec 内部 PLL 或 Σ-Δ 调制器
我的习惯:只要 Codec 支持,我尽量把 MCLK 加上。虽然多一根线,但能大幅降低对 SCK 的抖动要求,音质更干净。

4.2 标准 I2S 时序

标准 I2S 的时序有个关键特征:WS 在 SCK 的下降沿之后变化,而数据在 SCK 的上升沿被采样。这样做的好处是,数据有半个 SCK 周期的建立时间,对接收端更友好。

我画了一张时序图,帮你把信号关系看清楚:

标准 I2S 时序图 标准 I2S 时序(16位数据,左声道对齐) SCK WS 左声道 (高) 右声道 (低) SD MSB LSB WS 变化点 标准 I2S 特点:WS 在 SCK 下降沿后变化,数据在 SCK 上升沿采样 MSB 先传,且 MSB 在 WS 变化后的第二个 SCK 上升沿有效

注意看,WS 变化后,数据线并不会立即送出 MSB,而是延迟一个 SCK 周期。这是标准 I2S 和左对齐模式最大的区别。我刚开始做的时候没注意这个细节,结果左右声道数据串位了,排查了好久。

4.3 三种数据对齐模式

实际项目中,你会发现 I2S 设备并不都按标准时序来。常见的还有左对齐和右对齐模式。我整理了一张对比表:

模式 MSB 位置 WS 与数据关系 常见场景
标准 I2S WS 变化后第 2 个 SCK WS 变化后延迟 1 SCK 飞利浦协议,最通用
左对齐 WS 变化后第 1 个 SCK WS 变化同时开始传数据 日本厂商 Codec,如 AKM
右对齐 数据帧末尾对齐 LSB 对齐到 WS 变化前 旧式 DSP 或特定 Codec
我曾经踩过的坑:在一个 AKM 的 Codec 项目里,我默认用了标准 I2S 模式,结果声音全是噪声。后来查手册才发现它只支持左对齐。所以拿到新 Codec,第一件事就是确认它支持哪种对齐模式。

4.4 TDM 时分复用模式

当你要接多个 Codec 或者多通道音频时,TDM 就派上用场了。TDM 本质上是在一条数据线上分时传输多个声道的数据。

举个例子,8 通道 TDM 的时序是这样的:

  • WS 不再只是左右声道切换,而是变成帧同步信号
  • 每个 WS 周期内,依次传输 Slot 0 ~ Slot 7
  • 每个 Slot 可以配置为 16/24/32 bit

我参与过一个车载音响项目,用了 8 通道 TDM 来传输 5.1 声道加两个麦克风。一条 SD 线搞定所有,布线简单多了。

TDM 配置要点:

  • Slot 数量必须与通道数匹配
  • 每个 Slot 的位宽要一致
  • WS 频率 = 采样率 × 帧长度(所有 Slot 位宽之和)

4.5 主时钟与位时钟的关系

这是很多初学者容易搞混的地方。MCLK 和 SCK 到底是什么关系?

简单说:MCLK 是 SCK 的整数倍。常见的倍数关系有:

采样率 (fs) 位宽 声道数 SCK MCLK (256×fs) MCLK (384×fs)
48 kHz 16 bit 2 1.536 MHz 12.288 MHz 18.432 MHz
48 kHz 24 bit 2 2.304 MHz 12.288 MHz 18.432 MHz
96 kHz 24 bit 2 4.608 MHz 24.576 MHz 36.864 MHz

你发现没有?MCLK 是固定的 256×fs 或 384×fs,而 SCK 会随位宽变化。这是因为 MCLK 是给 Codec 内部 PLL 用的,它需要稳定的时钟来生成内部调制频率。SCK 则是数据传输时钟,位宽越大,SCK 越高。

我的建议:设计时钟树时,先确定 MCLK 频率,再用分频得到 SCK。很多 MCU 的 I2S 外设都支持 MCLK 输出,省掉一颗外部晶振。

4.6 实际项目中的时钟配置流程

最后,我分享一下我在项目中配置 I2S 时钟的步骤:

  1. 确定采样率 fs:比如 48 kHz
  2. 确定位宽和声道数:比如 24 bit 立体声
  3. 计算 SCK:SCK = fs × 位宽 × 声道数 = 48k × 24 × 2 = 2.304 MHz
  4. 选择 MCLK 倍数:常用 256×fs = 12.288 MHz
  5. 配置 MCU 时钟分频器:确保 MCLK 和 SCK 是整数倍关系
  6. 验证时序:用示波器看 WS 是否等于 fs,SCK 是否稳定

嗯,这一步验证千万别省。我见过有人代码配对了,但 PCB 走线太长导致 SCK 信号变形,Codec 就是不工作。示波器一看,波形都圆了。

核心公式:

SCK = fs × 位宽 × 声道数

MCLK = fs × 倍数(256、384、512 等)

MCLK 必须是 SCK 的整数倍,且倍数 ≥ 2

I2S 协议本身不复杂,但细节决定成败。对齐模式、时钟关系、TDM 配置,每一个点都可能在项目中给你挖坑。把这一节吃透,后面 Codec 驱动开发你会顺手很多。