本文是数字麦克风笔记文章的数据处理篇。

  读取数字麦克风的信号,需要嵌入式驱动和PC应用的结合,驱动负责信号采集,应用代码负责声音分析。

  一般而言,在完成特征分析和实验之后,把优化过的代码固化到嵌入式端,实现目标应用。本文记录了分析过程的一些基本步骤。

1、ARM驱动

使用STM32F4芯片,驱动使用ST-CUBE MX生成,节约了大量的时间。

1)GPIO

2)I2S配置

目标是16khz音频采样,这里选择为32khz的I2S频率,原因上一篇文章已经阐述了,计算方法为32khz*2*16/64=16khz。

3)DMA配置

 4)系统时钟配置

 

 5)I2S驱动编写

复制代码
/* I2S2 init function */void MX_I2S2_Init(void) {    hi2s2.Instance = SPI2;   hi2s2.Init.Mode = I2S_MODE_MASTER_RX;   hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;   hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;   hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;   hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_32K;   hi2s2.Init.CPOL = I2S_CPOL_HIGH;//I2S_CPOL_LOW;  hi2s2.Init.ClockSource = I2S_CLOCK_PLL;   hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;   if (HAL_I2S_Init(&hi2s2) != HAL_OK)   {     Error_Handler();   } }
复制代码

6)PDM2PCM配置

  ST公司提供PDM2PCM的解码包,在cube下载驱动即可,使用方式参考UM2372。抽样因子选择64。

  由于PDM的采样率为32khz*2=64khz,而目标PCM信号的频率设定目标为16khz,所以4个PDM数据将产生1个PCM数据,所以申请内存空间时候需要注意这个比例关系。

  首先配置PDM函数的参数。

复制代码
PDMFilter_InitStruct Filter; #define PDM_SAM_POINTS  (640) #define PCM_SAM_POINTS  (160) // 16khz频率,10ms数据160个采样点/* Filter LP & HP Init */ Filter.LP_HZ = 7500; Filter.HP_HZ = 100; Filter.Fs = 16000; Filter.Out_MicChannels = 1; Filter.In_MicChannels = 1; PDM_Filter_Init((PDMFilter_InitStruct *)&Filter);
复制代码

PDM函数驱动原型为:

int32_t PDM_Filter_64_LSB(uint8_t* data, uint16_t* dataOut, uint16_t MicGain,  PDMFilter_InitStruct * Filter);

其中因为PDM处理的是按byte处理,而STM32 DMA接收的数据是u16类型,所有需要颠倒下字节顺序。

复制代码
for(int i=0; i<PDM_SAM_POINTS; i++) {   uint16_t a = srcBuf[i];   srcBuf[i] = HTONS(a); }
复制代码

代码中调用驱动函数。

PDM_Filter_64_LSB((uint8_t *)&srcBuf[i], (uint16_t *)&dstBuf[i/4], volumeGain , (PDMFilter_InitStruct *)&Filter);

7)数据发送

复制代码
if(USBD_OK != CDC_Transmit_FS((uint8_t *)dstBuf,  2*PCM_SAM_POINTS) ) {   UsbTxErr++; }
复制代码

使用DMA接收数据,使用USB CDC传输。PC端接收到的文件为:

 

 (传输附件很不方便,直接复制数据到这里了,拷贝到本地重命名之后就可以运行后面的分析程序,听一听声音,保真度还是很高的,音频是一句海阔天空的歌)