I2S开发困难重重
用的STC32G8K64,从这个规格书上可以看到,I2S的位时钟主要和 I2SPRL这个寄存器有关,I2SPRH 固定写 3
I2SPRL设置的是音频主时钟,也叫同步时钟,而I2S的比特率也称位时钟=16*2*FS。
在这个图里,我FOSC设置12M,I2SDIV=FOSC/(16*2*8*SampleRate)=12M/(16*2*8*4500)=10
同步时钟FS=I2S时钟/(16*2*(2*DIV+ODD)*8))=12M/(16*2*(2*10+1)*8)=2.2Khz.
位时钟=16*2*FS=70.4Khz
以下为代码实际运行的效果。为什么对不上的。
您好,关于您在使用 STC32G8K64 进行 I2S 接口开发过程中遇到的问题,我们从以下几个方面进行分析与排查:
一、I2S时钟配置逻辑分析
根据您提供的信息,您使用的是 I2S主模式,FOSC为12MHz,I2SDIV设为10,I2SPRL=10,I2SPRH=3。根据规格书中的公式:
1. 同步帧时钟(FS)计算公式:
$$
FS = \frac{F{I2SCLK}}{162 \times (2 \times I2SPRL + I2SPRH) \times 8}
$$
其中:
$ F{I2SCLK} $:I2S主时钟源频率(由I2SDIV分频后得到)
I2SPRL:主时钟分频低位
I2SPRH:主时钟分频高位(固定为3)
162:固定系数,用于生成位时钟
2. I2S主时钟计算公式:
$$
F{I2SCLK} = \frac{F{OSC}}{16 \times (2 \times I2SDIV + ODD)}
$$
其中:
$ F{OSC} = 12MHz $
I2SDIV = 10
ODD = 1(根据您代码中的设置)
代入得:
$$
F{I2SCLK} = \frac{12M}{16 \times (2 \times 10 + 1)} = \frac{12M}{16 \times 21} = 35.714kHz
$$
再代入FS计算:
$$
FS = \frac{35.714kHz}{162 \times (2 \times 10 + 3) \times 8} = \frac{35.714}{162 \times 23 \times 8} = \frac{35714}{29808} \approx 1.198Hz
$$
这个结果显然与预期不符,说明配置逻辑存在偏差。
二、配置逻辑错误分析
1. I2SDIV的设置依据
您提供的公式为:
$$
I2SDIV = \frac{F{OSC}}{16 \times 2 \times SampleRate} = \frac{12M}{16 \times 2 \times 4500} = 83.33
$$
但实际您设置为10,这会导致I2S主时钟远低于预期,从而影响帧率和位时钟。
2. 位时钟(Bit Clock)计算错误
您提到位时钟应为 16 × 2 × FS = 162 FS,但实际上:
16 × 2 是指16位立体声(每声道16位,立体声即32位),而 I2S 标准下,每个帧包含两个声道,每个声道16位,即共32位。
所以正确的位时钟应为 32 × FS
因此:
$$
BitClock = 32 \times FS
$$
而您使用的162是错误的,可能是将系数混淆了。
三、建议的配置修正
1. 目标参数设定
FOSC = 12MHz
音频采样率 Fs = 4500Hz
位时钟 = 32 × Fs = 144,000Hz
2. I2SDIV的计算
$$
I2SDIV = \frac{F{OSC}}{16 \times BitClock} = \frac{12M}{16 \times 144000} = \frac{12000000}{2304000} ≈ 5.2
$$
取整数部分为5,ODD=0 或 1(可微调)
3. I2SPRL 和 I2SPRH 的设置
由于 I2SPRH 固定为3,所以:
$$
FS = \frac{F{I2SCLK}}{162 \times (2 \times I2SPRL + 3) \times 8}
$$
代入:
$$
F{I2SCLK} = \frac{12M}{16 \times (2 \times 5 + 0)} = \frac{12M}{16 \times 10} = 75kHz
$$
$$
FS = \frac{75000}{162 \times (2 \times I2SPRL + 3) \times 8}
$$
令 FS = 4500Hz:
$$
4500 = \frac{75000}{162 \times (2 \times I2SPRL + 3) \times 8}
\Rightarrow (2 \times I2SPRL + 3) = \frac{75000}{4500 \times 162 \times 8} ≈ 0.0128
$$
这显然不合理,说明系统时钟与I2S配置之间存在不匹配,可能需要提高FOSC或降低采样率。
四、建议解决方案
方案一:提高系统主频
将 FOSC 提高至 24MHz 或更高,以获得更高的 I2S 主时钟
重新计算 I2SDIV、I2SPRL 等寄存器值
方案二:使用外部时钟源
若芯片支持外部时钟输入,可接入高精度音频时钟(如12.288MHz),用于I2S模块
可极大提升音频同步精度
方案三:使用PLL倍频
若芯片支持 PLL 倍频功能,可将系统时钟倍频后再用于I2S
提高时钟精度与稳定性
五、调试建议
1. 使用示波器测量I2S各信号线(BCLK、WS、SD):
确认BCLK频率是否符合预期
WS是否与BCLK同步,且频率为4500Hz
数据线SD是否输出正确音频数据
2. 检查寄存器配置是否正确写入:
使用调试器或串口打印寄存器值,确认配置无误
3. 使用I2S标准音频设备验证输出:
接入DAC或音频解码芯片(如TI PCM5102、WM8731等)
观察是否能输出正常音频
六、总结
您当前的配置中存在以下问题:
I2SDIV设置过小,导致I2S主时钟偏低
位时钟计算错误,误将162作为固定系数
I2SPRL计算逻辑错误,导致帧率不匹配
未考虑主频与音频采样率之间的匹配关系
建议:
重新计算I2SDIV、I2SPRL等寄存器
提高主频或使用外部时钟
使用示波器辅助调试
如需进一步协助,欢迎提供完整代码或配置流程,我们可协助逐行分析。
祝开发顺利!
国芯人工智能团队
2025年4月5日
[本文内容由国芯人工智能辅助生成,仅供参考]
可以确定是16位的位宽 而且不管我如何修改SampleRate的数值或者FOSC的值,都不会导致这个波形发生变化。就很奇怪,时钟用的外部12M振荡器,已经确认晶振是工作的
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=19972&pid=186080
神农鼎 发表于 2025-10-8 14:01
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=19972&pid=186080
但是我用的是位宽16,采样21Khz,那MCLK=128*0.021=2.688Mhz
选择晶振12MHZ,四分频,按理说也可以做到差不多的吧。 妖怪罗小黑OL 发表于 2025-10-8 11:46
而且不管我如何修改SampleRate的数值或者FOSC的值,都不会导致这个波形发生变化。就很奇怪,时钟用的外部12 ...启用了外部晶振,主时钟源没选对
貌似是个AiCube自动生成BUG,同时启用外部晶振和PLL:
1.多了个选择内部HIRC时钟源,和外部晶振冲突
CLK_MCLK_XTAL
CLK_MCLK_HIRC
2.旁路MCLK2和PLL配置冲突
CLK_MCLK2_BYPASS
CLK_PLL_Output144MHz();
CLK_PLL_PreDivider2();
推荐先在已调通的I2S程序上修改试试:
Ai8051U实现USB全双工声卡,同时 录音/ 放 音,微信通话/腾讯会议 可用, 重磅开源 - 51 发烧友,UAC,极致音频,大国工匠,艺术人生,乐林漫步 国芯人工智能技术交流网站 - AI32位8051交流社区
一个音视频播放例程【USART-SPI==>DMA-P2P==>SPI, +I2S】@AI8051U - TFT彩屏,触摸屏,DMA-i8080/M6800并口自动刷屏,DMA-SPI刷屏,外设直接到外设 国芯人工智能技术交流网站 - AI32位8051交流社区
页:
[1]