{"id":4503,"date":"2026-06-03T13:38:16","date_gmt":"2026-06-03T13:38:16","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4503"},"modified":"2026-06-03T13:38:19","modified_gmt":"2026-06-03T13:38:19","slug":"stm32f407-discovery-audio-configuring-and-transmitting-i2s-data-via-polling","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4503","title":{"rendered":"STM32F407 Discovery Audio: Configuring and Transmitting I2S Data via Polling"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-1024x559.png\" alt=\"\" class=\"wp-image-4504\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-1024x559.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-300x164.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-768x419.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-1150x627.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-750x409.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-400x218.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky-250x136.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/Gemini_Generated_Image_thkyp8thkyp8thky.png 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The I2S (Inter-IC Sound) peripheral on the STM32F407 Discovery board provides a dedicated, high-performance synchronous communication interface designed specifically for transmitting digital audio data to external codecs and DACs. This guide covers the foundational steps to understand the underlying I2S protocol architecture, properly configure the microcontroller&#8217;s hardware registers, and reliably transmit audio signals using efficient polling-based data transfer.<\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Introduction.<\/li>\n\n\n\n<li>STM32CubeMX setup.<\/li>\n\n\n\n<li>Importing the project to STM32CubeIDE.<\/li>\n\n\n\n<li>Firmware development.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1.1 Introduction:<\/h2>\n\n\n\n<p>The&nbsp;<strong>Inter-IC Sound (I2S)<\/strong>&nbsp;peripheral on the STM32F407 microcontroller is a specialized, synchronous serial interface designed for high-fidelity digital audio transfer. While sharing physical hardware resources with the standard SPI peripheral, the I2S block is uniquely optimized to handle continuous audio data streams. It implements precise clock synchronization using dedicated internal architecture to feed external components like the CS43L22 Audio DAC found on the STM32F407 Discovery board.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">       [ STM32F407 (Master) ]                  [ External DAC \/ Codec ]\n  +------------------------------+            +------------------------+\n  |                              |---&gt; CK ----&gt;| Continuous Serial Clock|\n  |  I2S Peripheral Engine       |---&gt; WS ----&gt;| Word Select (L\/R)      |\n  |  (Configured via Registers)  |---&gt; SD ----&gt;| Serial Data Stream     |\n  +------------------------------+            +------------------------+\n<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Core Concepts &amp; System Architecture<\/h3>\n\n\n\n<p>To successfully implement a polling-based driver, the implementation focuses on three core pillars:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Hardware Interface Architecture:<\/strong>\u00a0Understanding how the internal clock generation connects to the protocol logic. The peripheral relies on a dedicated audio PLL ($PLLI2S$) to guarantee precise sampling frequencies (such as\u00a0<strong>44.1 kHz<\/strong>\u00a0or\u00a0<strong>48 kHz<\/strong>) while minimizing clock jitter.<\/li>\n\n\n\n<li><strong>Register Configuration:<\/strong>\u00a0Setting up communication parameters directly via the hardware abstraction layers or register definitions. Key adjustments are handled in the configuration register (<code>SPI_I2SCFGR<\/code>) to set the master mode and selection protocol, and the prescaler register (<code>SPI_I2SPR<\/code>) to define the exact audio sample rate division.<\/li>\n\n\n\n<li><strong>Polling-Based Firmware Logic:<\/strong>\u00a0Using a straightforward, synchronous software loop to transmit data. The firmware continuously monitors the Transmit Buffer Empty (<code>TXE<\/code>) flag in the status register. Once the flag is set, the CPU immediately writes the next 16-bit audio sample into the Data Register (<code>DR<\/code>), ensuring an uninterrupted hardware stream without relying on interrupts or DMA.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1.2 Feature Of I2S in STM32F407:<\/h2>\n\n\n\n<p>Half-duplex communication (only transmitter or receiver)<\/p>\n\n\n\n<p>\u2022 Master or slave operations<\/p>\n\n\n\n<p>\u2022 8-bit programmable linear prescaler to reach accurate audio sample frequencies (from 8 kHz to 192 kHz)<\/p>\n\n\n\n<p>\u2022 Data format may be 16-bit, 24-bit or 32-bit<\/p>\n\n\n\n<p>\u2022 Packet frame is fixed to 16-bit (16-bit data frame) or 32-bit (16-bit, 24-bit, 32-bit data frame) by audio channel<\/p>\n\n\n\n<p>\u2022 Programmable clock polarity (steady state)<\/p>\n\n\n\n<p>\u2022 Underrun flag in slave transmission mode, overrun flag in reception mode (master and slave) and Frame Error Flag in reception and transmitter mode (slave only)<\/p>\n\n\n\n<p>\u2022 16-bit register for transmission and reception with one data register for both channel sides<\/p>\n\n\n\n<p>\u2022 Supported I 2 S protocols:<\/p>\n\n\n\n<p>\u2013 I 2 S Philips standard<\/p>\n\n\n\n<p>\u2013 MSB-justified standard (left-justified)<\/p>\n\n\n\n<p>\u2013 LSB-justified standard (right-justified)<\/p>\n\n\n\n<p>\u2013 PCM standard (with short and long frame synchronization on 16-bit channel frame or 16-bit data frame extended to 32-bit channel frame)<\/p>\n\n\n\n<p>\u2022 Data direction is always MSB first<\/p>\n\n\n\n<p>\u2022 DMA capability for transmission and reception (16-bit wide)<\/p>\n\n\n\n<p>\u2022 Master clock can be output to drive an external audio component. Ratio is fixed at 256 \u00d7 F S (where F S is the audio sampling frequency)<\/p>\n\n\n\n<p>Block diagram of I2S in STM32G070:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"949\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-949x1024.png\" alt=\"\" class=\"wp-image-2668\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-949x1024.png 949w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-278x300.png 278w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-768x829.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-1423x1536.png 1423w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-1150x1241.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-750x809.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-400x432.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM-250x270.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/07\/Screenshot-2024-07-12-at-5.29.52\u202fPM.png 1564w\" sizes=\"(max-width: 949px) 100vw, 949px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeMX Setup:<\/h2>\n\n\n\n<p>Open STM32CubeMX as start a new project as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg\" alt=\"\" class=\"wp-image-3990\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Search for your STM32 MCU, select the MCU and click on Start New Project as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"723\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-1024x723.png\" alt=\"\" class=\"wp-image-4505\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-1024x723.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-300x212.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-768x542.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-1536x1084.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-2048x1445.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-1150x812.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-750x529.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-400x282.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-02_16-56-40-250x176.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from System Core, RCC, set HSE to Crystal\/Ceramic oscillator as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-1024x662.png\" alt=\"\" class=\"wp-image-4506\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-49-02-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now, we need to find the frequency of the external oscillator connected to STM32F407 discovery board.<\/p>\n\n\n\n<p>From user manual of STM32F407 Discover, we can find that the crystal oscillator is 8MHz as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-1024x683.png\" alt=\"\" class=\"wp-image-4508\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-1024x683.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-768x512.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-1536x1024.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-2048x1366.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-1150x767.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-750x500.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-52-27-250x167.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Clock Configuration, set HSE speed to 8MHz, PLL source to HSE and set the frequency to 1168MHz as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-1024x662.png\" alt=\"\" class=\"wp-image-4509\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-53-33-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, we need to find which pins are connected to the Audio chip. From the user manual of the board, we can find the pins as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PC7 is I2S3 MCK (Master Clock).<\/li>\n\n\n\n<li>PC1p is I2S3 SCK (Serial Clock).<\/li>\n\n\n\n<li>PC12 is I2S3 SD (Serial Data).<\/li>\n\n\n\n<li>PA4 is I2S3 WS (Word Select).<\/li>\n<\/ul>\n\n\n\n<p>Also, set PD4 as output to disable the audio chip<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"684\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-1024x684.png\" alt=\"\" class=\"wp-image-4510\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-1024x684.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-768x513.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-1536x1026.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-2048x1369.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-1150x768.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-750x501.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_15-55-57-250x167.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Hence, enable the pins as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1003\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-1003x1024.png\" alt=\"\" class=\"wp-image-4511\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-1003x1024.png 1003w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-294x300.png 294w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-768x784.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-1505x1536.png 1505w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-1150x1174.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-750x766.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-400x408.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12-250x255.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-01-12.png 1830w\" sizes=\"(max-width: 1003px) 100vw, 1003px\" \/><\/figure>\n\n\n\n<p>Next, from Multimedia, select I2S3 and enable it as master full duplex with enable master clock as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-1024x662.png\" alt=\"\" class=\"wp-image-4512\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-02-47-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from project tab, select code generation and enable generate peripherals initialization as pair of .c\/.h files as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"596\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-1024x596.jpg\" alt=\"\" class=\"wp-image-4297\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-1024x596.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-300x175.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-768x447.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-1536x894.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-2048x1192.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-1150x669.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-750x437.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-400x233.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/03\/2026-03-19_11-20-57-250x146.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Finally from project, set the destination, give the project a name and set toolchain\/IDE to STM32CubeIDE and click on Generate Code as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-1024x662.png\" alt=\"\" class=\"wp-image-4513\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/2026-06-03_16-08-15-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Thats all for the STM32CubeMX setup.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Importing the Project to STM32CubeIDE:<\/h2>\n\n\n\n<p>Open STM32CubeIDE, select your workspace and click on Launch.<\/p>\n\n\n\n<p>From the IDE, click File and select STM32 Project Create\/Import as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"873\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg\" alt=\"\" class=\"wp-image-3997\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-300x256.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-768x655.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1150x981.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-750x640.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-400x341.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-250x213.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21.jpg 1524w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Import STM32 Project, select STM32CubeMX\/STM32CubeIDE Project and click on Next as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg\" alt=\"\" class=\"wp-image-3998\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-768x577.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-250x188.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37.jpg 1172w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, select the folder that contains the .ioc file and click on Finish as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"652\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg\" alt=\"\" class=\"wp-image-4360\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-300x191.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-768x489.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1536x977.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1150x732.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-750x477.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-400x255.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-250x159.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41.jpg 1760w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note: Project name is for reference only.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Firmware Development:<\/h2>\n\n\n\n<p>We start of in user code begin PV (Private Variable), declare an array with 7 elements as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">uint16_t data[7]={0x00,0x0011,0x0022,0x0033,0x0044,0x0055,0x0066};<\/pre><\/div>\n\n\n\n<p>In user code begin code 3 in while 1 loop, we shall keep transmit the I2S data in polling mode as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">HAL_I2S_Transmit(&amp;hi2s3, data, 7,100);\nHAL_Delay(10);<\/pre><\/div>\n\n\n\n<p>Give a delay of 10ms for this application.<\/p>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<p>Save, build the project and run it as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"34\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png\" alt=\"\" class=\"wp-image-4349\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-300x10.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-768x26.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1536x51.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1150x38.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-750x25.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-400x13.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-250x8.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1.png 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>By probing the pins of MCK, SDK, SD and WS, you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12.png\" alt=\"\" class=\"wp-image-4515\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS12-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13.png\" alt=\"\" class=\"wp-image-4516\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13-300x185.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13-768x473.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13-750x461.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13-400x246.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/06\/RigolDS13-250x154.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note: Due to architecture of I2S, the first half word is missing.<\/p>\n\n\n\n<p>Next, we shall use DMA to send the data.<\/p>\n\n\n\n<p>Stay tuned.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The I2S (Inter-IC Sound) peripheral on the STM32F407 Discovery board provides a dedicated, high-performance synchronous communication interface designed specifically for transmitting digital audio data to external codecs and DACs. This guide covers the foundational steps to understand the underlying I2S protocol architecture, properly configure the microcontroller&#8217;s hardware registers, and reliably transmit audio signals using efficient [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-4503","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4503"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4503"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4503\/revisions"}],"predecessor-version":[{"id":4517,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4503\/revisions\/4517"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}