{"id":4495,"date":"2026-05-31T07:31:56","date_gmt":"2026-05-31T07:31:56","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4495"},"modified":"2026-05-31T07:31:58","modified_gmt":"2026-05-31T07:31:58","slug":"getting-started-with-stm32-low-layer-ll-uart-transmit-in-polling-mode","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4495","title":{"rendered":"Getting Started with STM32 Low Layer (LL): UART Transmit in Polling Mode"},"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\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-1024x559.png\" alt=\"\" class=\"wp-image-4496\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-1024x559.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-300x164.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-768x419.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-1150x627.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-750x409.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-400x218.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq-250x136.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_7rdq0v7rdq0v7rdq.png 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Establish robust, asynchronous serial communication by leveraging the STM32F4\u2019s\u00a0<strong>USART\/UART<\/strong>\u00a0peripheral configured with Low Layer (LL) drivers for maximum data throughput and minimal execution overhead. This guide covers register-level configuration of baud rate generation, frame formats, and status flags, enabling your firmware to efficiently transmit and receive bytes to and from a host computer or external sensors.<\/p>\n\n\n\n<p><\/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<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction:<\/h2>\n\n\n\n<p>While managing internal timing and handling local pins allows an embedded system to control its immediate environment, a truly useful device must communicate with the broader world. The&nbsp;<strong>Universal Asynchronous Receiver-Transmitter (UART)<\/strong>&nbsp;is one of the oldest, most robust, and most ubiquitous communication protocols in computing. From debugging system states on a development PC to streaming data from cellular modules, GPS receivers, or industrial sensors, UART serves as the foundational data highway for embedded firmware.<\/p>\n\n\n\n<p>Unlike synchronous protocols (such as SPI or I2C) that share a dedicated clock line between devices to synchronize data bits, UART is completely&nbsp;<strong>asynchronous<\/strong>. It relies on both the transmitter (TX) and receiver (RX) agreeing beforehand on a precise transmission speed\u2014known as the&nbsp;<strong>Baud Rate<\/strong>\u2014and a specific data packet architecture. This reliance on timing synchronization means that the physical hardware must handle bit-level sampling with extreme precision.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Anatomy of an Asynchronous Data Frame<\/h5>\n\n\n\n<p>Because there is no shared clock line, a UART line rests in an idle&nbsp;<strong>Logic HIGH<\/strong>&nbsp;state. When a transmission begins, the hardware sequences the data into a tightly controlled frame:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Start Bit:<\/strong>\u00a0The transmitter pulls the line\u00a0<strong>LOW<\/strong>\u00a0for exactly one bit period. This sudden high-to-low transition alerts the receiver&#8217;s hardware to wake up and start its internal sample counter.<\/li>\n\n\n\n<li><strong>Data Payload:<\/strong>\u00a0Typically 8 or 9 bits of data are clocked out sequentially, usually starting with the Least Significant Bit (LSB).<\/li>\n\n\n\n<li><strong>Parity Bit (Optional):<\/strong>\u00a0A primitive form of error checking that counts the number of 1s in the payload to verify data integrity over noisy lines.<\/li>\n\n\n\n<li><strong>Stop Bits:<\/strong>\u00a0The transmitter pulls the line back to a\u00a0<strong>Logic HIGH<\/strong>\u00a0state for 1, 1.5, or 2 bit periods to signify the end of the frame and reset the line for the next character.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Low Layer (LL) Control: Maximizing Hardware Efficiency<\/h5>\n\n\n\n<p>Configuring UART on the STM32F4 using Low Layer (LL) drivers gives you direct, uncompromising access to the peripheral&#8217;s internal registers. Instead of dealing with the multi-layered memory structures and abstract handle states of the HAL library, LL functions expose the immediate status flags of the hardware.<\/p>\n\n\n\n<p>To achieve efficient data transmission and reception, your code will interact directly with the hardware&#8217;s core bit-management structures:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>The Transmit Data Register (TDR) and Receive Data Register (RDR):<\/strong>\u00a0The data buffers where bytes are staged before being shifted out onto the physical copper wire bit-by-bit, or where incoming bits are compiled back into a usable byte.<\/li>\n\n\n\n<li><strong>The Baud Rate Generator (BRR):<\/strong>\u00a0A highly precise register that divides the peripheral&#8217;s internal clock source ($f_{PCLK}$) down to the exact frequency required for the chosen baud rate (e.g., 115200 bps).<\/li>\n\n\n\n<li><strong>Status Flags (TXE and RXNE):<\/strong>\u00a0Real-time hardware status indicators.\u00a0<code>TXE<\/code>\u00a0(Transmit Data Register Empty) tells your code the hardware is ready to accept a new byte, while\u00a0<code>RXNE<\/code>\u00a0(Read Data Register Not Empty) signals that a fresh byte has successfully arrived over the wire and is waiting to be processed.<\/li>\n<\/ul>\n\n\n\n<p>By managing these registers directly, you eliminate execution overhead, allowing you to build lean communication drivers. This forms the perfect foundation for everything from high-speed data logging to parsing dense AT-command streams from external wireless hardware.<\/p>\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\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"724\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-1024x724.jpg\" alt=\"\" class=\"wp-image-3991\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-1024x724.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-300x212.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-768x543.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-1536x1087.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-2048x1449.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-1150x814.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-750x531.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-400x283.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-06-08-250x177.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>From the user manual of STM32F411 Nucleo-64, we can find that PA2 and PA3 are connected to ST-Link MCU which corresponds to USART2 as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"403\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-1024x403.png\" alt=\"\" class=\"wp-image-4497\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-1024x403.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-300x118.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-768x303.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-1536x605.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-2048x807.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-1150x453.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-750x296.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-400x158.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-06-26-250x99.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>From Connectivity, enable UASRT2 as Asynchronous mode 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\/05\/2026-05-31_09-41-25-1024x662.png\" alt=\"\" class=\"wp-image-4498\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-25-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Keep the configuration as is since we shall use the UART to transmit the data in polling mode.<\/p>\n\n\n\n<p>Next, from Project Manager, Advanced Settings tab, set RCC, GPIO and USART to LL 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\/05\/2026-05-31_09-41-53-1024x662.png\" alt=\"\" class=\"wp-image-4499\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-41-53-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Finally, from Project Manager, Project tab, give the project a name and set toolchain\/IDE to STM32CubeIDE 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\/05\/2026-05-31_10-13-23-1024x662.png\" alt=\"\" class=\"wp-image-4500\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_10-13-23-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>That all for the configuration.<\/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><\/p>\n\n\n\n<p>In this guide, we shall cover two methods to send the data, using single character and the user has to handle how to send the data and how to send the string directly by providing the buffer and length of the buffer.<\/p>\n\n\n\n<p>We shall start with single character.<\/p>\n\n\n\n<p>We start by including stdio.h header file 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;}\">#include &quot;stdio.h&quot;<\/pre><\/div>\n\n\n\n<p>Next, in user code begin PV, declare the following three variables:<\/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;}\">char uart_buff[50]={0};\nuint8_t counter;\nuint16_t buff_len;<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>uart_buff[50] which holds the characters to be sent over uart.<\/li>\n\n\n\n<li>counter to counts number of times the uart send the data.<\/li>\n\n\n\n<li>buff_len which holds the buffer length to be sent.<\/li>\n<\/ul>\n\n\n\n<p>Next, in user code begin 0, declare a function that shall send single character 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;}\">void UART_Send_Char(char ch)\n{\n\twhile (!LL_USART_IsActiveFlag_TXE(USART2));   \t\/\/ Wait until TX buffer is empty\n\n\tLL_USART_TransmitData8(USART2, ch);\t\t\t\t\/\/ Send byte\n\n\twhile (!LL_USART_IsActiveFlag_TC(USART2));\t\t\/\/ Wait for complete transmission\n}<\/pre><\/div>\n\n\n\n<p>This function handles transmitting a single character over UART using blocking polling mode. It relies on a two-step hardware buffer process to ensure the data is safely sent out of the physical pin without corruption.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step-by-Step Breakdown<\/h3>\n\n\n\n<h5 class=\"wp-block-heading\">1. Wait for the Transmit Data Register (<code>TXE<\/code>)<\/h5>\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;}\">while (!LL_USART_IsActiveFlag_TXE(USART2));<\/pre><\/div>\n\n\n\n<p>The CPU blocks and continuously polls the&nbsp;<strong>TXE (Transmit Data Register Empty)<\/strong>&nbsp;flag. It waits here until the internal&nbsp;<code>TDR<\/code>&nbsp;buffer is empty and ready to accept a new byte. If a previous character is still sitting in the buffer, this line prevents it from being overwritten.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">2. Load Data into the Buffer<\/h5>\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;}\">LL_USART_TransmitData8(USART2, ch);<\/pre><\/div>\n\n\n\n<p>Once&nbsp;<code>TXE<\/code>&nbsp;is true, the CPU writes the 8-bit character&nbsp;<code>ch<\/code>&nbsp;directly into the&nbsp;<code>USART2-&gt;DR<\/code>&nbsp;register. The hardware immediately moves this byte from the&nbsp;<code>TDR<\/code>&nbsp;buffer into an internal hardware&nbsp;<strong>Shift Register<\/strong>, which begins clocking the data out onto the TX pin bit-by-bit (Start bit, data bits, stop bit).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">3. Wait for Complete Transmission (<code>TC<\/code>)<\/h5>\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;}\">while (!LL_USART_IsActiveFlag_TC(USART2));<\/pre><\/div>\n\n\n\n<p>The CPU blocks a second time, polling the&nbsp;<strong>TC (Transmission Complete)<\/strong>&nbsp;flag. This flag only turns true when the shift register has finished physically clocking every single bit of the frame out of the microcontroller.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in while 1 loop in user code begin 3:<\/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;}\">buff_len=sprintf(uart_buff,&quot;Counter Value =%d \\r\\n&quot;,counter++);\nfor (int i=0;i&lt;buff_len;i++)\n{\n  UART_Send_Char(uart_buff[i]);\n}<\/pre><\/div>\n\n\n\n<p>This code snippet formats a dynamic string containing an incrementing counter value and transmits it character-by-character over the UART interface.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step-by-Step Breakdown<\/h3>\n\n\n\n<h5 class=\"wp-block-heading\">1. String Formatting via&nbsp;<code>sprintf<\/code><\/h5>\n\n\n\n<p>The system constructs a formatted text string inside a character array named&nbsp;<code>uart_buff<\/code>. The current value of the&nbsp;<code>counter<\/code>variable replaces the&nbsp;<code>%d<\/code>&nbsp;placeholder, and the variable is then incremented by one so it is ready for the next cycle. The&nbsp;<code>sprintf<\/code>&nbsp;function returns the exact number of characters written to the buffer (excluding the null terminator), which is saved into&nbsp;<code>buff_len<\/code>&nbsp;to serve as the precise loop boundary.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">2. Character-by-Character Transmission<\/h5>\n\n\n\n<p>A sequential loop iterates through the populated&nbsp;<code>uart_buff<\/code>&nbsp;array, starting at index zero and ending just before reaching&nbsp;<code>buff_len<\/code>. During each iteration, the loop extracts a single character from the array\u2014such as &#8216;C&#8217;, then &#8216;o&#8217;, then &#8216;u&#8217;\u2014and feeds it directly into your blocking transmission function to be physically clocked out over the microcontroller&#8217;s TX pin.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, 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<p>Open your favourite  terminal application, set the baudrate to 115200 and you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"707\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1024x707.png\" alt=\"\" class=\"wp-image-4501\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1024x707.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-300x207.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-768x530.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1536x1060.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1150x794.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-750x518.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-400x276.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-250x173.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11.png 1866w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, we shall see how to send string using single function.<\/p>\n\n\n\n<p>In user code begin 0, declare the following function:<\/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;}\">void UART_Send_String(char *ch , uint16_t len)\n\n{\n\tfor (int i=0;i&lt;len;i++)\n\t{\n\t\twhile (!LL_USART_IsActiveFlag_TXE(USART2));   \t\/\/ Wait until TX buffer is empty\n\n\t\tLL_USART_TransmitData8(USART2, ch[i]);\t\t\t\t\/\/ Send byte\n\n\t}\n\n\twhile (!LL_USART_IsActiveFlag_TC(USART2));\t\t\/\/ Wait for complete transmission\n}<\/pre><\/div>\n\n\n\n<p>This will allow you send multiple bytes as fast as possible.<\/p>\n\n\n\n<p>In user code begin 3 in while function:<\/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;}\">buff_len=sprintf(uart_buff,&quot;Counter Value =%d \\r\\n&quot;,counter++);\nUART_Send_String(uart_buff,buff_len);\nLL_mDelay(10);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, 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>Open your favourite  terminal application, set the baudrate to 115200 and you should get the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"707\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1024x707.png\" alt=\"\" class=\"wp-image-4501\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1024x707.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-300x207.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-768x530.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1536x1060.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-1150x794.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-750x518.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-400x276.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11-250x173.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-31_09-50-11.png 1866w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Congratulations, you send the string successfully.<\/p>\n\n\n\n<p>You may download the project from <a href=\"https:\/\/github.com\/hussamaldean\/Embedded-Expert-Post-Projects\/tree\/main\/Projects\/LL_UART\" data-type=\"link\" data-id=\"https:\/\/github.com\/hussamaldean\/Embedded-Expert-Post-Projects\/tree\/main\/Projects\/LL_UART\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Establish robust, asynchronous serial communication by leveraging the STM32F4\u2019s\u00a0USART\/UART\u00a0peripheral configured with Low Layer (LL) drivers for maximum data throughput and minimal execution overhead. This guide covers register-level configuration of baud rate generation, frame formats, and status flags, enabling your firmware to efficiently transmit and receive bytes to and from a host computer or external sensors. [&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-4495","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\/4495"}],"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=4495"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4495\/revisions"}],"predecessor-version":[{"id":4502,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4495\/revisions\/4502"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}