2. I2S协议详解:I2S总线标准、数据格式、主从模式配置、时钟关系

各位同学,咱们今天聊聊I2S。说实话,在嵌入式音频开发里,I2S协议是绕不开的坎。我最早接触I2S是在做一款POS机的语音播报模块,那时候被时钟关系搞得晕头转向,后来踩了几个坑才算真正搞明白。今天我把这些经验掰开揉碎了讲给你听。

2.1 I2S总线标准——三条线搞定音频传输

I2S总线,说白了就是专门为数字音频设备之间传输数据而设计的。它不像I2C那样需要地址寻址,也不像SPI那样可以全双工随意传。I2S就干一件事——把音频数据从左声道、右声道轮流送出去。

标准I2S总线有三条核心信号线:

  • BCLK(位时钟):也叫串行时钟SCK。每一个脉冲对应一个数据位。我习惯叫它“节拍器”,它打一拍,数据线就送一个bit。
  • LRCK(左右声道时钟):也叫帧时钟WS。它决定当前数据属于左声道还是右声道。高电平通常是左声道,低电平是右声道(也有反的,看具体芯片)。
  • SD(串行数据):就是音频数据线,把PCM编码的音频数据串行传出去。

嗯,这里要注意,有些芯片还会多出一条MCLK(主时钟)。MCLK不是I2S标准强制要求的,但很多音频编解码芯片都需要它来做内部时钟同步。我遇到过一块CODEC芯片,不接MCLK死活不出声,查了两天手册才发现是时钟配置问题。

核心要点:I2S是串行总线,数据是一位一位传的。BCLK频率决定了数据传输速率,LRCK频率等于采样率。

2.2 数据格式——左对齐、右对齐、I2S格式

这部分是面试常考题,也是实际开发最容易出bug的地方。三种格式的区别,说白了就是数据相对于LRCK边沿的对齐方式不同。

2.2.1 I2S格式(飞利浦格式)

这是最常用的格式。数据在LRCK变化后的第二个BCLK上升沿开始传输。为什么延迟一个时钟?因为LRCK变化时数据线可能还不稳定,延迟一拍能保证数据可靠。我个人习惯用这种格式,兼容性最好。

2.2.2 左对齐格式

数据在LRCK变化后的第一个BCLK上升沿就开始传。说白了就是“不等待,直接发”。有些DSP芯片默认用这种格式。我曾经在一个项目里,CPU和CODEC一个用I2S格式,一个用左对齐,结果出来的声音全是噪声,调了两天才发现是格式不匹配。

2.2.3 右对齐格式

数据在LRCK变化后的最后一个BCLK周期才开始传。这种格式现在用得少了,主要是为了兼容一些老旧的DAC芯片。

格式 数据起始位置 常见应用
I2S格式 LRCK变化后第2个BCLK 飞利浦CODEC、主流音频芯片
左对齐 LRCK变化后第1个BCLK 部分DSP、ADI芯片
右对齐 LRCK变化后最后1个BCLK 老旧DAC、特定日本芯片

我的经验:拿到一个新芯片,第一件事就是看数据格式配置寄存器。很多芯片支持多种格式,默认值可能不是你想要的。我曾经因为没改默认配置,浪费了一整天。

2.3 主从模式配置——谁说了算?

I2S通信里,必须有一个设备产生BCLK和LRCK时钟信号。这个设备就是主设备,其他设备都是从设备

  • 主模式:自己产生BCLK和LRCK。通常CPU或MCU做主设备,CODEC做从设备。
  • 从模式:接收外部输入的BCLK和LRCK。CODEC通常配置为从模式。

你想想看,如果两个设备都想做主设备,那时钟就打架了。反过来,如果两个都是从设备,没人产生时钟,通信就僵死了。所以配置主从关系是第一步。

我记得有一次调试,CODEC配置成了主模式,CPU也配置成了主模式,结果两个设备都在输出时钟,信号乱成一团。示波器一看,BCLK上两个波形在打架,那叫一个惨烈。

避坑指南:我曾经在STM32上配置I2S外设,默认是主模式。如果CODEC也默认主模式,两个设备都输出时钟,轻则通信失败,重则烧坏IO口。上电前一定先确认主从配置。

2.4 时钟关系——BCLK、LRCK、MCLK怎么算?

这部分是硬骨头,但搞懂了就一通百通。咱们先看公式:

BCLK频率 = 采样率 × 位宽 × 声道数 × 2

举个例子:
采样率 44100Hz,位宽 16bit,立体声(2声道)
BCLK = 44100 × 16 × 2 × 2 = 2.8224 MHz

等等,为什么最后还要乘以2?
因为I2S格式里,每个声道的数据占用了32个BCLK周期(即使位宽只有16bit)。
所以实际计算是:BCLK = 44100 × 32 × 2 = 2.8224 MHz

嗯,这里要注意,很多芯片支持“数据压缩模式”,比如16位数据只占16个BCLK周期。但标准I2S格式下,每个声道固定占32个BCLK周期。我刚开始做的时候没注意这个细节,算出来的BCLK频率总是对不上。

LRCK频率就简单了,直接等于采样率。44100Hz采样,LRCK就是44100Hz。LRCK的占空比通常是50%,高电平左声道,低电平右声道。

MCLK呢?MCLK一般是BCLK的整数倍,常见的有256倍、384倍、512倍。比如采样率44100Hz,MCLK可能是44100 × 256 = 11.2896 MHz。为什么需要MCLK?因为CODEC内部有数字滤波器和Σ-Δ调制器,需要更高频率的时钟来工作。

采样率 位宽 BCLK MCLK(256倍)
44100 Hz 16 bit 2.8224 MHz 11.2896 MHz
48000 Hz 16 bit 3.072 MHz 12.288 MHz
96000 Hz 24 bit 6.144 MHz 24.576 MHz

核心公式:BCLK = 采样率 × 每个声道的BCLK数 × 声道数。标准I2S下每个声道固定32个BCLK。MCLK = BCLK × 倍数(256/384/512等)。

2.5 实战中的时钟配置建议

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

  1. 先看手册:每个CODEC芯片对MCLK的要求不一样。有的需要MCLK是采样率的256倍,有的需要384倍。别想当然。
  2. 用示波器量:配置好之后,用示波器抓BCLK和LRCK的波形。看频率对不对,看相位关系对不对。我每次调I2S必做这步。
  3. 注意时钟抖动:如果MCLK是从PLL分频出来的,抖动可能会影响音频质量。高端音频应用建议用独立晶振。
  4. 主从模式别搞反:这个前面说过了,再强调一遍——上电前确认主从配置。

好了,I2S协议的核心内容就这些。下一章咱们会讲如何在Linux下配置I2S控制器,以及如何用ALSA驱动来操作音频设备。到时候我会拿一个真实的POS机音频模块案例来演示,敬请期待。

小技巧:如果你不确定BCLK频率算得对不对,可以用一个简单方法验证——BCLK频率除以LRCK频率,结果应该是声道数乘以每个声道的BCLK数。比如立体声16位标准I2S,这个比值应该是64。如果算出来不是64,那肯定哪里算错了。