数字麦克风PDM信号采集与STM32 I2S接口应用(三)
本文是数字麦克风笔记文章的数据处理篇。
读取数字麦克风的信号,需要嵌入式驱动和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端接收到的文件为:
(传输附件很不方便,直接复制数据到这里了,拷贝到本地重命名之后就可以运行后面的分析程序,听一听声音,保真度还是很高的,音频是一句海阔天空的歌)