4. WM8960 寄存器概览与初始化流程

好,这一章咱们来啃 WM8960 的寄存器。说实话,我第一次看 WM8960 的数据手册时,也被那密密麻麻的寄存器表吓了一跳——整整 56 个寄存器,每个 9 位,加起来 500 多个控制位。但别慌,实际项目中常用的也就那么十几个。我习惯把寄存器分成几类来理解,这样思路就清晰多了。

4.1 寄存器地址映射

WM8960 的寄存器地址范围是 0x00 ~ 0x3F,每个寄存器 9 位数据。注意,是 9 位,不是 8 位。这一点很容易踩坑——你如果用标准的 I²C 8 位写操作,数据会错位。

地址映射的规律其实很简单:

  • 0x00 ~ 0x0F:电源管理与复位
  • 0x10 ~ 0x1F:音频接口与时钟
  • 0x20 ~ 0x2F:音频路径与混音器
  • 0x30 ~ 0x3F:音量控制与附加功能

我整理了一张常用寄存器速查表,建议你收藏:

地址 寄存器名称 核心功能
0x00 Reset 软件复位,写入 0x00 复位芯片
0x01 Power Management 1 主电源开关,VREF、VMID 使能
0x02 Power Management 2 输入/输出 PGA 电源控制
0x03 Power Management 3 左/右声道混音器电源
0x04 Audio Interface I²S 格式、字长、主从模式
0x05 Clock Gen Control SYSCLK 分频、PLL 使能
0x06 Additional Control DAC/ADC 采样率、去加重
0x07 ~ 0x0A GPIO / Jack Detect GPIO 功能、耳机插入检测
0x10 ~ 0x15 Left/Right Input PGA 输入增益、静音控制
0x18 ~ 0x1D Left/Right Output Mixer 混音器通路选择
0x2A ~ 0x2F DAC / ADC Control 数字音量、软静音、过采样
0x30 ~ 0x33 Left/Right Speaker Volume 扬声器输出音量(每步 0.5 dB)
0x34 ~ 0x37 Left/Right Headphone Volume 耳机输出音量
我的小技巧: 写代码时别用魔数地址。我习惯在头文件里用宏定义,比如 #define WM8960_REG_PWR1 0x01,这样代码可读性高得多,也方便后期维护。

4.2 关键寄存器功能说明

寄存器虽多,但真正需要你手写的就那么几个。我挑几个核心的讲讲,其他的你用到时再查手册就行。

4.2.1 电源管理寄存器(0x01 ~ 0x03)

这三个寄存器是 WM8960 的命门。上电顺序错了,芯片可能不工作,甚至烧坏。我见过有人把 VREF 和 VMID 的使能顺序搞反,结果输出端一直有直流偏置,喇叭滋滋响。

Power Management 1 (0x01):

  • Bit 8: VREF 使能(必须先开)
  • Bit 7: VMID 使能(VREF 稳定后再开)
  • Bit 6: AINL/AINR 偏置使能
  • Bit 5: 数字核心电源使能
  • Bit 4: 偏置发生器使能

Power Management 2 (0x02):

  • Bit 8: 左声道输入 PGA 使能
  • Bit 7: 右声道输入 PGA 使能
  • Bit 6: 左声道 ADC 使能
  • Bit 5: 右声道 ADC 使能
  • Bit 4: 左声道输出混音器使能
  • Bit 3: 右声道输出混音器使能
  • Bit 2: 左声道 DAC 使能
  • Bit 1: 右声道 DAC 使能

Power Management 3 (0x03):

  • Bit 8: 左声道扬声器输出级使能
  • Bit 7: 右声道扬声器输出级使能
  • Bit 6: 左声道耳机输出使能
  • Bit 5: 右声道耳机输出使能
  • Bit 4: 左声道 LINEOUT 使能
  • Bit 3: 右声道 LINEOUT 使能
注意: 不要一次性把所有电源位都置 1。WM8960 的电源轨有先后依赖关系,乱开可能导致电流浪涌。我建议按「VREF → 数字核心 → 偏置 → PGA → ADC/DAC → 输出级」的顺序逐步使能。

4.2.2 音频接口控制寄存器(0x04)

这个寄存器配置 I²S 通信格式。说白了,就是告诉 WM8960:STM32 那边用什么格式发数据给你。

关键位:

  • Bit 8: 主从模式选择 — 0 为主模式,1 为从模式。我一般用从模式,让 STM32 提供 BCLK 和 LRCLK。
  • Bit 7: BCLK 极性 — 0 为正常,1 为反相。通常保持默认 0。
  • Bit 6: LRCLK 极性 — 0 为左声道低电平,1 为左声道高电平。I²S 标准是左声道低电平。
  • Bit 5: 字长选择 — 0 为 16 位,1 为 20 位,2 为 24 位,3 为 32 位。我常用 16 位或 24 位。
  • Bit 4: 格式选择 — 0 为 I²S,1 为左对齐,2 为右对齐,3 为 DSP 模式。

举个例子,如果你用 STM32 的 I²S 外设,格式通常配成:从模式、I²S 格式、16 位字长、BCLK 和 LRCLK 都正常极性。对应的寄存器值就是 0b00000010,即 0x02。

4.2.3 时钟使能寄存器(0x05)

WM8960 内部有一个 SYSCLK,所有数字模块(ADC、DAC、滤波器)都靠它驱动。SYSCLK 可以来自外部 MCLK,也可以来自内部 PLL。

关键位:

  • Bit 8: PLL 使能 — 1 为开启 PLL
  • Bit 7: SYSCLK 分频系数 — 0 为不分频,1 为 2 分频
  • Bit 6: SYSCLK 源选择 — 0 为 MCLK,1 为 PLL 输出
  • Bit 5: BCLK 分频使能 — 用于从 BCLK 产生 SYSCLK

我常用的配置是:外部提供 12.288 MHz MCLK,SYSCLK 直接取 MCLK 不分频。这样 ADC/DAC 的采样率正好是 48 kHz(256 倍过采样)。

4.2.4 音频路径控制(0x08 ~ 0x0D)

这部分控制信号怎么从输入走到输出。WM8960 的路径很灵活,但也容易配错。我画了一张简化的路径图:

WM8960 音频路径框图 LINE_IN MIC_IN 输入 PGA ADC I²S 接口 DAC 输出混音器 SPK/HP_OUT 录音路径:LINE_IN → PGA → ADC → I²S 播放路径:I²S → DAC → 混音器 → SPK_OUT

从图上你能看到,录音时信号走「LINE_IN → PGA → ADC → I²S」,播放时走「I²S → DAC → 混音器 → SPK_OUT」。每个节点都有对应的使能位和音量控制,缺一个都不行。

4.3 初始化序列设计

好了,寄存器功能都清楚了,接下来就是怎么把它们串起来。初始化序列是 WM8960 能否正常工作的关键。我踩过的坑不少,下面这个序列是我验证过多次的,你照着来基本不会出问题。

4.3.1 上电顺序

WM8960 的上电顺序有严格的时间要求。我总结成 5 步:

  1. 硬件上电:先给 DVDD(1.8V)和 AVDD(3.3V)供电。注意 DVDD 必须先于或同时于 AVDD 上电。
  2. 等待电源稳定:至少等 10 ms,让内部 LDO 和参考电压稳定下来。
  3. 软件复位:向寄存器 0x00 写入 0x00,复位所有寄存器到默认值。
  4. 使能 VREF 和 VMID:先开 VREF,等 5 ms 后再开 VMID。VMID 的电压是 AVDD/2,作为模拟信号的参考地。
  5. 使能数字核心和偏置:打开数字核心电源和偏置发生器,再等 2 ms。
核心要点: 上电顺序的本质是「先模拟后数字,先参考后信号」。VREF 和 VMID 是模拟电路的「地基」,地基没打好就盖楼,肯定要塌。

4.3.2 时钟启动

时钟是 WM8960 的心脏。我习惯用外部 MCLK,省去配置 PLL 的麻烦。时钟启动步骤:

  1. 确保外部 MCLK 已经稳定(用示波器看一下波形,别偷懒)。
  2. 配置寄存器 0x05:选择 MCLK 作为 SYSCLK 源,不分频。
  3. 配置寄存器 0x04:设置 I²S 格式、字长、从模式。
  4. 使能 BCLK 和 LRCLK(由 STM32 的 I²S 外设提供)。

如果你非要用 PLL,那就要算分频系数了。公式是:

PLL 输出频率 = MCLK × (N × 2) / (R × 2^K)
其中 N、R、K 是 PLL 配置参数,具体值查手册 Table 42

说实话,PLL 配置挺烦的,我一般只在 MCLK 频率不匹配时才用。比如你只有 12 MHz 晶振,但想要 48 kHz 采样率,那就得开 PLL 把 12 MHz 倍频到 12.288 MHz。

4.3.3 接口配置

接口配置就是让 WM8960 和 STM32 对上话。我以 I²S 从模式、16 位数据、48 kHz 采样率为例:

// 步骤1:软件复位
WM8960_WriteReg(0x00, 0x00);
HAL_Delay(10);

// 步骤2:使能 VREF 和 VMID
WM8960_WriteReg(0x01, 0x0180);  // VREF=1, VMID=1
HAL_Delay(5);

// 步骤3:使能数字核心和偏置
WM8960_WriteReg(0x01, 0x01B0);  // 加上 DIGEN=1, BIASEN=1
HAL_Delay(2);

// 步骤4:配置时钟
WM8960_WriteReg(0x05, 0x0000);  // SYSCLK 来自 MCLK,不分频

// 步骤5:配置音频接口
WM8960_WriteReg(0x04, 0x0002);  // 从模式,I²S 格式,16 位

// 步骤6:使能输入路径(录音)
WM8960_WriteReg(0x02, 0x01E0);  // 左 PGA=1, 右 PGA=1, 左 ADC=1, 右 ADC=1

// 步骤7:使能输出路径(播放)
WM8960_WriteReg(0x03, 0x01C0);  // 左 SPK=1, 右 SPK=1, 左 HP=1, 右 HP=1

// 步骤8:设置音量(避免爆音)
WM8960_WriteReg(0x30, 0x0019);  // 左扬声器音量 -30 dB
WM8960_WriteReg(0x31, 0x0019);  // 右扬声器音量 -30 dB
避坑指南: 我曾经在初始化完成后直接开最大音量,结果喇叭「噗」的一声差点烧掉。后来我学乖了,初始化时先把音量调到最低(比如 -30 dB),等系统稳定后再慢慢调高。这叫「软启动」,对扬声器和耳机都友好。

4.3.4 完整的初始化流程图

把上面这些步骤串起来,就是一张完整的初始化流程图:

WM8960 初始化流程图 开始初始化 1. 硬件上电 (DVDD → AVDD) 2. 等待 10 ms 电源稳定 3. 软件复位 (Reg 0x00 = 0) 4. 使能 VREF → 等 5 ms → 使能 VMID 5. 配置时钟与音频接口 初始化完成

这张图我建议你打印出来贴在工位上。每次调试 WM8960 时,按图索骥,哪一步卡住了就去查对应的寄存器配置,效率会高很多。

最后提醒一句: 初始化完成后,别急着跑业务逻辑。先读一下寄存器 0x01 的值,确认 VREF 和 VMID 确实置位了。我遇到过芯片虚焊导致写操作无效的情况,读回的值全是 0,排查了半天才发现是硬件问题。所以,写完寄存器后读回来验证一下,这个习惯能帮你省下大量调试时间。