发新帖我要提问
12
返回列表
打印
[其他ST产品]

使用STM32的I2S协议读取麦克风INMP441

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
21
由于前面将DMA Mode设置为了Circular,因此只需要调用一次该函数,就能开启DMA的连续存取。该函数的原文注释如下:


/**
  * @brief  Receive an amount of data in non-blocking mode with DMA
  * @param  hi2s pointer to a I2S_HandleTypeDef structure that contains
  *         the configuration information for I2S module
  * @param  pData a 16-bit pointer to the Receive data buffer.
  * @param  Size number of data sample to be sent:
  * @NOTE   When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
  *         configuration phase, the Size parameter means the number of 16-bit data length
  *         in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
  *         the Size parameter means the number of 24-bit or 32-bit data length.
  * @note   The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
  *         between Master and Slave(example: audio streaming).
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)

使用特权

评论回复
22
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
根据以上说明,最后一个参数size的单位是由数据帧的长度决定的。前面在Cube中设置的数据格式为24 Bits Data on 32 Bits Frame,因此DMA读取数据的总长度为size×4字节。前面定义的DMA缓冲区是一个长度为4的uint32_t型数组,缓冲区中的数据格式为:前2个元素表示左声道数据,后2个表示右声道数据。根据前面的电路图,本次试验只接了一个左声道的麦克风,因此右声道数据始终为0.以下是在数组dma[]中,左声道数据的示例:

使用特权

评论回复
23
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
可以观察出,dma[0]左移8位 + dma[1]右移8位,就得到了24位采样值。例如将0000fff5 00007700合并为0xfff577:

val24 = (buf32[0]<<8) + (buf32[1]>>8);

使用特权

评论回复
24
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
在这个DMA数据获取的阶段非常容易出错,最终的数据格式和在Cube中设置的DMA Data With、main.c中DMA缓冲数组的元素类型和DMA接收函数的参数值size都有关系,在我之前的测试中,如果把缓冲区元素转为uint8_t,就会得到不一样的结果,24bit采样值被拆分为3个字节,且未必是高位字节在前、低位字节在后的排列顺序。总之需要小心修改,通过把数据打印到串口,来寻找规律。按照本文的配置,接收到的原始数据是用2个32位无符号整型表示一个采样值,这应该不是最佳的格式,但我没有继续试验,读者可以尝试在Cube中把Data With设为Half-Word再进行测试。

使用特权

评论回复
25
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
麦克风发送的数值是24位二进制补码的形式,二进制补码也是单片机存储有符号整型的方式,因此可以将采样值视为24位有符号整型,为了与C语言的整型格式一致,需要将这个24位整型扩展到32位,方法为:正数保持不变,对于负数在左边加一个0xff。例如24位数0xfff577,它的最高位(符号位)是1,代表负数,因此转换为0xffff f577,代码如下:

                if(val24 & 0x800000){//negative
                        val32=0xff000000 | val24;
                }else{//positive
                        val32=val24;
                }

使用特权

评论回复
26
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
在串口绘图器中查看音频波形
使用串口绘图工具SerialPlot查看声音波形,SerialPlot相当于一个带波形绘制功能的串口助手,它的下载和使用方法可以到网上搜到。由于声音采样速度比较快,在上面回调函数中我把串口发送频率设成了采样频率的十分之一。

使用特权

评论回复
27
个百zz分点个|  楼主 | 2024-6-30 18:19 | 只看该作者
可在图中看到波形随着外界声音而波动,声音越响幅值越大,这说明采集到的数据是正常的。

至此实验完成。本文使用STM32的硬件I2S协议和DMA功能实现了对INMP441音频数据的采集,并将数据化为了有符号整型格式,以便进一步处理。

使用特权

评论回复
28
菜鸟的第一步| | 2024-7-10 15:26 | 只看该作者
过程详细,代码简介,很棒

使用特权

评论回复
29
雨果喝水| | 2024-8-29 12:38 | 只看该作者
需要在调用此函数前初始化好 I2S_HandleTypeDef 结构体,包括 I2S 配置、DMA 配置等。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则