🛠 Lecture audio sur le codec CS43L22 : I2S, classe D et les limitations du BSP
Objective
The STM32F4DISCOVERY was marketed by ST as the board "for easily developing audio applications." The hardware is real: a CS43L22 codec (stereo DAC + class D amplifier for the speaker), a headphone jack, a speaker connector, and a digital microphone — all driven by the STM32F407VGT6. This tutorial plays a sound via the CubeF4 BSP and, more importantly, addresses its documented limitations, which explain 90% of disappointments.
Hardware Architecture
- Control: I2C1, device address 0x94, reset pin PD4; the BSP verifies the codec's presence by reading
CS43L22_ID. - Audio stream: I2S sends 16-bit stereo samples to the CS43L22; playback in the CubeF4 BSP uses I2S3, while microphone PDM capture uses I2S2.
- Official examples:
Projects/STM32F4-Discovery/in STM32CubeF4 (audio play/record demos).
BSP Limitations (Source: Known Limitations section)
- 16-bit stereo only: A mono file must be duplicated across both channels.
- Noise at low sampling rates: Low-quality files produce a "high and uncomfortable noise level" on the class D speaker — increase the rate to above 48 kHz.
- Possible I2C corruption: Communication with the CS43L22 can be corrupted if interrupted by user interrupt routines — keep ISRs short or mask interrupts around codec accesses.
- Volume and mute are handled by codec registers (
BSP_AUDIO_OUT_SetVolume,..._SetMute), not by the MCU. - Initialization fails if the ID read over I2C1 does not match: check the PD4 reset line before compiling.
Code Skeleton
#include "stm32f4_discovery.h"
#include "stm32f4_discovery_audio.h"
/* Buffer stereo 16 bits, 48 kHz mini pour eviter le bruit classe D */
static int16_t audioBuffer[2 * 480]; /* 10 ms de sine 440 Hz */
int main(void)
{
HAL_Init;
SystemClock_Config; /* 168 MHz */
/* Init codec : I2C1 addr 0x94, reset PD4, verif CS43L22_ID */
BSP_AUDIO_OUT_Init(AUDIO_FREQUENCY_48K, 70); /* volume 70 */
BSP_AUDIO_OUT_SetAudioFrameFilter(CODEC);
FillSine(audioBuffer, 480, 440, 48000); /* a ecrire : stereo 16b */
BSP_AUDIO_OUT_Play((uint16_t *)audioBuffer,
sizeof(audioBuffer)); /* DMA I2S circulaire */
while (BSP_AUDIO_OUT_Playing) { } /* attente fin */
BSP_AUDIO_OUT_Stop(CODEC_DURING);
}
Procedure
- Open the CubeF4 audio demo (
Projects/STM32F4-Discovery/) as a reference for I2S pinout. - Prepare your samples in 16-bit stereo, ≥ 48 kHz — convert with ffmpeg if needed (
-ac 2 -ar 48000 -sample_fmt s16). - Feed the buffer in circular mode via DMA and reload it in the half-transfer callback (
HalfTransfer) for a continuous stream. - Set the volume with
BSP_AUDIO_OUT_SetVolume; the headphone output and the speaker connector share the same DAC.
Expected Verification
A clean 440 Hz tone comes out of the speaker (or headphones). If you hear an unpleasant hissing sound, your sampling rate is too low — this is limitation #2, not a hardware defect. If the codec fails to initialize (invalid CS43L22_ID), check the PD4 reset line and address 0x94 on I2C1 with a logic analyzer.
Common Errors
- Playing mono without duplicating it: the BSP only accepts 16-bit stereo (limitations 4 and 5 of the BSP).
- Making
BSP_AUDIO_OUT_*calls inside a long ISR: the BSP warns that the codec's I2C can be corrupted by user interrupts. - Confusing the MP45DT02 microphone (PDM, capture on I2S2) with the playback codec: two distinct peripherals, two distinct initializations.
- Using PC7 (codec MCLK) as a free pin: it is engaged on the audio clock as long as the codec is active.
Other tutorials for this board
- Premier téléversement sur la STM32F4DISCOVERY avec l'Arduino STM32duino
- Zephyr RTOS sur la STM32F4DISCOVERY : west build et west flash
- MicroPython sur la STM32F4DISCOVERY : REPL interactif et pilotage des LED
- STM32Cube HAL et BSP officiel : LED, bouton et accéléromètre avec détection automatique
- USB OTG FS sur le port micro-AB : se faire passer pour un périphérique classe CDC
- Acquérir le micro PDM MP45DT02 : I2S2, filtre PDM-vers-PCM et contraintes de sortie