2. 音频基础
各位好,欢迎来到第二章。上一章我们聊了WM8960能做什么,这一章咱们把它的「四肢」和「神经」拆开看看。说白了,你要让这颗芯片干活,得先搞清楚三件事:音频数据怎么走(I2S)、控制命令怎么发(I2C)、以及它怎么才能正常醒来工作(电源和时钟)。
我个人习惯,拿到一个新芯片,先看它的接口框图。WM8960的引脚不算多,但每个脚都有讲究。咱们一个一个来。
I2S音频总线协议:音频数据的「高速公路」
WM8960支持标准的I2S接口,也支持左对齐和右对齐格式。但实际项目中,99%的情况都用I2S。为什么?因为STM32的SAI和I2S外设原生支持的就是I2S协议,省事。
I2S总线就四根线:
- BCLK(位时钟)—— 每个音频数据位对应一个脉冲。采样率48kHz、16位双声道时,BCLK = 48k × 16 × 2 = 1.536MHz。
- LRCK(左右声道时钟)—— 也叫帧时钟。高电平传左声道,低电平传右声道(或者反过来,看配置)。频率等于采样率。
- DIN(数据输入)—— 从STM32发给WM8960,用于播放。
- DOUT(数据输出)—— 从WM8960发给STM32,用于录音。
关键点:WM8960的I2S接口可以配置为主模式或从模式。主模式下,BCLK和LRCK由WM8960内部产生;从模式下,这两个时钟由外部(比如STM32)提供。我建议新手先用从模式,让STM32做主时钟源,调试起来更可控。
我在项目中遇到过一个问题:I2S的BCLK频率算错了,导致声音变调。你想想看,如果BCLK比标准值快了0.1%,人耳可能听不出来,但如果快了1%,那声音就像磁带快放一样。所以时钟精度很重要。
WM8960的I2S时序参数在数据手册里有详细表格,我挑几个关键的列出来:
| 参数 | 最小值 | 典型值 | 最大值 | 说明 |
|---|---|---|---|---|
| BCLK频率 | 128 × fs | 256 × fs | 384 × fs | fs为采样率 |
| LRCK占空比 | 45% | 50% | 55% | 左右声道平衡 |
| 数据建立时间 | 10 ns | — | — | DIN相对BCLK边沿 |
| 数据保持时间 | 5 ns | — | — | BCLK边沿后数据维持 |
嗯,这里要注意:WM8960的I2S数据位宽支持16位、20位、24位和32位。但STM32的I2S外设通常只支持16位和32位。如果你要用24位音频,得用32位帧格式,然后只取高24位。我踩过这个坑,当时录音文件全是噪声,查了半天才发现是位宽没对齐。
I2C控制接口:芯片的「遥控器」
WM8960的所有寄存器配置都通过I2C接口完成。它只有一个I2C地址:0x1A(7位地址),或者0x34(8位地址)。为什么只有一个?因为WM8960没有地址选择引脚,固定死了。
I2C接口就两根线:
- SCL(时钟线)—— 由主设备(STM32)驱动,标准模式100kHz,快速模式400kHz。
- SDA(数据线)—— 双向,开漏输出,需要上拉电阻。
注意:WM8960的I2C接口不支持高速模式(1MHz)。我曾经为了赶速度把I2C时钟设到800kHz,结果芯片偶尔不响应。老老实实用400kHz,稳定第一。
WM8960的寄存器是7位地址 + 9位数据。你没看错,是9位数据。它的每个寄存器有9位有效位,但I2C传输时按16位处理:高7位是寄存器地址,低9位是数据,中间补0。写操作时序如下:
// I2C写WM8960寄存器示例(伪代码)
// reg_addr: 7位寄存器地址
// data: 9位数据值
uint16_t wm8960_write_reg(uint8_t reg_addr, uint16_t data) {
uint8_t buf[2];
buf[0] = (reg_addr << 1) | ((data >> 8) & 0x01); // 高7位地址 + 数据第8位
buf[1] = data & 0xFF; // 数据低8位
// 调用HAL_I2C_Master_Transmit(&hi2c1, 0x34, buf, 2, 100);
}
我个人习惯,把WM8960的寄存器初始化序列写成一个结构体数组,按顺序写入。这样调试时方便增删寄存器配置。
电源管理与时钟树:芯片的「心脏和血管」
WM8960的电源设计比普通音频芯片复杂一些。它有多个电源域:
| 电源引脚 | 电压范围 | 典型值 | 供电对象 |
|---|---|---|---|
| AVDD | 2.7V ~ 3.6V | 3.3V | 模拟核心电路 |
| DBVDD | 1.71V ~ 3.6V | 3.3V | 数字缓冲器 |
| DCVDD | 1.71V ~ 3.6V | 1.8V 或 3.3V | 数字核心电路 |
| SPKVDD | 2.7V ~ 5.5V | 5.0V | 扬声器功放 |
| CPVDD | 2.7V ~ 3.6V | 3.3V | 电荷泵 |
你可能会问:为什么搞这么多电源?说白了,是为了隔离噪声。模拟电路对电源纹波敏感,数字电路开关噪声大,功放电流需求高。分开供电,各取所需。
时钟树方面,WM8960需要两个时钟:
- MCLK(主时钟)—— 用于内部DSP和ADC/DAC的时钟源。典型频率:12.288MHz(48kHz采样率)、11.2896MHz(44.1kHz采样率)。
- BCLK(位时钟)—— 用于I2S接口的数据移位。
WM8960内部有一个PLL,可以把MCLK倍频到所需的内部时钟。如果你用的MCLK不是标准频率,可以配置PLL分频比。我建议直接用标准频率,省去PLL配置的麻烦。
小技巧:WM8960支持自动时钟检测。如果MCLK丢失,它会自动切换到内部振荡器。但内部振荡器精度不高,只能用于省电模式。正常工作时,一定要保证MCLK稳定。
原理图设计要点:别让硬件坑了你
原理图设计是音频系统的基石。我见过太多「软件调不通,最后发现是原理图画错了」的案例。下面是我总结的几个关键点:
- 去耦电容不能省:每个电源引脚旁边放一个10μF电解电容 + 一个100nF陶瓷电容。电解电容滤低频,陶瓷电容滤高频。电容要尽量靠近芯片引脚,走线要短。
- 模拟地和数字地要分开:WM8960有AGND和DGND引脚。在原理图上,模拟地和数字地用磁珠或0Ω电阻单点连接。不要直接铺铜连在一起,否则数字噪声会串进模拟电路。
- 音频输入输出走线要保护:LINE_IN、MIC_IN、HP_OUT这些信号线,远离时钟线和数字信号线。我习惯在音频线两侧加地线屏蔽。
- 扬声器输出要加滤波:WM8960的SPK_OUT是D类功放输出,含有高频开关噪声。在输出端串联一个10μH电感和一个100nF电容到地,构成LC低通滤波器。
- I2C上拉电阻要选对:SCL和SDA各接一个4.7kΩ上拉电阻到3.3V。如果I2C总线长度超过10cm,可以换成2.2kΩ。
下面这张图是我整理的WM8960核心接口与电源架构,方便你理解整体连接关系:
嗯,这张图把WM8960的接口关系说清楚了。左边是I2S和I2C,右边是电源和时钟,下面是音频输入输出。你设计原理图时,就按这个思路来:先保证电源干净,再保证时钟准确,最后接好数据和控制线。
避坑指南:我曾经在一个项目里,把WM8960的SPKVDD接到了3.3V上,结果扬声器输出功率只有标称值的一半。后来查手册才发现,SPKVDD需要5V才能达到1W输出。所以,功放电源一定不要省。
最后说一句:原理图设计时,多留几个测试点。比如I2S的BCLK、LRCK,I2C的SCL、SDA,都引出焊盘。调试时用示波器一看就知道信号正不正常。这个习惯帮我省了无数排查时间。