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 在前 |
有些场景还会用到额外的 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、数字音频处理 |
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 可以通过寄存器配置这个极性。
3.6 知识体系总览
下面这张图把 I2S 协议的核心知识点串起来了。你可以把它当作本章的思维导图:
这张图把 I2S 协议的六个核心维度都列出来了。你写代码的时候,可以对照这张图检查配置:总线引脚接对了没?时序模式选对了没?数据位宽和 SCK 周期匹配了没?主从模式设对了没?时钟频率算对了没?