stm32读取麦克风inmp441数据并实时播放
概述近来在做一个功能类似于对讲机通话的功能,原来在网上感觉很容易找到同样的案例复刻,结果发现大多数都是用esp32,或者说电脑作为上位机传输wav音频解码播放的结果,也有很相仿的,但是都测试结果不尽人意,经过不停探索下面是我给出的方案。
但是本篇文章只限于单片机mcu芯片通过i2s读取麦克风inmp441的音频数据再通过i2s传输给MAX98357功放芯片(i2s转dac),这个功放芯片再连接到扬声器并举行播放,整体我已经测试过 结果很好
I2S协议
注意这虽然很像i2c协议 但是并不是,i2s协议是一种音频传输的协议,用来传输音频数据,i2s一样平常是三个引脚 分别是SD SCK WS
其中SCK用来提供时钟信号 ,WS协议是用于指示当前数据位是左声道还是右声道,一样平常来说低电平是左,高是右。SD是串行数据线传输音频数据。像i2c一样 i2s上应该也可以连接多个设备,好比一对麦克风和扬声器, 只必要做的是SCK和WS连接相同引脚 而SD作为数据输出单独联机一个引脚。不过在本文里面 为了方便读者明白,我使用了两个i2s总线 一个负责读取麦克风数据 一个负责播放麦克风。关于i2s协议的更多信息在网上已经有很详细的解释了可以很方便查阅到。
INMP441麦克风
价格8R(我买的这样的)
https://i-blog.csdnimg.cn/direct/e67f459a8af7437e85d1a601660b4553.png
目前我找了许多麦克风方案,就这一款方案应该是全网比较多的类型,这个麦克风是直接使用i2s协议读取的,直接连接到芯片即可。别的特别要提到的是这个麦克风是全向麦克风,很容易捕捉到噪声,以是其实不太发起把扬声器和麦克风放在一起使用,会引起啸叫
引脚定义:
VDD
3.3v电源
GND
接地
SD
I2S协议的SD引脚用来数据输出
SCK
I2S协议里面的时钟 信号输入
WS
I2S协议的字选择引脚
L/R
用来区分这个麦克风是左声道还是右声道 没有要求的话就直接接地就行了
MAX98357
价格:4.7R
https://i-blog.csdnimg.cn/direct/4a78d0b42f94459fa7fbd47cba2a4a89.png
这是一个音频功放芯片而且他具有i2s转DAC的功能(重点),支持扬声器的阻抗4欧姆到8欧姆,最大提供功率是3W
类型:D类音频放大器
引脚定义
VDD
电源引脚,通常连接到5v
GND
接地
DIN
i2s协议的数据输入引脚SD
BCLK
i2s协议的时钟引脚SCK
LRC
I2S协议的字选择引脚WS,代表左声道还是右声道
OUT+
音频输出正极,连接扬声器的正极
OUT-
音频输出负极,连接扬声器的负极
GAIN
增益引脚,可浮空
SD
静音引脚,可浮空
如果你对扬声器没有太大的要求 其实1 块2块的扬声器就已经够用了
主控芯片stm32f407vet6
我使用的这个芯片其实是GD32f407vet6但是实际上所有的引脚类型什么的跟stm同类型的完全没有区别 ,而且我也是拿cubeide开发的以是完全不影响。
必要单独说一下的是,你自己的芯片必要至少一个i2s协议的片上外设,我不知道有没有软件i2s的东西。
连线图
https://i-blog.csdnimg.cn/direct/4e2b19d5ab0243b3a34ce3170fe6da72.png
根据上面的引脚定义把红色框框的是i2s2的三根线 蓝色框框的是I2S_3的三根线
红色连接到麦克风的i2s的三根线 蓝色则对应的是MAX98357
https://i-blog.csdnimg.cn/direct/4005ba3cc69b4483a72e648becc04f9b.png
开始设置
首先根据引脚定义连接inmp441模块,max98357模块
1:设置I2S_2总线 设置这个是用来读取麦克风INMP441数据的总线
https://i-blog.csdnimg.cn/direct/61ff0b1eff31430ba1a771e7f36b4cf7.png
注意按照我红色框框的地方设置, 特别要说的一点是inmp441这个模块输出的是24位 以是只能选择我这个Data and Frame Format的设置
下面48HZ是采样率 根据你自己的环境选择就行了 只不过在下面的i2s 3也要设置成一样的采样率
2.设置i2s2的dma
https://i-blog.csdnimg.cn/direct/5695c13c096f46d3b1eab60e1af00d05.png
同样按照我的设置方式设置
3.设置I2S 3总线 这个总线是把i2s 2接受到的数据传输给MAX98357功放模块
https://i-blog.csdnimg.cn/direct/8c9f9432af27409db5a4653c55eb22e2.png
注意这里由于是发送数据 以是要把 Transmission Mode设置为 Mode Master Transmit
4.设置I2S_3的dma
https://i-blog.csdnimg.cn/direct/69e07befeaf248c58139b77dac3f8e02.png
5:接着生成代码后 只必要在main.c里面写简单两个函数就行了
https://i-blog.csdnimg.cn/direct/48226488bf17481d9162ad0ef845796d.png
https://i-blog.csdnimg.cn/direct/8c15af3eac044e5181a53b3d424b48ab.png
这里dma的数组大小最好是1024 ,如果太小,那么每次传输的数据就比较小 结果就会变差 失真也比较高
一样平常来说到这一步就已经乐成完成了,烧录进芯片就可以实现功能结果了
过程履历(Debug)
首先要说一个我最开始碰到的一个认知明白标题。
最开始当我了解到i2s读取麦克风数据并传输给芯片的时间的, 由于i2s读取的数据是有正负性的 而且数据范围也很大,而我 拿到手上的麦克风是只有正负极,正极是要通过DAC模拟电压值变化来举行播放声音的。
很显然地可以明白到我可以在单片机上接收到i2s的音频数据再把这个数据映射到0-4095范围(DAC一样平常是12位的)然后把DAC的输出引脚接在扬声器的正极 负极接地。
我确实也是这样做的,音频确实是传输有结果了,但是音质差的不行,别说人声了 连一点稍微有规律的音乐都听不出来。我最开始是以为是电源的噪音,或者要做数据滤波,但是都试过了都没有办法办理这个标题,拖了很长时间。
而其时为什么我没有想到功放呢,是由于我其时的明白是功放只是放大音频信号,普通的功放芯片不具备滤波结果会把噪音一并放大,而且我其时想做的功能类似于耳机,并不必要把声音放的有多大,这就导致我一开始完全没有想到用功放芯片。
但是我在网上找了许多资料和视频,他们大多数没有做任何的滤波,简单地把Inmp441的麦克风数据传输给电脑播放出来的声音结果特别好,以是根本上可以排查麦克风的优劣标题,而电源的噪音我也拿示波器测试过了 是比较稳定的 不至于影响到噪音特别大。然后我以为是扬声器的标题,一开始扬声器是1块钱一个的,后面换成2块钱一个了 但是结果一样很差。
然后直到我刷到一个博主用esp32读取Inmp441数据并传输给 MAX98357播放出来的声音特别好,我就去查了这个功放芯片的东西。我惊讶地发现他可以把I2S的数据转成DAC数据输出 而不必要我软件中心把I2S数据转成DAC。虽然我不知道两者有什么差别,但是我还是买返来试了一下。一开始我写好代码设置好引脚后,虽然说噪音少了一些了,信噪比更高了,但是希奇的是 声音仿佛断断续续导致失真很严峻。
然后我开始重新审查软件代码的标题,我发现我的dma的缓冲区的大小写的4(由于一开始软件i2s的数据转dac的时间这样每一次都处理映射成dma和dma举行位操纵会比较方便),而如今我不必要软件转了 直接把数据给max98357芯片不就好了吗 ,然后我删除了这部分的代码,直接设置好两个i2s的协议的设置相同,把麦克风数据直接传给max98357,然后dma的数组定义成1024大小。一调试,发现乐成了,音质也很好,结果也非常不错。
参考链接:
使用STM32的I2S协议读取麦克风INMP441-CSDN博客
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]