数字麦克风PDM信号采集与STM32 I2S接口应用(二)
在使用STM32的数字麦克风I2S接口时,计算采样率让人头疼,芯片手册上没有明确的说法,而手册上的计算方法经过测试却和实验不符。借助搜索引擎,大部分资料都是来自于开发板卖家或开发板论坛,主要是咪头采集然后配置WM89系列解码芯片,然后配合FatFS、MP3解码等模式,主要是讲解I2S录音、存储、放音等。外文资料得到的也寥寥无几,也没有找到讲解STM32数字麦克风配置、计算的文档。加上网上资料转载、抄袭、浅尝辄止的笔记教程,这些更是让检索大海捞针,过程艰辛一言难尽,有些网文三言两语抑或作者都没有搞清楚随手一写,有些是作者搞清楚了但藏着掖着最关键的点没说,有些是跟着别人现成的教程做了一边又写了一篇笔记却没有增加任何新东西,种种缘由搞得技术圈文章氛围差到极点让人恼火。
我的需求是音频特征点检测,所以把声音录制然后传输到PC上是首要任务,经过多次摸索,终于了解一二,现在分享出来方便后来者,恐水平有限有未发现的错误而误导他人,在文尾附上STM32 I2S和PDM采集相关的原厂资料以作参考。
尽管内容庞杂,但争取化繁为简讲清楚数字麦克风单声道模式的PDM信号采集,PDM到PCM解码,以及上位机验证分析如python/matlab脚本读取录音文件和播放,频谱分析等。
1、 STM32 I2S接口标准和数据格式
这些内容参考STM32芯片编程手册,基本上就是4个模式,以及16位32位数据格式,若使用SPI/I2S接口通信还要有MSB、LSB配置。

2、 STM32 I2S采样率的配置
STM32的时钟配置和数据格式决定了音频信号的采样率,如下计算。在使用了ST CUBE MX后,下面的计算过程也省略了,直接配置传感器的数据格式、接口标准、采样率就可以了。

上面是STM32芯片手册给出的信息,在做音频采集时候,发现这和实测效果相差较远,原来这组公式并不适合PDM信号的数字麦克风。PDM麦克风只是利用了STM32的I2S信号时钟和数据线,它的采样只是按照bit采样,每一个sample为1bit,要转换为类似于AD/DA的采样值,还需要进行PDM2PCM转换,ST给出了一个驱动包,可以进行类似转换,可以参考AM3998和UM2372手册。
下面的公式才是PDM麦克风与STM32 I2S接口配合时使用的采样率计算方法,其中FS是PDM bit sample的采样率,DIV是PDM到PCM的抽样因子,经过抽样,把bit sample变为类似于模拟采样的sample。这里的Fs都是指采样sample的速率,虽然PDM输出是以u16或u32方式呈现的,但其采样率是按照bit计算的,一个sample只有1个bit。

例如下面的配置,PDM采样率为32khz,单声道应用,那么PDM2PCM使用64抽取比,则真实的音频采样率为16*2*32khz/64 = 16khz。
/* I2S2 init function */
void MX_I2S2_Init(void)
{
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
hi2s2.Init.Standard = I2S_STANDARD_MSB;
hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
hi2s2.Init.MCLKOutput =
I2S_MCLKOUTPUT_DISABLE;
hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_32K;
hi2s2.Init.CPOL = I2S_CPOL_LOW;
hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
hi2s2.Init.FullDuplexMode =
I2S_FULLDUPLEXMODE_DISABLE;
if (HAL_I2S_Init(&hi2s2) != HAL_OK)
{
Error_Handler();
}
}
此时PDM的时钟频率为32khz*16*2=1024khz,测量结果如下验证了该分析结论。

STM32F407的I2S IP核是按照左右声道来处理音频信号的,所以其SW脚信号频率为32khz。

3、PDM和PCM信号
PDM调制器将缓冲模拟信号转换为串行脉冲密度调制信号,时钟输入( CLK)用于控制PDM调制器。PDM信号无法直接驱动DA进行声音播放,PDM信号要变为声音信号还需要进行下采样,经过一次低通滤波和抽样,然后成为PCM信号。
PDM是一种调制形式,用于表示数字域中的模拟信号。它是1位数字采样的高频数据流。在PDM信号中,脉冲的相对密度对应于模拟信号的幅度。大量的1s对应于高(正)幅度值,而大量的0s对应于低(负)幅度值,交替的1s和0s对应于幅度值0。

PDM转为PCM信号,需要进行滤波和抽取。PDM信号采样率就是I2S的clk时钟频率,可见这是一个高频采样,按bit采样的信号。PCM信号是目标音频的采样率,比如高保真44khz,PDM2PCM的抽样因子M,则M=PDM频率/音频采样率。

ST 提过了PDM2PCM的软件包,可以完成上面的工作。
软件包源码没有开源,使用手册也简洁的让人抓狂,我觉得可能是因为ST更高级的MCU直接带了硬解码,所以对中低端MCU I2S接口的软解码关注度也不够。幸好之前做过信号处理工作,一些概念和内在逻辑能猜个八九不离十,使用起来没有任何难度就上手了,这个软件包使用时需要配置下面几个参数。
1)初始化PDMFilter,包括采样率,低通高通滤波器截止频率,通道个数。
typedef struct {
uint16_t Fs;
float LP_HZ;
float HP_HZ;
uint16_t Out_MicChannels;
char InternalFilter[];
} PDMFilter_InitStruct;
2)完成参数初始化后调用滤波器初始化函数。
Void PDM_Filter_Init (PDMFilter_InitStruct * Filter)
3)最后调用下面函数完成PDM2PCM的抽取。
PDM_Filter_XX_XX(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter)
ST提供了多种PDM2PCM的抽取方法。
int32_t PDM_Filter_64_MSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter);
int32_t PDM_Filter_80_MSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter);
int32_t PDM_Filter_64_LSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter);
int32_t PDM_Filter_80_LSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain, PDMFilter_InitStruct * Filter);
参考文档:
1、如何将PDM数字麦克风连接到STM32单片机
AN5027 使用STM32 32位Arm® Cortex® MCU连接PDM数字麦克风
2、 PDM audio software decoding on STM32 microcontrollers
3、 UM2372_用于STM32F4_F7_H7的PDM2PCM软件包介绍
STM32Cube PDM2PCM software library for the STM32F4/F7/H7 Series
4、 基于 STM32 I2S 的音频应用开发介绍
数字麦克风PDM信号采集与STM32 I2S接口应用--笔记目录:
数字麦克风PDM信号采集与STM32 I2S接口应用(一)
https://www.cnblogs.com/pingwen/p/11298675.html
数字麦克风PDM信号采集与STM32 I2S接口应用(二)
https://www.cnblogs.com/pingwen/p/11301935.html
数字麦克风PDM信号采集与STM32 I2S接口应用(三)
https://www.cnblogs.com/pingwen/p/11794081.html
数字麦克风PDM转PCM与STM32 I2S接口应用----重要文档列表
https://www.cnblogs.com/pingwen/p/11302452.html
尊重原创技术文章,转载请注明。
数字麦克风PDM信号采集与STM32 I2S接口应用(二)的更多相关文章
- 数字麦克风PDM信号采集与STM32 I2S接口应用
数字麦克风采用MEMS技术,将声波信号转换为数字采样信号,由单芯片实现采样量化编码,一般而言数字麦克风的输出有PDM麦克风和PCM麦克风,由于PDM麦克风结构.工艺简单而大量应用,在使用中要注意这二者 ...
- 数字麦克风PDM信号采集与STM32 I2S接口应用--笔记目录
数字麦克风采用MEMS技术,将声波信号转换为数字采样信号,由单芯片实现采样量化编码,一般而言数字麦克风的输出有PDM麦克风和PCM麦克风,由于PDM麦克风结构.工艺简单而大量应用,在使用中要注意这二者 ...
- 数字麦克风PDM信号采集与STM32 I2S接口应用(四)--单片机源码
本文是数字麦克风笔记文章的单片机程序.一些朋友私信我,调试出问题. 我就把源码贴出来吧,可能主要问题是DMA的配置. 尤其双DMA时候,需要手动启动I2S的接收DMA,HAL库没有这个接口,不看dat ...
- 数字麦克风PDM信号采集与STM32 I2S接口应用(三)
本文是数字麦克风笔记文章的数据处理篇. 读取数字麦克风的信号,需要嵌入式驱动和PC应用的结合,驱动负责信号采集,应用代码负责声音分析. 一般而言,在完成特征分析和实验之后,把优化过的代码固化到嵌入式端 ...
- 数字麦克风PDM转PCM与STM32 I2S接口应用----重要文档列表
数字麦克风PDM脉冲到PCM信号需要一个二次采样,ST 提过了PDM2PCM的软件包,可以完成上面的工作.软件包源码没有开源,使用手册也简洁的让人抓狂,我觉得可能是因为ST更高级的MCU直接带了硬解码 ...
- ADI高速信号采集芯片与JESD204B接口简介
ADI高速信号采集芯片与JESD204B接口简介 JESD204B接口 介绍: JEDEC Standard No. 204B (JESD204B)—A standardized serial int ...
- 4~20mA信号采集
4-20mA信号采集 4-20mA信号采集可选卓岚ZLAN6802(485)/ZLAN6842(以太网)/ZLAN6844(无线wifi)他们不仅可以可采集4~20mA还可以采集 /0~5V/0~10 ...
- ESP8266 软件实现 Delta-sigma(ΔΣ)调制器 并通过I2S接口输出编码流
一.关于Delta-sigma(ΔΣ)调制器 Delta-sigma(ΔΣ)调制器是Delta-sigma转换器的核心部件.如下所示为一个简单的一阶Delta-sigma调制器,该调制器产生一个1bi ...
- I2S接口介绍
I2S接口介绍一.I2S协议介绍 I2S协议作为音频数据传输协议,由Philips制定.该协议由三条数据线组成:1.SCLK:串行时钟,频率= 2 * 采样频率 * 采样位数.2.WS:字段(声道)选 ...
随机推荐
- Fabric1.4源码解析:Peer节点加入通道
又开始新的阅读了,这次看的是Peer节点加入通道的过程.其实每次看源码都会有好多没有看懂的地方,不过相信只要坚持下去,保持记录,还是有很多收获的. 对于Peer节点加入通道这一 ...
- CPP常用库函数以及STL
其他操作 memset void * memset ( void * ptr, int value, size_t num ); memset(ptr,0xff,sizeof(ptr)); 使用mem ...
- 多语言应用性能监控系统:Elastic APM
▶ 概述 Elastic APM 是基于 Elastic Stack 构建的应用性能监控系统.通过 Elastic APM 可以监控应用程序,收集有关请求的响应时间.数据库查询.高速缓存调用.外部 H ...
- 线性模型之LDA和PCA推导
线性模型之LDA和PCA 线性判别分析LDA LDA是一种无监督学习的降维技术. 思想:投影后类内方差最小,类间方差最大,即期望同类实例投影后的协方差尽可能小,异类实例的投影后的类中心距离尽量大. 二 ...
- 学习 GitHub 有什么好处?
layout: post title: "学习 GitHub 有什么好处?" date: 2018-04-15 19:20:20 +0800 --- 鸣谢:王顶 老师(河北经贸大学 ...
- 1.Solr安装与配置
1.Solr安装 1:安装 Tomcat,解压缩即可. 2:解压 solr. 3:把 solr 下的dist目录solr-4.10.3.war部署到 Tomcat\webapps下(去掉版本号). 4 ...
- Spring Cloud Alibaba | 序言
目录 Spring Cloud Alibaba | 序言 1. Spring Cloud Alibaba是什么? 2. 主要功能 3. 组件 4. 版本说明 4.1 版本依赖关系 4.2 组件版本关系 ...
- vue-cli · Failed to download repo vuejs-templates/webpack: self signed certificate in certificate chain
vue init webpack <Project name> 报错: vue-cli · Failed to download repo vuejs-templates/webpack: ...
- 使用wincc vbs脚本查找进程及如何运行进程
使用vbs代码查看某个进程是否在运行,本文要检查的进程名为 QRscan.exe,其代码如下: sub CheckProcess Dim WMI,Objs,Process,ObjSet WMI=Get ...
- 多线程总结-同步之volatile关键字
目录 1 案例引出可见性 2 案例引出原子性 1 案例引出可见性 代码解析:新起一个子线程执行m()方法,1秒后主线程将b置为false,子线程是否会停止执行死循环while(b){},打印" ...