WavePlayer using STM32 Discovery

This tutorial will cover how to make WavePlayer using STM32 Discovery board. This player will be able to play the wave files from the USB device. The peripherals that we are going to use are as follows: I2S (Inter IC Sound), I2C, FATFS and USB HOST


The code Works alright for F4 Discovery board. You will get some error with PLLI2SN. Just comment out those 2 lines and it will be fine.

CubeMX Setup

Below is the picture of the schematics of the Discovery board that I am using for this project. I will setup all the peripherals according to their connection with the CS43L22 IC

I2C Peripheral

First of all I am setting the I2C Peripheral as shown below

Here I needed to change the default SDA pin (PB7) to PB9, since that’s the one connected to the IC

I2S peripheral

After I2C, its time to setup the I2S peripheral

Make sure you select all the pins as shown in the schematics

  • PC12 -> I2S3_SD
  • PC10 -> I2S3_CK
  • PC7 -> I2S3_MCK
  • PA4 -> I2S3_WS

Here we also need to enable the DMA as shown below

DMA is selected in circular mode, and Data Width is Half width since we will be dealing with 16 bits.


Next we need to enable the USB HOST, so that we can read the audio files from the USB

Also make sure you activate the VBUS, as the USB devices mostly don’t have the Power supply, and that’s why HOST is responsible to provide the required power to such devices.

Next, select the USB_HOST and select the class as Mass Storage Class. Leave everything here to default.

And now we need to enable the voltage supply to the VBUS pin. To do that you need to look at the user manual for your board. I am using STM32F4 discovery board, and it have the following diagram for the USB

As you can see above, the VBUS is powered from the PC0 pin. But PC0 is connected to the EN Pin, which is an active Low pin. This means in order to supply the voltage to the VBUS, we must Pull down the PC0 Pin, or basically Set it LOW.

Also enable the PC0 in the Platform Settings as shown above

FAT File System

Now we will setup the FAT File System

Select the USB Disk Mode, and leave everything to default here. I have enabled the use of Long Filename just in case if I have files with long names

And finally I am using PA0 as the external interrupt key. This is to control the operations in Player like NEXT, PREVIOUS, PAUSE, RESUME etc

Some Insight into the CODE

We need to copy the respective library files into the src, and the inc folders. The final image of these libraries is shown below

The underlined files are the libraries that you need to include in your project. You can download them at the end of this post


First of all we need to include the header files in our main file. We will be using functions only from waveplayer.h and File_Handling.h files

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "waveplayer.h"
#include "File_Handling.h"

/* USER CODE END Includes */

Next, we will define the functions to check the USB state, and the AUDIO state

extern ApplicationTypeDef Appli_state;
extern AUDIO_PLAYBACK_StateTypeDef AudioState;

int IsFinished = 0;

ApplicationTypeDef Appli_state is the already defined in usb_host.c file, and that’s why we need to declare it as an extern. USB can have the following states


AUDIO_PLAYBACK_StateTypeDef AudioState is defined in the waveplayer.c file, and it have the following states


Other then these, I have also define a variable IsFinished to check if the AUDIO playback is stopped.

Interrupt Callback

Now we will write an external interrupt callback for the button

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
	if (GPIO_Pin == GPIO_PIN_0)
//		AudioState = AUDIO_STATE_NEXT;
		if (AudioState == AUDIO_STATE_PLAY)
			AudioState = AUDIO_STATE_PAUSE;

		if (AudioState == AUDIO_STATE_WAIT)

Here we can control what the button will do. In the code above, the button is programmed to PAUSE, and RESUME the audio

Main function

Our main code will be written inside the while loop

  while (1)

    /* USER CODE BEGIN 3 */

    if (Appli_state == APPLICATION_READY)

    	while (!IsFinished)

    		if (AudioState == AUDIO_STATE_STOP)
    			IsFinished = 1;


In the code above, first we will continuously check if the USB is ready for communication. Once it is ready

  • Mount the USB
  • Start the Audio Player. The parameter is the index of the track (song) that you want to start playing with
  • AUDIO_PLAYER_Process will keep processing the AUDIO until it is stopped. It takes the parameter “isLoop“, which means do you want the loop the AUDIO ? If set TRUE, the 1st track will play after the last track, or in case of FALSE, the player will stop after the last track
  • If the AUDIO state is STOP, the IsFinished will be set to 1, and the processing will STOP


Check out the Video Below


You can help with the development by DONATING
To download the code, click DOWNLOAD button and view the Ad. The project will download after the Ad is finished.

12 Comments. Leave new

  • Hello, I saw in the video that you did not connect the pins on the kit. I followed the instructions and plugged the headphones into the 3.5 jack on the kit but I can’t hear music. Can I ask if I2S module is needed to amplify the sound and do you have any solution for my problem?
    Thank you.

  • Hi ,
    do you have code example for I2S slave where it uses external clock (STM32F407) Disc board

  • think there is a minor issue in the code. In Audio.c, AUDIO_OUT_MspInit, the DMA is configured in normal mode, but I believe the DMA needs it to be in circular mode. I am guessing the only reason it works is that AUDIO_OUT_MspInit probably does not get called in AUDIO_OUT_Init due to the if statement checking if I2S is in reset state. Since the DMA is initialized in stm32f4xx_hal_msp.c into circular mode. Am I understanding this right?

  • I have an STM32F407-DISCOVERY board and as from what I checked is equal the pinout with the one you’re using… my question is if the code will work correctly?

  • Hello ,
    how can i contact you ?
    on email or ??
    Thanks in advance.

  • sorry but i failed at error: ‘RCC_PLLI2SInitTypeDef {aka struct <anonymous>}’ has no member named ‘PLLI2SM’; did you mean ‘PLLI2SN’?


  • Such a nice work u have done sir.
    It would be more perfect if you make a tutorial of sound recording using STM32.
    Love ur job


Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.


Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add controllerstech.com to your ad blocking whitelist or disable your adblocking software.