STM32CubeMX+MDK通过I2S接口进行音频输入输出(全双工读写一个DMA回调)续-音质问题解决总结

一、前言

之前进行了STM32CubeMX+MDK通过I2S接口进行音频输入输出(全双工读写一个DMA回调)的研究总结:
https://juejin.cn/post/7339016190612881408#heading-34

后续音质问题解决了,目前测试下来48khz的双声道使用效果很好,由于比较重要,这里单独补充总结一下可能音质原因(包括杂音),这对于调试stm32的i2s录放音很有帮助,不管stm32作为i2s从模式还在作为i2s主模式都是有用的,上述总结的全双工DMA回调处理接口是不需要变的。

二、资料收集

https://blog.csdn.net/Fairchild_1947/article/details/123391638?spm=1001.2014.3001.5501

这里的时钟配置对我有很大的启发,对应f4的芯片对应i2s的时钟配置必须是按照这样固定的,否则音质一定会打折扣。

三、音质问题可能原因总结(重要)

  • 1、是采样率匹配问题,采样率设置不对一定会导致杂音、快进慢放等问题;
  • 2、一个是单双声道问题,生成wav文件时如果声卡设备转换为双声道但是按照单声道处理就会有问题,数据量是双声道的,但是存储时处理了一半;(部分声卡固定是双声道,即使你的播放文件是单声道的,但是经过声卡播放后就是双声道的音,这时单片机通过i2s接收和发送都必须是按照双声道处理
  • 3、还有一个可能就是声卡设备的干扰问题,比如声卡i2s或者某些引脚接线不对导致影响数字信号采集,比如单片机作为主模式可选配的主时钟接入了声卡导致音质影响,实际声卡有其自己的主时钟mclk,声卡的该引脚就不能接入单片机了,否则单片机的i2s的mclk和声卡的mclk互相影响会导致音质问题;
  • 4、还有发现一个问题,声卡i2s的收和发的数据长度设置不一致,比如发设置了标准的16位长度,而接收设置了16位扩展32位长度,导致i2s初始化后接收可能正常,但是发送时声卡收不到数据从而导致录音没有声音,这一点也是很奇怪的,目前猜测可能是声卡双声道传输的问题导致的,所以一般出现设置16位数据长度16位数据帧接收没问题但是发送发送没有声音的话可以试着设置成16位数据32位帧;
  • 5、如果使用spi flash+fatfs进行音频文件写入的,那么音频波形快进样式也可能是spi flash的驱动问题导致的,正片擦除后写入时写入速度快就不会有这个问题,需要在写入前先擦除,如果写入时再擦除会影响写入速度从而影响录音;(调试时可以用示波器先确认硬件对应引脚输出的频率是否符合预期)
    采样率的时钟频率F4按照下图配置即可(比如48khz的固定为258的PLLI2SN和3的PLLi2SR,不同外部输入时钟可以设置对应分频后为1MHZ,比如8MHZ的则设置8分频,25MHZ的设置为25):spi flash理论上是不适合实时读写的,一般开机时写入一次,后续读取即可,因为spi flash的擦除是很耗时的,所以音频文件的实时读写在方案设计之初就需要考虑这一点,对于实时音频存储一定要注意这一点(目前考虑可以直接通过usb3.0等高速接口透传出来音频输出或者使用SD卡等方式);
  • 6、时钟配置配置这里给出一个参考,外部高速时钟不同可能会有一些差异,但是一定要按照固定的时钟分频去配置,比如我这里是25MHZ的:(如果是8MHZ的则M设置为8,后面N和R固定为258和3)

如下是参考网友的i2s时钟分频:

对于不同的HSE,我们为了达到上述一样的i2s时钟分频,需要根据25或8MHZ的不同HSE做不同的分频系数,比如25MHZ的HSE则对应的PLLM分频系统设置25,8MHZ的设置8,这样后面的PLLI2SN和PLLI2SR就能像上图一样固定了(HAL库的一般STM32CubeMX会自动配置时钟,这里往往自动配置的是不对的,要注意这一点 )。

参考非HAL库中设置采样率的这一段代码可以更好的理解上面这一配置:

c 复制代码
//采样率计算公式:Fs=I2SxCLK/[256*(2*I2SDIV+ODD)]
//I2SxCLK=(HSE/pllm)*PLLI2SN/PLLI2SR
//一般HSE=8Mhz 
//pllm:在Sys_Clock_Set设置的时候确定,一般是8
//PLLI2SN:一般是192~432 
//PLLI2SR:2~7
//I2SDIV:2~255
//ODD:0/1
//I2S分频系数表@pllm=8,HSE=8Mhz,即vco输入频率为1Mhz
//表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
const u16 I2S_PSC_TBL[][5]=
{
	{800 ,100,2,24,0},		//8Khz采样率
	{1102,429,4,19,0},		//11.025Khz采样率 
	{1600,213,2,13,0},		//16Khz采样率
	{2205,429,4, 9,1},		//22.05Khz采样率
	{3200,213,2, 6,1},		//32Khz采样率
	{4410,271,2, 6,0},		//44.1Khz采样率
	{4800,100,2, 4,0},		//48Khz采样率
	{8820,316,2, 3,1},		//88.2Khz采样率
	{9600,344,2, 3,1},  	//96Khz采样率
	{17640,361,2,2,0},  	//176.4Khz采样率 
	{19200,393,2,2,0},  	//192Khz采样率
};  
//设置IIS的采样率(@MCKEN)
//samplerate:采样率,单位:Hz
//返回值:0,设置成功;1,无法设置.
u8 I2S2_SampleRate_Set(u32 samplerate)
{ 
	u8 i=0; 
	u32 tempreg=0;
	samplerate/=10;//缩小10倍   
	
	for(i=0;i<(sizeof(I2S_PSC_TBL)/10);i++)//看看改采样率是否可以支持
	{
		if(samplerate==I2S_PSC_TBL[i][0])break;
	}
 
	RCC_PLLI2SCmd(DISABLE);//先关闭PLLI2S
	if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到
	RCC_PLLI2SConfig((u32)I2S_PSC_TBL[i][1],(u32)I2S_PSC_TBL[i][2]);//设置I2SxCLK的频率(x=2)  设置PLLI2SN PLLI2SR
 
	RCC->CR|=1<<26;					//开启I2S时钟
	while((RCC->CR&1<<27)==0);		//等待I2S时钟开启成功. 
	tempreg=I2S_PSC_TBL[i][3]<<0;	//设置I2SDIV
	tempreg|=I2S_PSC_TBL[i][4]<<8;	//设置ODD位
	tempreg|=1<<9;					//使能MCKOE位,输出MCK
	SPI2->I2SPR=tempreg;			//设置I2SPR寄存器 
	return 0;
}

四、最后

基本上stm32使用i2s的音视频总结这两篇文章就够用了,其它的stm32作为usb声卡或者录音也只是以stm32作为i2s主模式来驱动像wm8978这类音频编解码器即可,反而不会遇到这种直接和声卡交互stm32作为从模式可能引起的一些音质问题(调试过程中使用示波器来测量引脚频率可以帮助排除一些硬件问题,这样更能明确问题处理方向)。

相关推荐
逼子格20 分钟前
五种音频器件综合对比——《器件手册--音频器件》
嵌入式硬件·音视频·硬件工程师·硬件测试·电子器件·硬件笔试真题·音频器件
EasyGBS1 小时前
视频设备轨迹回放平台EasyCVR打造视频智能融合新平台,驱动智慧机场迈向数字新时代
网络·人工智能·安全·音视频
EasyGBS2 小时前
视频设备轨迹回放平台EasyCVR综合智能化,搭建运动场体育赛事直播方案
网络·安全·音视频
niuTaylor2 小时前
STM32平衡车开发实战教程:从零基础到项目精通
stm32·单片机·嵌入式硬件
SKYDROID云卓小助手6 小时前
三轴云台之相机技术篇
运维·服务器·网络·数码相机·音视频
yunteng5217 小时前
音视频(一)ZLMediaKit搭建部署
音视频·zlmediakit·安装搭建
Merokes10 小时前
关于Gstreamer+MPP硬件加速推流问题:视频输入video0被占用
c++·音视频·rk3588
可待电子单片机设计定制(论文)11 小时前
【STM32设计】基于STM32的智能门禁管理系统(指纹+密码+刷卡+蜂鸣器报警)(代码+资料+论文)
stm32·单片机·嵌入式硬件
不可思议迷宫12 小时前
Verilog编程实现一个分秒计数器
单片机·嵌入式硬件·fpga开发
EasyGBS14 小时前
NVR接入录像回放平台EasyCVR视频系统守护舌尖上的安全,打造“明厨亮灶”云监管平台
安全·音视频