STM32F4 DISCOVERY board and MEMS microphone MP45DT02
This is a repost of a couple of submissions I made on the ST Community site. It seems they are not searchable on the site, nor on Google, so I will republish them here in the hope to make them more visible.
I wanted to configure the I2S peripheral for the microphone MP45DT02 mounted on the STM32F4DISCOVERY board using STM32CubeMX and HAL. When searching for information regarding this I came across a couple of errors in the ST documentation I would like to point out, and at the same time give some hints on how to correctly capture audio data from the microphone. If I have made any mistakes I hope to be corrected.
In  the "Data and Frame Format" for the I2S peripheral is set to "16 Bits Data on 32 Bits Frame" which I think is wrong. With "16 Bits Data on 16 Bits Frame" and an audio frequency of 16KHz, the data capturing rate in the peripheral will be 2*16 bits @ 16KHz and the I2S clock will oscillate with 2*16*16000 Hz. When the frame is extended to 32 bits the I2S clock will double its frequency to 2*32*16000 Hz, but the data capturing rate in the peripheral will not change. It is still 2*16 bits @ 16KHz. This means every other 16 bits of data coming from the microphone will be dropped as the pheripheral assumes they are zero. This is not what you want. I decided to use "32 Bits Data on 32 Bits Frame" to get a data aquisition rate of 2*32 bits @ 16KHz, i.e. 64 times oversampling.
This leads us to the next documentation error in . When capturing 16 bits of data per frame, regardless of frame size, the size parameter is the number of 16 bit halfwords that will be captured. So far so good. When capturing 24 or 32 bits of data per frame the size parameter is the number of 32 bit words that will be captured, i.e. twice the number of 16 bit halfwords. This is not clearly expressed in the documentation of the function.
Setting the DMA channel to Circular will automatically restart the capture at the end of the buffer. To be able to work on stable data at the same time as the capturing is ongoing I use both the HAL_I2S_RxHalfCpltCallback() and HAL_I2S_RxCpltCallback(), each working on the part of the capturing buffer that is not currently being filled.
~ ~ ~
I thought I needed DMA double buffering as well and investigated how to get it to work. The HAL DMA module actually supports double buffering, but the HAL I2S module has no function to start a double buffer DMA transfer. I modified HAL_I2S_Receive_DMA() to work with double buffers and got it to work, but then I realized that HAL_I2S_RxHalfCpltCallback() can be used to accomplish the same thing and reverted my changes.
Yes, it is a PDM mono microphone which means you can't use the data as PCM samples directly. The data have to be filtered and decimated 64 times to become 16kHz PCM.