{"id":4613,"date":"2026-07-26T06:01:37","date_gmt":"2026-07-26T06:01:37","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4613"},"modified":"2026-07-26T06:01:38","modified_gmt":"2026-07-26T06:01:38","slug":"emulating-uart-part-1-introduction-and-environment-setup","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4613","title":{"rendered":"Emulating UART Part 1: Introduction and environment Setup"},"content":{"rendered":"\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\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-1024x683.png\" alt=\"\" class=\"wp-image-4614\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-1024x683.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-768x512.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-1150x767.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-750x500.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM-250x167.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/ChatGPT-Image-Jul-26-2026-at-08_11_52-AM.png 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In this new series guide, we shall emulate the UART hardware using a clever combination of timers and DMA to achieve effortless, CPU-independent serial communication. Before a single byte can take flight, we will use STM32CubeMX to forge the precise timing pathways and autonomous logic required to bring this invisible engine to life.<\/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>How to calculate the baudrate<\/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<h2 class=\"wp-block-heading\">1. Introduction:<\/h2>\n\n\n\n<p><strong>Why Software Emulation?<\/strong><br>As your project grows, you often find yourself running out of available hardware UART ports. You might need just one more debug log, a connection to a specialized sensor, or an extra serial channel on a pin that lacks a hardware transceiver. Software UART bridges this gap, allowing you to turn any standard GPIO into a fully functional serial port. It provides the ultimate flexibility to expand your microcontroller&#8217;s communication capabilities beyond its physical limitations.<\/p>\n\n\n\n<p><strong>How Does Soft UART Work?<\/strong><br>A standard UART frame is simply a timed sequence of high and low voltage pulses\u2014a start bit, eight data bits, and a stop bit. Traditional software UART implementations force the CPU to manually toggle a pin and waste cycles in blocking delay loops to time the bits. Our approach is far more elegant: we use a hardware timer configured in &#8220;Output Compare Toggle&#8221; mode. By pre-calculating the exact moments the signal needs to change state and feeding those timestamps via DMA directly to the timer, the microcontroller&#8217;s hardware autonomously generates the perfect UART waveform. The CPU is completely uninvolved.<\/p>\n\n\n\n<p><strong>Advantages and Disadvantages<\/strong><\/p>\n\n\n\n<p><em>The Good:<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CPU Independence:<\/strong> Because DMA handles the heavy lifting, your CPU is 100% free to execute critical code while bytes transmit seamlessly in the background.<\/li>\n\n\n\n<li><strong>Pin Flexibility:<\/strong> You are no longer bound by fixed alternate-function pins. Any GPIO can become a TX line.<\/li>\n\n\n\n<li><strong>Total Customization:<\/strong> You can easily tweak the code for inverted logic, custom baud rates, or non-standard frame sizes (like 7 or 9 data bits).<\/li>\n<\/ul>\n\n\n\n<p><em>The Trade-offs:<\/em><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Resource Cost:<\/strong> This method consumes a hardware timer and a DMA stream, which might be scarce in complex, heavily loaded applications.<\/li>\n\n\n\n<li><strong>Timing Jitter:<\/strong> While DMA is precise, it isn&#8217;t immune to bus contention. Very high baud rates (above 115200 or 230400) might start to show jitter if the DMA is blocked by higher-priority transfers, whereas a dedicated hardware UART is bulletproof.<\/li>\n\n\n\n<li><strong>RX Complexity:<\/strong> Transmitting asynchronously via DMA is straightforward, but receiving is notoriously tricky. Capturing asynchronous incoming edges with timers and reconstructing the bytes requires careful state management and edge-case handling.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. How to Calculate the Baudrate: <\/h2>\n\n\n\n<p>Here is a dedicated section explaining the math behind the timer configuration. You can add this right after the CubeMX setup steps or just before diving into the code.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding the Math: Calculating Timer Parameters<\/h3>\n\n\n\n<p>To emulate a UART port reliably, the underlying timer must tick at a rate that allows us to slice the signal into exact &#8220;bit times.&#8221; If our timing is off by even a fraction of a percent, the receiving device will misinterpret the 1s and 0s.<\/p>\n\n\n\n<p>Here is how we calculate the timer parameters to achieve a target baud rate of <strong>115200<\/strong> on an STM32F411RE running at <strong>100 MHz<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">1. Determine the Timer Clock Frequency<\/h4>\n\n\n\n<p>On the STM32F411RE, we configured the system clock (SYSCLK) to 100 MHz.<br>Because the APB1 prescaler is set to 2, the APB1 peripheral clock is 50 MHz. However, by STM32 hardware design, <strong>if the APB prescaler is not 1, the timer clock is automatically doubled<\/strong>. Therefore, our TIM3 clock is exactly <strong>100,000,000 Hz (100 MHz)<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">2. Calculate Ticks Per Bit<\/h4>\n\n\n\n<p>A baud rate of 115200 means 115,200 bits are transmitted every second. Therefore, the duration of a single bit is:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"132\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-1024x132.jpg\" alt=\"\" class=\"wp-image-4615\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-1024x132.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-300x39.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-768x99.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-1150x148.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-750x96.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-400x51.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19-250x32.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-19.jpg 1230w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We need to figure out how many timer ticks fit into this 8.68uS window. The formula is:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"133\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-1024x133.jpg\" alt=\"\" class=\"wp-image-4616\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-1024x133.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-300x39.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-768x100.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-1150x150.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-750x98.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-400x52.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26-250x33.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-26.jpg 1304w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><br>For our setup:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"105\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-1024x105.jpg\" alt=\"\" class=\"wp-image-4617\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-1024x105.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-300x31.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-768x79.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-1150x118.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-750x77.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-400x41.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38-250x26.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-38-38.jpg 1386w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since timer registers can only hold whole integers, we must round. As recommended by ST&#8217;s AN4457, we use mathematical rounding (adding half the divisor before integer division) to minimize drift over the 10-bit UART frame:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"96\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-1024x96.jpg\" alt=\"\" class=\"wp-image-4618\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-1024x96.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-300x28.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-768x72.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-1536x144.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-2048x192.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-1150x108.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-750x70.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-400x37.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-07-250x23.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">3. Verify the Baud Rate Error<\/h4>\n\n\n\n<p>Because we rounded 868.055 down to 868, our actual baud rate will be slightly faster than 115200. Let&#8217;s calculate the error:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"744\" height=\"118\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-18.jpg\" alt=\"\" class=\"wp-image-4619\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-18.jpg 744w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-18-300x48.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-18-400x63.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-39-18-250x40.jpg 250w\" sizes=\"(max-width: 744px) 100vw, 744px\" \/><\/figure>\n\n\n\n<p>Standard UART communication can tolerate up to <strong>2% to 3% error<\/strong> before bits start corrupting. Our error of <strong>0.006%<\/strong> is virtually perfect.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">4. Choosing the Prescaler (PSC) and Auto-Reload (ARR)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Prescaler (PSC):<\/strong> Because 100MHz divided by 115200 gives us 868 (which easily fits inside a 16-bit register), we don&#8217;t need to slow the timer down. We set <strong>PSC = 0<\/strong>, meaning the timer ticks at the full 100 MHz.<\/li>\n\n\n\n<li><strong>Auto-Reload (ARR):<\/strong> A standard UART frame is 10 bits long (1 Start + 8 Data + 1 Stop). The total ticks for a full frame is 10 times 868 = 8,680 ticks. We set <strong>ARR = 65535<\/strong> (the maximum 16-bit value) so the timer counter never resets in the middle of a transmission.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. 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><\/p>\n\n\n\n<p>Next, from System Core RCC, enable the external oscillator:<\/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\/07\/2026-07-26_08-08-38-1024x662.jpg\" alt=\"\" class=\"wp-image-4620\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-38-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since this guide shall use STM32F411RE Nucleo, it has 8MHz clock generated by on board ST-Link.<\/p>\n\n\n\n<p>From Clock Configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set Input Frequency to 8MHz.<\/li>\n\n\n\n<li>Set PLL source to HSE.<\/li>\n\n\n\n<li>Set HCLK to 100MHz and hit enter<\/li>\n<\/ul>\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\/07\/2026-07-26_08-08-58-1024x662.jpg\" alt=\"\" class=\"wp-image-4621\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-08-58-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This will set the maximum frequency for the MCU. Please note that if your MCU can operate faster than 100MHz, you need to set it to 100MHz when you follow this guide.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Next,  from Pinout and Configuration:<\/p>\n\n\n\n<p>From Timers, select TIM3, set the clock source to internal and set CH1 as Output Compare and set it to toggle on match 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\/07\/2026-07-26_08-31-06-1024x662.jpg\" alt=\"\" class=\"wp-image-4622\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-31-06-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note that PA6 has been set, this will be our TX pin for now.<\/p>\n\n\n\n<p>Next, from DMA settings, add DMA with direction of Memory to Peripheral 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\/07\/2026-07-26_08-32-53-1024x662.jpg\" alt=\"\" class=\"wp-image-4623\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-32-53-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Project Manager, Code Generation, enable generate peripherals initialization as pair .c\/.h files per peripheral.<\/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\/07\/2026-07-26_08-56-55-1024x662.jpg\" alt=\"\" class=\"wp-image-4624\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-56-55-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Finally, from Project, give the project a name, set the 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\/07\/2026-07-26_08-58-40-1024x662.jpg\" alt=\"\" class=\"wp-image-4625\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/07\/2026-07-26_08-58-40-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. 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<p>In next part, we shall start developing the code to transmit data by software method.<\/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>In this new series guide, we shall emulate the UART hardware using a clever combination of timers and DMA to achieve effortless, CPU-independent serial communication. Before a single byte can take flight, we will use STM32CubeMX to forge the precise timing pathways and autonomous logic required to bring this invisible engine to life. In this [&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-4613","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\/4613"}],"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=4613"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4613\/revisions"}],"predecessor-version":[{"id":4626,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4613\/revisions\/4626"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}