M-Design设计竞赛 - 基于MEMS麦克风的音频采集设备
该项目使用了SPH0641LM4H1,实现了音频采集的设计,它的主要功能为:MEMS麦克风采集音频,通过USB传输到电脑上。
标签
麦克风
MEMS
M-Design
智能设备
胖头鱼
更新2025-04-01
19

随着智能语音交互和便携式设备的普及,物联网、智能穿戴和消费电子市场的迅速发展,对高性能、小型化、低功耗的声学传感器需求不断增长。传统电容式或驻极体麦克风因体积较大、功耗和噪声等问题逐渐难以满足日益紧凑的产品设计要求。MEMS 麦克风将微型机械结构与半导体工艺相结合因其微型化、低功耗和集成数字接口等优点正逐步替代传统电容式麦克风。本次使用的SPH0641LM4H1 作为其中的代表产品,采用数字输出的 PDM 格式,具有高信噪比和低总谐波失真(THD),适合高质量音频采集及语音处理应用,我参加本次活动的智能设备方向,打算实现一个USB麦克风。


SPH0641LM4H1

image.png

从贸泽上很容易就能找到芯片的资料

SPH0641LM4H1 是一款高性能 MEMS 麦克风,主要特点包括:

  • 高信噪比:保证清晰的音频采集,适用于语音交互和环境噪音检测。
  • 宽动态范围:适应多种声音强度变化,满足高质量音频录制要求。
  • 低功耗设计:非常适合电池供电的便携设备及 IoT 应用。
  • 数字输出:采用 PDM 数字接口输出,便于直接与 MCU 进行数据传输和后续数字信号处理。

工作原理

MEMS麦克风通常采用微机械结构(如悬臂梁或振膜)来感应声波引起的压力变化。外界声压使振膜产生微小位移,进而改变与固定板之间的电容或电阻值。对于SPH0641LM4H1来说,其内部集成了声学传感元件和放大电路,经过机械-电转换后产生数字信号(常见输出格式为PDM,即脉冲密度调制)。这种数字输出方式不仅便于抗干扰和后续数字信号处理,而且大大简化了系统设计中模拟信号的调理过程。

image.png

编码原理

PDM(脉冲密度调制)是一种数字音频编码技术,常用于MEMS麦克风的数字输出。其基本原理是将模拟音频信号转换为一串单比特(1位)数据流,通过脉冲的密度来反映原始音频信号的幅度信息。如下图就是将正弦信号用PDM编码后的波形。

image.png

  • 单比特数据流:
    PDM将连续的模拟信号转换成一个高速的单比特流。信号在高采样率(通常远高于音频信号带宽)的条件下,输出的每个脉冲只有“1”或“0”两个状态。
  • 脉冲密度与信号幅值:
    在PDM中,信号的幅值由脉冲“1”的比例决定。简单来说,当原始音频信号较大时,高采样率下输出“1”的密度也会较高;而当信号较小时,输出“1”的比例较低。通过对整个数据流进行低通滤波,可以重构出近似的原始模拟波形。

在MEMS麦克风内部,声学振膜检测到的声音信号首先经过模拟前端放大和调理,然后通过ADC进行采样。但与传统的多比特ADC不同,PDM技术通常采用ΔΣ(Delta-Sigma)调制器结构。ΔΣ调制器通过在超高采样率下不断比较信号与反馈信号,将模拟信号量化为1位数据流。调制器内部的噪声整形技术将量化噪声推向高频区域,从而在音频带宽内实现较高的信噪比。

而接收方的解调工作就是还原出原始的音频信号,需要通过低通滤波器来进行数字滤波,将高频的量化噪声滤除,同时保留原始音频信号的低频部分。经过低通滤波后的数据再进行降采样处理,生成符合音频标准采样率的多比特PCM数据流,供后续的音频处理和播放使用。

当然这个方案也并非十全十美,受限于微机械结构,部分MEMS麦克风在极低频段(低于100 Hz)响应较弱,可能影响录制背景音乐或低频环境音的还原。

为了方便测试,所以我设计了一个小PCB板,预留出了时钟和信号管脚,并且为了维持供电,板子上集成了一个LDO电源芯片。

image.png

image.png

1fda40bb197728c3408c878b0e7ceb9.jpg

原理图/PCB/实物图

软件实现

由于PDM编码格式已经被各大主流微控制器厂商的芯片支持,所以并不需要写复杂的驱动或者转换程序就可以完成读取。在这里我选择了对我来说最方便的开发工具,MCUXpresso IDE软件,并搭配FRDM-RW612开发板,从图中可以看出这个板卡扩展功能很多,尤其是对多媒体的支持很好。

image.png

对软件进行改造就可以完成从PDM信号到USB数据的采集。.

//PDM设备初始化​
void Board_DMIC_DMA_Init(void)
{
    dmic_channel_config_t dmic_channel_cfg;

    DMA_Init(DEMO_DMA);

    DMA_EnableChannel(DEMO_DMA, DEMO_DMIC_RX_CHANNEL);
    DMA_SetChannelPriority(DEMO_DMA, DEMO_DMIC_RX_CHANNEL, kDMA_ChannelPriority2);
    DMA_CreateHandle(&s_dmicRxDmaHandle, DEMO_DMA, DEMO_DMIC_RX_CHANNEL);

    memset(&dmic_channel_cfg, 0U, sizeof(dmic_channel_config_t));

    dmic_channel_cfg.divhfclk            = kDMIC_PdmDiv1;
    dmic_channel_cfg.osr                 = DEMO_DMIC_OSR;
    dmic_channel_cfg.gainshft            = 3U;
    dmic_channel_cfg.preac2coef          = kDMIC_CompValueZero;
    dmic_channel_cfg.preac4coef          = kDMIC_CompValueZero;
    dmic_channel_cfg.dc_cut_level        = kDMIC_DcCut155;
    dmic_channel_cfg.post_dc_gain_reduce = 1U;
    dmic_channel_cfg.saturate16bit       = 1U;
    dmic_channel_cfg.sample_rate         = kDMIC_PhyFullSpeed;
    DMIC_Init(DMIC0);
#if !(defined(FSL_FEATURE_DMIC_HAS_NO_IOCFG) && FSL_FEATURE_DMIC_HAS_NO_IOCFG)
    DMIC_SetIOCFG(DMIC0, kDMIC_PdmDual);
#endif
    DMIC_Use2fs(DMIC0, true);
    DMIC_EnableChannelDma(DMIC0, DEMO_DMIC_CHANNEL, true);
    DMIC_ConfigChannel(DMIC0, DEMO_DMIC_CHANNEL, kDMIC_Left, &dmic_channel_cfg);

    /* FIFO disabled */
    DMIC_FifoChannel(DMIC0, DEMO_DMIC_CHANNEL, FIFO_DEPTH, true, true);
    DMIC_EnableChannnel(DMIC0, DEMO_DMIC_CHANNEL_ENABLE);

    DMIC_TransferCreateHandleDMA(DMIC0, &s_dmicDmaHandle, dmic_Callback, NULL, &s_dmicRxDmaHandle);
    DMIC_InstallDMADescriptorMemory(&s_dmicDmaHandle, s_dmaDescriptorPingpong, 2U);
    DMIC_TransferReceiveDMA(DMIC0, &s_dmicDmaHandle, s_receiveXfer, DEMO_DMIC_CHANNEL);
}
//USB发送
if (USB_AUDIO_STREAM_INTERFACE_INDEX == interface)
{
    if (alternateSetting < USB_AUDIO_GENERATOR_STREAM_INTERFACE_ALTERNATE_COUNT)
    {
        s_audioGenerator.currentInterfaceAlternateSetting[interface] = alternateSetting;
        error                                                        = kStatus_USB_Success;
       if (USB_AUDIO_GENERATOR_STREAM_INTERFACE_ALTERNATE_1 == alternateSetting)
        {
             USB_AudioRecorderGetBuffer(s_wavBuff, (USB_SPEED_HIGH == s_audioGenerator.speed) ?
                                                                      HS_ISO_IN_ENDP_PACKET_SIZE :
                                                                      FS_ISO_IN_ENDP_PACKET_SIZE);
              error = USB_DeviceAudioSend(
                      s_audioGenerator.audioHandle, USB_AUDIO_STREAM_ENDPOINT, s_wavBuff,
                      (USB_SPEED_HIGH == s_audioGenerator.speed) ? HS_ISO_IN_ENDP_PACKET_SIZE :
                                                                    FS_ISO_IN_ENDP_PACKET_SIZE);
        }
    }
}

实现效果由于是音频,图片只能展示出底噪还是很小的,声音效果可以听一下视频中录制的对比

image.png

需要注意的是,由于采样率目前使用了16K,所以8K以下的信号被保留,听起来声音可能会缺少一些高频,这留给我未来去深入研究USB的传输机制,未来升级这个设备。

总结与心得

感谢主办方组织了一次很好的活动,我在这次活动中我学习了麦克风的原理,并且购买到了芯片,配合手中的板卡把它们组合在一起,实现了一个小小的设计!

参考文档

  • MCUXpresso SDK文档: 包含了USB音频类设备的驱动说明和示例代码,详细介绍了如何配置USB主机模式以及如何处理音频数据。
  • FRDM-MCXN947用户手册: 介绍了开发板的硬件接口、引脚分配以及USB接口的使用说明。
  • NXP官网技术资源: 提供了针对USB音频应用的参考设计和应用笔记,可作为项目开发的技术支持资料。


附件下载
PCB.zip
PCB设计文件
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号