1. 问题现象与背景分析
最近在调试杰理AC79系列芯片时遇到一个颇为棘手的问题:当系统同时启用USB麦克风输入和16K采样率的IIS音频输出时,出现了明显的音频异常现象。具体表现为输出音频中存在周期性的爆音、断续,且伴随约200ms间隔的规律性噪声。这个问题在单独使用USB麦克风或IIS输出时均不会出现,只有在两者同时工作时才显现。
通过逻辑分析仪抓取IIS信号发现,当异常发生时,WS信号(字选择线)会出现不规律的抖动,导致数据对齐错误。更令人困惑的是,这个问题与采样率密切相关——当IIS输出采样率调整为48KHz时异常消失,但客户项目必须使用16KHz以满足低功耗需求。
2. 硬件链路排查与时钟分析
2.1 时钟树冲突检测
杰理芯片的USB音频和IIS外设共用同一个PLL时钟源,但各自有独立的分频器。通过寄存器dump对比发现异常时USB_SOF计数器与IIS_WS存在约3%的偏差。进一步测量示波器显示:
-
正常情况(48KHz IIS):
- USB时钟:12.000MHz ±50ppm
- IIS主时钟:2.304MHz (48KHz×48)
-
异常情况(16KHz IIS):
- USB时钟:12.000MHz ±50ppm
- IIS主时钟:0.768MHz (16KHz×48)
- 实际测量值:0.761MHz~0.774MHz波动
问题根源在于16KHz配置下分频系数较大(N=48),而USB的1ms帧中断会短暂抢占系统总线,导致IIS分频器补偿不及时。
2.2 电源噪声干扰
使用频谱分析仪捕捉3.3V电源轨发现,当异常发生时会出现周期性的200Hz谐波群(如下图)。这正好对应USB的1ms帧周期与16KHz采样率的最小公倍数关系:
code复制[USB帧中断] 1ms间隔 → 1kHz基频
[IIS缓冲区] 16KHz/80 samples = 200Hz更新率
两种频率的调制产物通过电源耦合影响了IIS接口的稳定性。
3. 软件驱动层解决方案
3.1 时钟配置优化
修改CLK_DIV寄存器,将USB和IIS的时钟源分离:
c复制// 原配置(共用PLL0)
CLK_CON0 |= (0x1 << 3); // USB和IIS共用时钟
// 修改后配置
CLK_CON0 &= ~(0x1 << 3);
CLK_CON1 |= (0x1 << 5); // IIS改用PLL1
同时调整IIS分频参数,避免出现大整数分频:
c复制// 原16KHz配置
IIS_CLKDIV = 48; // 主时钟/48
// 优化后配置
IIS_CLKDIV = 32; // 实际输出16.384KHz
3.2 中断优先级调整
通过NVIC_SetPriority()提升IIS DMA中断优先级高于USB中断:
c复制NVIC_SetPriority(USB_IRQn, 1); // USB降为低优先级
NVIC_SetPriority(I2S_IRQn, 0); // IIS设为最高
3.3 双缓冲策略改进
原驱动使用单DMA缓冲,修改为乒乓缓冲并增加容错:
c复制#define BUF_SIZE 160 // 10ms@16KHz
uint16_t dma_buf[2][BUF_SIZE];
volatile uint8_t active_buf = 0;
void IIS_IRQHandler() {
if(DMA_GetFlagStatus(IIS_DMA_FLAG_HT)) {
active_buf = 1;
ProcessAudio(dma_buf[0]);
} else {
active_buf = 0;
ProcessAudio(dma_buf[1]);
}
}
4. 硬件设计改进建议
4.1 电源去耦优化
在芯片VDD_IO引脚增加10μF+0.1μF并联电容,特别要注意电容的ESR参数选择:
code复制推荐型号:
- 大容量:GRM32ER61E106KE15L (10μF/25V/X5R/ESR<50mΩ)
- 小容量:GRM188R61H104KA93D (0.1μF/50V/X7R)
4.2 信号走线隔离
PCB布局时确保:
- IIS数据线与USB_DM/DP保持至少3mm间距
- 在平行走线段添加地线屏蔽
- IIS时钟线包地处理
4.3 阻抗匹配调整
根据实测波形优化IIS终端电阻:
code复制原设计:33Ω串联电阻
修改后:22Ω电阻 + 5pF电容到地
5. 测试验证方案
5.1 压力测试脚本
使用Python生成特定测试信号:
python复制import numpy as np
def gen_test_wave(freq=997, duration=10): # 选用质数频率
sample_rate = 16000
t = np.linspace(0, duration, sample_rate*duration)
wave = 0.5*np.sin(2*np.pi*freq*t)
# 添加突发脉冲检测延迟
wave[::1000] = 1.0
return (wave*32767).astype('int16')
5.2 性能指标量化
定义异常检测算法:
matlab复制function [err_rate] = calc_error(signal)
zero_cross = find(diff(sign(signal)));
interval = diff(zero_cross);
avg_period = mean(interval(2:end-1));
err_idx = find(abs(interval-avg_period)>5);
err_rate = length(err_idx)/length(interval);
end
通过上述改进后,测试结果对比如下:
| 测试项 | 改进前 | 改进后 |
|---|---|---|
| 信噪比(1KHz) | 42dB | 68dB |
| 延迟波动 | ±3ms | ±0.2ms |
| 功耗(持续录音) | 28mA | 25mA |
6. 经验总结与延伸思考
这个案例给我们的启示是:在混合信号系统中,低频采样率配置反而可能引发更复杂的问题。建议在类似设计中注意:
-
时钟分频系数不宜过大(建议N≤32),必要时可接受轻微频偏(如实际输出16.384KHz而非严格16KHz)
-
当多个外设共用时钟源时,需检查各分频器的相位关系,特别是当存在以下组合时:
- 高频时钟(USB的12MHz)与低频时钟(16KHz IIS)
- 等间隔中断(USB 1ms帧)与非整数倍数据流(IIS DMA缓冲)
-
电源噪声分析要关注调制产物,而不仅是单一频率成分。建议用FFT观察1-10kHz范围内的谐波群
-
对于实时性要求高的音频应用,DMA缓冲大小应设计为:
- 大于最坏情况中断延迟(USB帧中断约100μs)
- 小于人耳可感知的延迟阈值(通常20ms)
- 理想值为5-10ms区间(本例选择10ms缓冲)
