stm32读取麦克风inmp441数据并实时播放

打印 上一主题 下一主题

主题 1777|帖子 1777|积分 5331

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
概述

近来在做一个功能类似于对讲机通话的功能,原来在网上感觉很容易找到同样的案例复刻,结果发现大多数都是用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(我买的这样的)

目前我找了许多麦克风方案,就这一款方案应该是全网比较多的类型,这个麦克风是直接使用i2s协议读取的,直接连接到芯片即可。别的特别要提到的是这个麦克风是全向麦克风,很容易捕捉到噪声,以是其实不太发起把扬声器和麦克风放在一起使用,会引起啸叫
引脚定义:
  VDD
  3.3v电源
  GND
  接地
  SD
  I2S协议的SD引脚用来数据输出
  SCK
  I2S协议里面的时钟 信号输入
  WS
  I2S协议的字选择引脚
  L/R
  用来区分这个麦克风是左声道还是右声道 没有要求的话就直接接地就行了
  MAX98357

价格:4.7R

这是一个音频功放芯片而且他具有i2s转DAC的功能(重点),支持扬声器的阻抗4欧姆到8欧姆,最大提供功率是3W
类型类音频放大器
引脚定义
  VDD
  电源引脚,通常连接到5v
  GND
  接地
  DIN
  i2s协议的数据输入引脚SD
  BCLK
  i2s协议的时钟引脚SCK
  LRC
  I2S协议的字选择引脚WS,代表左声道还是右声道
  OUT+
  音频输出正极,连接扬声器的正极
  OUT-
  音频输出负极,连接扬声器的负极
  GAIN
  增益引脚,可浮空
  SD
  静音引脚,可浮空
  如果你对扬声器没有太大的要求 其实1 块2块的扬声器就已经够用了

主控芯片stm32f407vet6

我使用的这个芯片其实是GD32f407vet6但是实际上所有的引脚类型什么的跟stm同类型的完全没有区别 ,而且我也是拿cubeide开发的以是完全不影响。
必要单独说一下的是,你自己的芯片必要至少一个i2s协议的片上外设,我不知道有没有软件i2s的东西。

连线图


根据上面的引脚定义把红色框框的是i2s2的三根线 蓝色框框的是I2S_3的三根线
红色连接到麦克风的i2s的三根线 蓝色则对应的是MAX98357

开始设置

首先根据引脚定义连接inmp441模块,max98357模块
1:设置I2S_2总线 设置这个是用来读取麦克风INMP441数据的总线

注意按照我红色框框的地方设置, 特别要说的一点是inmp441这个模块输出的是24位 以是只能选择我这个Data and Frame Format的设置
下面48HZ是采样率 根据你自己的环境选择就行了 只不过在下面的i2s 3也要设置成一样的采样率

2.设置i2s2的dma

同样按照我的设置方式设置

3.设置I2S 3总线 这个总线是把i2s 2接受到的数据传输给MAX98357功放模块

注意这里由于是发送数据 以是要把 Transmission Mode设置为 Mode Master Transmit
4.设置I2S_3的dma

5:接着生成代码后 只必要在main.c里面写简单两个函数就行了


这里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[0]和dma[1]举行位操纵会比较方便),而如今我不必要软件转了 直接把数据给max98357芯片不就好了吗 ,然后我删除了这部分的代码,直接设置好两个i2s的协议的设置相同,把麦克风数据直接传给max98357,然后dma的数组定义成1024大小。一调试,发现乐成了,音质也很好,结果也非常不错。

参考链接:
使用STM32的I2S协议读取麦克风INMP441-CSDN博客


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

吴旭华

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表