2、I2S总线协议详解:I2S信号定义、数据格式与时序参数
I2S总线,说白了就是数字音频的“高速公路”。你想想看,Codec芯片和主控之间要传音频数据,总得有个规矩。飞利浦在80年代搞出来的这个标准,到现在还是主流。我这些年调过的板子,十块里有八块都在跟I2S打交道。
这一节咱们就把I2S的底裤扒干净。信号怎么走、数据怎么摆、时序怎么算,全给你讲透。
2.1 I2S的三条信号线
I2S总线就三根线,不多不少。我见过不少新手一上来就搞混,其实记清楚各自职责就行。
| 信号 | 全称 | 谁产生 | 干什么用 |
|---|---|---|---|
| BCLK | Bit Clock | 主控或Codec(主模式) | 每个脉冲对应一个数据位 |
| LRCLK | Left/Right Clock | 主控或Codec(主模式) | 区分左声道和右声道 |
| SDATA | Serial Data | 发送方 | 承载音频采样数据 |
关键点:BCLK和LRCLK必须由同一个设备产生。我曾经在一个项目里让主控产生BCLK、Codec产生LRCLK,结果波形乱成一锅粥。嗯,那次debug花了我整整两天。
2.1.1 BCLK——位时钟
BCLK的频率直接决定了你能传多高规格的音频。公式很简单:
BCLK频率 = 采样率 × 位深 × 声道数
举个例子,CD音质(44.1kHz、16bit、立体声):
BCLK = 44100 × 16 × 2 = 1.4112 MHz
如果是192kHz、24bit、立体声:
BCLK = 192000 × 24 × 2 = 9.216 MHz
我建议你选主控的时候,先算算BCLK能不能跑上去。有些低端MCU的I2S模块,BCLK上限就8MHz,硬要跑192kHz/24bit就会翻车。
2.1.2 LRCLK——帧时钟
LRCLK的频率就等于采样率。左声道为低电平,右声道为高电平(标准I2S是这样,但有些芯片会反过来,看数据手册最稳)。
这里有个坑:LRCLK的占空比不一定是50%。我见过一些Codec要求LRCLK高电平至少占32个BCLK周期,否则右声道数据会丢。你想想看,如果位深是24bit,但LRCLK高电平只给了16个BCLK,那右声道的后8位就没了。
注意:LRCLK的跳变沿必须和BCLK对齐。如果两者之间有skew(偏斜),数据采样就会出错。我建议PCB走线时,BCLK和LRCLK等长,误差控制在5mm以内。
2.1.3 SDATA——数据线
SDATA上跑的是串行二进制数据。标准I2S格式下,数据在BCLK的上升沿被采样,MSB(最高有效位)最先发送。
数据位的有效范围取决于位深。比如16bit数据,只有高16位有效,低8位(如果有的话)会被忽略。我遇到过有人把24bit数据塞进16bit的I2S配置里,结果声音全是噪声——说白了就是高位被截断了。
2.2 I2S数据格式
I2S有三种主流数据格式:标准I2S、左对齐、右对齐。很多Codec都支持配置,但默认通常是标准I2S。
| 格式 | 数据与LRCLK的关系 | 典型应用 |
|---|---|---|
| 标准I2S | 数据在LRCLK跳变后延迟1个BCLK开始 | 绝大多数Codec |
| 左对齐 | 数据在LRCLK跳变时立即开始 | 一些DSP、老式Codec |
| 右对齐 | 数据对齐到LRCLK周期的末尾 | I2S兼容模式、部分ADC |
2.2.1 标准I2S格式
这是最常用的格式。数据在LRCLK跳变后的第二个BCLK上升沿开始传输。为什么延迟1个BCLK?说白了就是为了让接收方有足够时间识别声道变化。
LRCLK: __|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|__________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|__
BCLK: _‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_
SDATA: XXX|MSB|...|...|...|LSB|XXX|MSB|...|...|...|LSB|XXX
↑延迟1BCLK后开始
我习惯用逻辑分析仪抓I2S波形时,先看LRCLK跳变后第一个BCLK是不是空位。如果是,那就是标准I2S没跑了。
2.2.2 左对齐格式
左对齐格式下,数据在LRCLK跳变的同时就开始传输。没有那个延迟位。这种格式在DSP芯片里比较常见。
LRCLK: __|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|__________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|__
BCLK: _‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_‾|_
SDATA: MSB|...|...|...|LSB|XXX|MSB|...|...|...|LSB|XXX
↑立即开始
小技巧:如果你的主控和Codec都支持多种格式,我建议统一用标准I2S。兼容性最好,踩坑最少。左对齐格式我只有在DSP强制要求时才用。
2.2.3 右对齐格式
右对齐格式比较特殊。数据不是从帧开头开始,而是对齐到帧的末尾。比如16bit数据在32BCLK的帧里,数据从第17个BCLK才开始传。
这种格式在I2S兼容模式下有用。有些老式Codec只支持右对齐,你主控如果配成标准I2S,声音就会完全不对。我曾经被一个AKM的Codec坑过,数据手册写的是“I2S compatible”,结果默认是右对齐。嗯,那次浪费了三个小时。
2.3 时序参数与采样率关系
时序参数是I2S调试的重灾区。很多问题都是时序不满足导致的。
| 参数 | 符号 | 说明 | 典型值 |
|---|---|---|---|
| BCLK周期 | T_bclk | BCLK一个完整周期的时间 | 取决于采样率 |
| BCLK高电平时间 | T_high | BCLK高电平持续时间 | ≥ T_bclk/2 - 抖动 |
| 数据建立时间 | T_setup | 数据在BCLK上升沿前必须稳定 | ≥ 10ns(典型) |
| 数据保持时间 | T_hold | 数据在BCLK上升沿后必须保持 | ≥ 5ns(典型) |
| LRCLK到BCLK偏斜 | T_skew | LRCLK跳变与BCLK跳变的时间差 | ≤ 10ns |
采样率决定了BCLK频率,BCLK频率又决定了你能容忍的最大时序误差。举个例子:
- 44.1kHz/16bit/立体声:BCLK=1.4112MHz,周期≈709ns。时序余量很大,随便拉根杜邦线都能跑。
- 192kHz/24bit/立体声:BCLK=9.216MHz,周期≈108ns。这时候PCB走线稍微长一点,反射和串扰就可能让你丢数据。
- 384kHz/32bit/立体声:BCLK=24.576MHz,周期≈40ns。嗯,到这个级别,我建议你用差分I2S或者干脆上TDM。
避坑指南:我曾经在一个项目里用飞线连接Codec和主控,跑48kHz没问题,一上96kHz就爆音。用示波器一量,BCLK波形已经圆得不像话了。后来改成PCB走线,问题解决。高频I2S,走线长度别超过5cm,尽量加串联电阻(22Ω左右)抑制过冲。
2.4 I2S知识体系总览
下面这张图把I2S的核心知识点串起来了。你可以把它当作调试时的快速参考。
2.5 调试时的实用建议
最后给几条我自己的经验,希望能帮你少走弯路:
- 先确认主从模式:主控和Codec谁产生BCLK和LRCLK,必须明确。两边都配成主模式,总线就打架了。
- 用逻辑分析仪抓波形:别光看数据手册。实际抓一下BCLK频率对不对、LRCLK占空比是否正常、SDATA数据格式是否匹配。
- 注意电平标准:I2S通常是3.3V,但有些Codec用1.8V。电平不匹配,轻则数据错误,重则烧芯片。
- 预留测试点:PCB设计时,BCLK、LRCLK、SDATA各留一个测试点。调试时直接焊线抓波形,省事很多。
我的习惯:每次拿到新Codec的板子,第一件事就是用示波器看BCLK和LRCLK的波形。频率对不对、上升沿陡不陡、有没有抖动,一眼就能看出问题。别急着写驱动,先把物理层搞定。