STM32 I2S Interface With A MEMS Microphone

I’ve started using STMicroelectronics STM32 microcontrollers in my client’s embedded applications. Recently I needed to interface an STM32G0x0 MCU with a Knowles SPH0645LM4H-1 MEMS microphone using I2S interface.

The STM32G0x0 MCU is an entry level, 32-bit Arm® Cortext®-M0+ MCU that runs up to 64MHz. This MCU series is cost effective and part of the ST STM32 value line. My client selected the STM32G030F6, which has 32Kbytes of Flash and 8Kbytes of RAM packaged in a 20-pin TSSOP. This MCU has I2C, USART, SPI/I2S communication interfaces, a 12-bit ADC, multiple GPIOs, timers, DMA, and RTC.

The Knowles SPH0645LM4H-1 is a miniature, low power, bottom ported MEMS microphone with a 24-bit I2S standard digital interface. The microphone supports 16kHz to 64kHz sampling. This microphone can be configured for either a right or left channel by an external signal. The key microphone feature is the output is already in PCM format so no additional CODEC hardware or PDM firmware conversion is needed in this application.

I2S (Inter-IC Sound) is a serial bus communication standard used for communicating with digital audio devices. Philip Semiconductor introduced the standard in 1986. The interface has three signals, serial clock (SCLK), word select (WS) and serial data (SD). SCLK is a continuous signal and is 32 or 64 times the audio sample rate based on word size. For example working with 32-bit data frames for a 16KHz audio, SCLK is 2 (audio words left and right) x 32-bits (size of each audio word) x 16kHz (sample rate) = 1.024MHz. WS is used to select left (low) and right (high) channel. SD is the audio data that is either 16 or 32 bit data word. Below is the I2S SCLK/WS/SD relationships from the Knowles datasheet. The Knowles data is 24-bit left shifted in a 32-bit word format.

STM32G030F6 I2S Setup

The STMicroelectronics development environment, STM32CubeIDE, has a configuration tool to setup the STM32 I/O as well as to set the clock configuration. Once you setup the hardware components this tool generates the support code and data structures.

For this application the Multimedia I2S1 interface to configuration for half-duplex master mode. This has the STM32 send the SCLK and WS signals and can either send or received data (half-duplex).

The I2S parameter setup configurations the transmission mode, communication standard, data and frame format, audio frequency, and the clock polarity. In our application the transmission mode is Mode Master Receive since the processor is the master and the microphone is the data source.

For the communication standard the selections include I2S Philips, MSB First, LSB First, and a couple of PCM framing selections. Originally I used the MSB first standard but discovered that the data was under shifted (MSB was bit 30 not 31 as expected). A look at the STM32 reference manual showed why.

The STMicroelectronics RM0454 Reference Manual (rev 5) shows waveforms for both the I2S Philips standard the MSB justified formats. Both the I2S Philips and the MSB justified framing sets WS on the falling clock edge. In the I2S Philips standard data changes on the next rising SCLK edge and read on the falling edge creating a null 1/2 bit time before the first data bit. With MSB justified format there is no gap. Data changes on the SCLK falling edge along with WS and read on the next rising edge. By using the MSB justified format the STM32 read the first bit before being transmitted by the microphone.

Below is the I2S interface measured with an oscilloscope (channel 1 = SCLK, channel 2 = WS, channel 3 = SD). It is clear that WS changes to the left channel on the falling edge of SCLK and the first data bit from the microphone appears on the next rising edge.

Next is to configure the Data and Frame Format. The SPH0645LM4H-1 data format is 24-bits in a 32-bit frame. Of the 24-bits only the most significant 18-bits are valid and the remaining bits (lowest 6-bits of the 24-bit word) are set to zero by the microphone. The remaining data byte (8-bits) are tri-stated and with a 100K pulldown resistors are read as zero by the STM32. Our choice must include a 32 Bits Frame since that is the output of the microphone, but we can select 16, 24, or 32 data bits.

The 24 and 32-bit choices requires two reads from the receive data register while using 16-bits of data in a 32-bit frame requires only 1 read and the second 16-bits are automatically set to zero. For this test I selected 16-bits in a 32-bit frame.

The code is very simple when using the provide blocking call to receive I2S data. The call is made to HAL_I2S_Receive, which takes the I2S handle pointer created by the auto code generation tools when configuring the processor, a pointer to a data buffer, the number of samples, and a timeout value. Since the I2S interface is designed for a left and right channel, 2 samples are selected.

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	volatile HAL_StatusTypeDef result = HAL_I2S_Receive(&hi2s1, (uint16_t *)&dataIn[0], 2, 100);
	if(result != HAL_OK) {
		printf("Error Code %08lX\n", HAL_I2S_GetError(&hi2s1));
	}
  }
  /* USER CODE END 3 */

Below is a screen shot showing the Live Expressions window for the data buffer. Note that dataIn[0] is our left channel and dataIn[1] is our right channel and is always 0 since we don’t have a another sensor attached.

From the single blocking read, there isn’t much time to processed the received I2S data. With two channels at 16kHz there is only 15.625 microseconds (16kHz x 4 16-bit words = 64kHz) before the next 16-bit data word is ready at the input SPI/I2S register. That is just 1,000 CPU clock cycles at 64MHz maximum clock rate. Just trying to convert the read integer to a string caused data overflow errors (sprintf is a very, very slow function). With an overflow error you miss some real-time data and the data may shift within the data buffer (i.e., left channel moved to dataIn[1]).

A safer approach to processing incoming audio stream data is to use DMA where data is read from the microphone and placed directly into memory without the CPU. The STM32 programming environment provides support for a continuous circular buffer with interrupt callbacks for buffer half full and completely full. The image below shows the DMA data buffer. Note that all right channel data is zero.

For the I2S DMA test I counted each buffer related interrupt and performed a timing analysis to verify continuous data was being read from the MEMS microphone at the realized audio sampling rate (slightly different than the desired audio rate due to processor clock tree).

Overall the STMicroelectronics STM32CubeIDE tool make the developer’s job easier with the hardware configuration interface and auto hardware abstraction layer (HAL) code and data structures generation.

Leave a Reply