2. Codec 硬件架构:从框图到总线协议
做音频系统这么多年,我拆过不少 Codec 的数据手册。说实话,刚入行那会儿看内部框图,总觉得眼花缭乱——又是 ADC 又是混音器,还有一堆看不懂的开关矩阵。后来自己画板子、调驱动,才慢慢摸清楚每个模块到底在干嘛。
这一章,咱们就把 Codec 的硬件架构掰开揉碎。你跟着我走一遍,保证以后看任何 Codec 的 datasheet 都不怵。
2.1 音频 Codec 内部框图核心模块
先看一张典型的音频 Codec 内部结构。我习惯把它分成四个功能区:模拟前端、数字核心、时钟管理和控制接口。
核心要点:Codec 的本质是模拟世界和数字世界之间的桥梁。一边是麦克风、喇叭这些模拟器件,另一边是 I2S、TDM 这些数字总线。中间所有模块,都是为了把信号干净地搬过去。
2.2 ADC 与 DAC:信号转换的核心
ADC 和 DAC 是 Codec 的心脏。我见过不少工程师只关心采样率和位数,却忽略了转换器的动态范围和信噪比。这两个参数直接决定了你的音频底噪有多干净。
| 参数 | ADC(模数转换) | DAC(数模转换) |
|---|---|---|
| 核心指标 | SNR、THD+N、动态范围 | SNR、THD+N、输出摆幅 |
| 常见架构 | Sigma-Delta、SAR | Sigma-Delta、R-2R |
| 采样率范围 | 8kHz ~ 384kHz | 8kHz ~ 384kHz |
| 位深 | 16bit / 24bit / 32bit | 16bit / 24bit / 32bit |
我的经验:选型时别只看位数。24bit 的 ADC 如果 SNR 只有 90dB,还不如一颗 16bit 但 SNR 做到 100dB 的芯片。我在一个车载项目里就吃过这个亏——选了高位数低 SNR 的片子,结果底噪怎么都压不下去。
2.3 PGA 与混音器:模拟域的精细控制
PGA(可编程增益放大器)这东西,说白了就是给模拟信号做音量调节。但要注意,它是在模拟域完成的,不像数字音量调节那样会损失精度。
我习惯把 PGA 的增益范围分成三段:
- 低增益区(-12dB ~ 0dB):适合 LINE IN 信号,防止削波
- 中增益区(0dB ~ +20dB):麦克风信号常用,我一般设在 +12dB 左右
- 高增益区(+20dB ~ +60dB):驻极体麦克风或远场拾音才用,噪声也会被放大
混音器呢?它负责把多路音频信号叠加到一起。有些 Codec 的混音器在模拟域,有些在数字域。我个人更倾向数字域混音——灵活,而且不会引入模拟噪声。
注意:混音器叠加信号时,一定要留意溢出。两个 0dB 信号叠加,数字域会变成 +6dB,直接削波。我见过有人调了半天音质都破,最后发现是混音器增益没配好。
2.4 时钟管理:Codec 的节拍器
时钟管理这块,说实话,是 Codec 调试里最容易出问题的地方。Codec 需要三个时钟:MCLK(主时钟)、BCLK(位时钟)和LRCLK(帧时钟)。
它们的关系很简单:
- MCLK 是 Codec 内部 PLL 的参考源,频率通常是采样率的 256 倍或 512 倍
- BCLK 决定每一位数据的传输速率,BCLK = 采样率 × 位深 × 通道数
- LRCLK 就是采样率本身,左声道高电平,右声道低电平
举个例子:48kHz 采样率、24bit 立体声,BCLK = 48k × 24 × 2 = 2.304MHz。MCLK 如果是 256fs,那就是 12.288MHz。
避坑指南:我曾经在一个项目里,MCLK 和 BCLK 的相位关系没对齐,导致 Codec 偶尔出现爆音。查了两天才发现是时钟源抖动太大。后来我习惯在 MCLK 路径上加一个 RC 滤波,问题就解决了。
2.5 I2S / PCM / TDM 总线协议详解
这部分是 Codec 和 SoC 通信的命脉。三种协议本质上都是串行音频总线,但适用场景不同。
2.5.1 I2S 协议
I2S 是飞利浦搞的标准,三根线:BCLK、LRCLK、DATA。数据在 BCLK 的上升沿采样,LRCLK 高电平传左声道,低电平传右声道。数据从 MSB 开始传输,紧跟在 LRCLK 切换之后。
你想想看,为什么 I2S 这么流行?因为它简单。三根线就能传立体声音频,而且时序清晰,几乎所有的 SoC 都支持。
// I2S 时序示例(48kHz, 24bit)
// LRCLK 高电平 = 左声道, 低电平 = 右声道
// 数据在 BCLK 上升沿采样
LRCLK ┌──────────────────────┐ ┌──────
│ │ │
└──────────────────────┘─────────┘
BCLK ┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐
└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘
DATA ── MSB ── ... ── LSB ── MSB ── ...
← 左声道 24bit → ← 右声道 24bit →
2.5.2 PCM 协议
PCM 和 I2S 很像,但有个关键区别:PCM 的帧同步信号是短脉冲,不是 I2S 那种电平切换。PCM 常用于语音通信,比如蓝牙免提、VoIP 网关。
我记得有一次调试蓝牙通话,Codec 死活不出声。查了半天,发现是 SoC 配成了 I2S 模式,但 Codec 默认是 PCM 模式。帧同步信号一个用电平、一个用脉冲,根本对不上。
| 特性 | I2S | PCM | TDM |
|---|---|---|---|
| 帧同步方式 | 电平(高/低) | 短脉冲 | 帧同步脉冲 |
| 通道数 | 2(立体声) | 1~2 | 2~16 |
| 典型应用 | Hi-Fi 音频 | 语音通信 | 多通道音频 |
| 数据对齐 | MSB 对齐 | MSB 或 LSB | 时隙对齐 |
2.5.3 TDM 协议
TDM 是 I2S 的扩展版。它把多个通道的数据塞进同一个数据线上,每个通道分配一个固定的时隙。比如 8 通道 TDM,一个帧周期里就有 8 个时隙,每个时隙传一个通道的数据。
做多麦克风阵列的时候,TDM 几乎是唯一选择。我做过一个 4 麦克风阵列的项目,用 TDM 模式一根数据线就搞定了,省了不少 GPIO。
配置建议:用 TDM 时,一定要确认 SoC 和 Codec 的时隙对齐方式。有些芯片时隙从 BCLK 的第一个上升沿开始,有些从第二个开始。差一个 BCLK,整个数据就全乱了。
2.6 控制接口:I²C 与 SPI
Codec 的寄存器配置靠 I²C 或 SPI。我个人更习惯用 I²C,因为只需要两根线(SCL、SDA),而且大多数 SoC 都有硬件 I²C 控制器。
但 SPI 也有优势——速度快。如果你需要频繁更新 Codec 的滤波器系数,SPI 的吞吐量比 I²C 高一个数量级。
// I²C 写 Codec 寄存器示例(伪代码)
// 设备地址:0x1A(7bit)
// 寄存器地址:0x10(PGA 增益控制)
// 写入值:0x0C(+12dB)
i2c_start();
i2c_write(0x1A << 1 | 0); // 设备地址 + 写标志
i2c_write(0x10); // 寄存器地址
i2c_write(0x0C); // 写入数据
i2c_stop();
注意:I²C 的时序要求很严格。上拉电阻选不对,或者总线电容太大,都可能导致通信失败。我建议上拉电阻选 4.7kΩ,总线长度控制在 10cm 以内。
好了,Codec 的硬件架构和总线协议就聊到这儿。这些内容看起来琐碎,但每一条都是我踩过坑之后总结出来的。你把这些吃透了,后面调驱动、写算法的时候,心里就有底了。