3、I2S协议基础:从物理层到数据格式

说实话,I2S 这玩意儿在音频领域太常见了。我最早接触它是在做一款智能音箱的项目,当时被时序图搞得晕头转向。后来调通了才发现,I2S 其实没那么玄乎——它就是专门为音频数据设计的一种串行总线协议。

这一章,咱们把 I2S 的底裤扒干净。从总线定义、时序标准、数据格式,到主从模式和时钟关系,一个一个说清楚。

3.1 I2S 总线定义:三条线就够了

I2S 总线全称 Inter-IC Sound,是飞利浦(现 NXP)在 1986 年提出的。它专门用来连接音频编解码器和数字信号处理器。你想想看,音频数据是连续的流,不像 I2C 那样需要地址和应答,所以 I2S 的引脚非常精简。

标准 I2S 接口只需要三根信号线:

信号名 全称 作用
SCK Serial Clock(位时钟) 每个脉冲对应一位数据,频率 = 采样率 × 位宽 × 通道数
WS Word Select(帧时钟/左右声道选择) 高电平表示右声道,低电平表示左声道(飞利浦标准)
SD Serial Data(串行数据) 音频数据按位传输,MSB 在前
个人习惯: 我画 PCB 时喜欢把这三根线走等长,尤其是 SCK 和 SD。虽然 I2S 频率通常不高(几 MHz),但等长布线能减少数据建立时间的抖动。曾经有个项目因为 SCK 走线长了 2cm,导致高采样率下数据错位,查了我一整天。

有些场景还会用到额外的 MCLK(主时钟),比如 WM8960 这类音频芯片。MCLK 一般是 SCK 的整数倍,用于内部数字滤波和时钟同步。这个后面讲 WM8960 配置时会细说。

3.2 飞利浦 I2S 标准时序

飞利浦标准时序是 I2S 最常用的模式。它的核心规则就一条:WS 变化后,SD 在 SCK 的第二个上升沿开始传输数据。

为什么不是第一个上升沿?我当年也纳闷。后来看了飞利浦的原始文档才明白——WS 变化后留出一个 SCK 周期,是为了给发送端足够的时间准备数据。说白了,就是时序余量。

来看一个典型的时序图:

飞利浦 I2S 标准时序要点:

  • WS 在 SCK 的下降沿变化
  • SD 在 WS 变化后的第二个 SCK 上升沿开始传输
  • 数据从 MSB(最高位)开始传输
  • 数据在 SCK 上升沿被接收端锁存
  • WS 变化前,最后一个 SCK 下降沿传输 LSB(最低位)

嗯,这里要注意:WS 的切换时机是在 SCK 下降沿,而不是上升沿。这个细节很容易被忽略。我见过有人用逻辑分析仪抓数据,发现 WS 和 SD 总是差半个周期,其实就是没搞懂这个下降沿切换的规则。

3.3 数据格式:16/24/32 位

I2S 支持多种数据位宽。常见的就三种:16 位、24 位、32 位。但这里有个坑——数据位宽和 SCK 周期数不一定相等。

举个例子:

  • 16 位数据 + 16 位 SCK 周期:最标准,每个声道 16 个 SCK 脉冲
  • 24 位数据 + 32 位 SCK 周期:数据占 24 位,后面补 8 个 0(零填充)
  • 32 位数据 + 32 位 SCK 周期:全用满,常见于高端音频设备

为什么会有这种不对等?因为很多音频芯片内部处理是 24 位的,但为了兼容 32 位总线,就把数据左对齐放在 32 位槽里。WM8960 就支持这种模式。

数据格式 SCK 周期/声道 有效数据位 填充位 常见场景
16 位标准 16 16 0 CD 音质、低功耗设备
24 位左对齐 32 24 8(低 8 位补 0) 专业音频、WM8960 常用
32 位标准 32 32 0 高端 DAC、数字音频处理
我曾经踩过的坑: 用 STM32 的 I2S 外设发送 24 位数据时,如果配置成 16 位数据帧格式,高 8 位会被截掉。声音听起来就像隔着一层纱——高频细节全没了。后来我查了 RM(参考手册)才发现,STM32 的 I2S 数据寄存器是 32 位的,但帧格式必须和外设配置一致。

3.4 主从模式:谁控制时钟?

I2S 通信中,主设备负责产生 SCK 和 WS 时钟信号,从设备则被动接收或发送数据。

在 STM32 + WM8960 的典型配置中:

  • STM32 做主设备:产生 SCK 和 WS,WM8960 做从设备。这是最常见的方案,时钟控制权在 MCU 手里。
  • WM8960 做主设备:由音频芯片产生时钟,STM32 做从设备。这种模式适合需要精确音频时钟的场景,比如录音时避免时钟抖动。
  • 外部晶振做主时钟源:WM8960 内部 PLL 锁定外部 MCLK,再输出 SCK 和 WS。这种模式最稳定,但硬件成本稍高。

我个人建议初学者先用 STM32 做主设备。原因很简单——调试方便。你可以用逻辑分析仪直接抓 STM32 输出的时钟,确认频率对不对。如果让 WM8960 做主设备,一旦时钟不对,你都不知道是配置问题还是硬件问题。

3.5 帧时钟与位时钟的关系

这两个时钟是 I2S 的核心。搞懂它们的关系,I2S 就算入门了。

  • 位时钟(SCK):频率 = 采样率 × 位宽 × 通道数。比如 44.1kHz 采样率、16 位数据、双声道:SCK = 44.1k × 16 × 2 = 1.4112 MHz。
  • 帧时钟(WS):频率 = 采样率。44.1kHz 采样率下,WS 就是 44.1 kHz。WS 的每个周期对应一个声道的数据帧。

说白了,WS 是 SCK 的分频结果。分频系数 = SCK 频率 ÷ WS 频率 = 位宽 × 通道数。

举个例子:

  • 16 位立体声:SCK 频率是 WS 的 32 倍(16 × 2)
  • 24 位立体声(32 位槽):SCK 频率是 WS 的 64 倍(32 × 2)
  • 32 位立体声:SCK 频率是 WS 的 64 倍(32 × 2)

这里有个容易混淆的地方:WS 的占空比不一定是 50%。飞利浦标准中,WS 在左声道期间为低电平,右声道期间为高电平。但有些芯片(比如某些日本厂商的)会把左右声道反过来。WM8960 可以通过寄存器配置这个极性。

调试技巧: 用示波器同时抓 SCK 和 WS。如果 WS 的上升沿和下降沿都对齐 SCK 的下降沿,说明时序是对的。如果 WS 变化在 SCK 上升沿,那可能就是配置成了其他 I2S 模式(比如左对齐或右对齐模式)。

3.6 知识体系总览

下面这张图把 I2S 协议的核心知识点串起来了。你可以把它当作本章的思维导图:

I2S 协议知识体系 I2S 协议 总线定义 SCK(位时钟) WS(帧时钟/声道选择) SD(串行数据) 飞利浦标准时序 WS 下降沿变化,MSB 先传 数据在 SCK 上升沿锁存 WS 变化后第 2 个 SCK 开始 数据格式 16 位(16 SCK 周期) 24 位(32 SCK 周期) 32 位(32 SCK 周期) 主从模式 主设备:产生 SCK 和 WS 从设备:被动收发数据 时钟关系 SCK = 采样率 × 位宽 × 通道数 WS = 采样率(SCK 分频) 常见配置 STM32 主 + WM8960 从 外部 MCLK + PLL 同步

这张图把 I2S 协议的六个核心维度都列出来了。你写代码的时候,可以对照这张图检查配置:总线引脚接对了没?时序模式选对了没?数据位宽和 SCK 周期匹配了没?主从模式设对了没?时钟频率算对了没?