<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Embedded Engineering Toolkit]]></title><description><![CDATA[Embedded Engineering Toolkit]]></description><link>https://embedded-engineering-toolkit.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Embedded Engineering Toolkit</title><link>https://embedded-engineering-toolkit.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 13:25:01 GMT</lastBuildDate><atom:link href="https://embedded-engineering-toolkit.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[STM32 Timer Frequency: Choosing PSC and ARR Without Guesswork]]></title><description><![CDATA[Why can a PWM output still be at the wrong frequency after you set both PSC and ARR? Usually the problem is an incorrect timer input clock or a missing “+1” in the register math—not a mysterious timer]]></description><link>https://embedded-engineering-toolkit.hashnode.dev/stm32-timer-frequency-choosing-psc-and-arr-without-guesswork</link><guid isPermaLink="true">https://embedded-engineering-toolkit.hashnode.dev/stm32-timer-frequency-choosing-psc-and-arr-without-guesswork</guid><category><![CDATA[STM32]]></category><category><![CDATA[embedded systems]]></category><category><![CDATA[Microcontrollers ]]></category><category><![CDATA[embedded c]]></category><category><![CDATA[Electronics]]></category><dc:creator><![CDATA[Lindy kellams]]></dc:creator><pubDate>Sat, 05 Sep 2026 04:02:59 GMT</pubDate><content:encoded><![CDATA[<p>Why can a PWM output still be at the wrong frequency after you set both PSC and ARR? Usually the problem is an incorrect timer input clock or a missing “+1” in the register math—not a mysterious timer bug.</p>
<h2>Start with the timer input clock</h2>
<p>This article uses an up-counting, edge-aligned timer time base. The value you need is the clock actually entering the timer (<code>timerClock</code>), in hertz. It may differ from the CPU clock and from the APB bus clock. STM32 families and APB prescaler settings do not all route clocks in the same way, so confirm the effective timer clock in your part’s clock tree and reference manual.</p>
<h2>What PSC and ARR control</h2>
<p>PSC is the prescaler. A register value of 71 divides the timer input by 72, because the divider is <code>PSC + 1</code>. ARR is the auto-reload value. In an up-counter, the counter visits zero through ARR, so one period contains <code>ARR + 1</code> counter ticks. CCR is the capture/compare value; with PWM mode 1, edge alignment, and active-high polarity, it sets the compare point and gives the ideal duty calculation below.</p>
<pre><code class="language-text">counterClock = timerClock / (PSC + 1)
frequency = timerClock / ((PSC + 1) × (ARR + 1))
period = 1 / frequency
duty = CCR / (ARR + 1) × 100%
</code></pre>
<p>These equations describe the stated mode, not every STM32 timer mode. Center-aligned counting, down-counting, repetition counters, preload/update timing, dead time, and inverted outputs need device-specific treatment.</p>
<h2>Three hand-calculated examples</h2>
<h3>1) 72 MHz, 1 kHz, 25% duty</h3>
<p>Take <code>timerClock = 72,000,000 Hz</code>, <code>PSC = 71</code>, <code>ARR = 999</code>, and <code>CCR = 250</code>.</p>
<ul>
<li>Counter clock = 72,000,000 / (71 + 1) = <strong>1,000,000 Hz</strong>.</li>
<li>Period ticks = 999 + 1 = <strong>1,000</strong>.</li>
<li>PWM frequency = 1,000,000 / 1,000 = <strong>1,000 Hz</strong>; period = <strong>1 ms</strong>.</li>
<li>Ideal duty = 250 / 1,000 × 100 = <strong>25%</strong>.</li>
</ul>
<h3>2) 72 MHz, 100 Hz, 50% duty</h3>
<p>With <code>PSC = 719</code>, <code>ARR = 999</code>, and <code>CCR = 500</code>, the counter clock is 72,000,000 / 720 = <strong>100,000 Hz</strong>. Dividing by 1,000 period ticks gives <strong>100 Hz</strong>, a <strong>10 ms</strong> period, and <strong>50%</strong> ideal duty.</p>
<h3>3) 80 MHz, 1 kHz, 75% duty</h3>
<p>With <code>PSC = 79</code>, <code>ARR = 999</code>, and <code>CCR = 750</code>, the counter clock is 80,000,000 / 80 = <strong>1,000,000 Hz</strong>. The result is <strong>1,000 Hz</strong>, <strong>1 ms</strong>, and <strong>75%</strong> ideal duty.</p>
<table>
<thead>
<tr>
<th>Timer input</th>
<th>PSC</th>
<th>ARR</th>
<th>CCR</th>
<th>Counter clock</th>
<th>PWM frequency</th>
<th>Period</th>
<th>Duty</th>
</tr>
</thead>
<tbody><tr>
<td>72 MHz</td>
<td>71</td>
<td>999</td>
<td>250</td>
<td>1 MHz</td>
<td>1 kHz</td>
<td>1 ms</td>
<td>25%</td>
</tr>
<tr>
<td>72 MHz</td>
<td>719</td>
<td>999</td>
<td>500</td>
<td>100 kHz</td>
<td>100 Hz</td>
<td>10 ms</td>
<td>50%</td>
</tr>
<tr>
<td>80 MHz</td>
<td>79</td>
<td>999</td>
<td>750</td>
<td>1 MHz</td>
<td>1 kHz</td>
<td>1 ms</td>
<td>75%</td>
</tr>
</tbody></table>
<h2>Reproduce the calculation</h2>
<p>I maintain the <a href="https://embedded-engineering-toolkit.pages.dev/tools/stm32-timer-pwm/">STM32 Timer &amp; PWM calculator</a>. It is a theoretical calculation aid, not an oscilloscope and not ST’s configuration tool. Enter <code>72000000</code> Hz, select 16-bit, set PSC to <code>71</code>, ARR to <code>999</code>, and CCR to <code>250</code>, then calculate. The expected counter clock is 1 MHz, PWM frequency 1 kHz, period 1 ms, and duty 25%. Comparing each field with the hand calculation is a useful sanity check.</p>
<h2>Boundaries that matter in real firmware</h2>
<p>Do not substitute a CPU or APB frequency for the effective timer input without checking the clock tree. Do not drop the <code>+1</code> terms. PSC and ARR determine the period; CCR determines the compare point. The calculator validates integer register ranges for 16-bit and 32-bit selections, rejects an out-of-range CCR, and its target solver reports frequency error while searching valid integer pairs.</p>
<p>The equations assume a continuously running, up-counting, edge-aligned timer. Startup latency, preload and update-event timing, interrupt or DMA scheduling, output polarity, oscillator tolerance, and board-level effects can change what you observe. Center-aligned and other specialized modes are not interchangeable with this formula.</p>
<h2>References and disclosure</h2>
<p>ST’s <a href="https://www.st.com/resource/en/application_note/an4776-generalpurpose-timer-cookbook-for-stm32-microcontrollers-stmicroelectronics.pdf">AN4776 timer cookbook</a> provides official timer and PWM configuration examples. For STM32F1 devices, see the general-purpose timer sections in <a href="https://www.st.com/resource/en/reference_manual/rm0008-stm32f103xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf">RM0008</a>. Always use the reference manual for the exact MCU and clock configuration.</p>
<p>AI assisted with drafting and language editing. The equations and numerical examples were independently recomputed from the model above; no hardware measurement or performance claim is implied.</p>
]]></content:encoded></item><item><title><![CDATA[UART Transmission Time: Why 115200 Baud Is Not 115200 Bytes/s]]></title><description><![CDATA[When someone says “115200 baud,” it is easy to read that as “115200 bytes per second.” A UART does not work that way: every transmitted frame also contains framing bits. The useful rate depends on the]]></description><link>https://embedded-engineering-toolkit.hashnode.dev/uart-transmission-time-why-115200-baud-is-not-115200-bytes-s</link><guid isPermaLink="true">https://embedded-engineering-toolkit.hashnode.dev/uart-transmission-time-why-115200-baud-is-not-115200-bytes-s</guid><category><![CDATA[uart]]></category><category><![CDATA[embedded systems]]></category><category><![CDATA[Microcontrollers ]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Lindy kellams]]></dc:creator><pubDate>Fri, 04 Sep 2026 16:12:14 GMT</pubDate><content:encoded><![CDATA[<p>When someone says “115200 baud,” it is easy to read that as “115200 bytes per second.” A UART does not work that way: every transmitted frame also contains framing bits. The useful rate depends on the selected data width, parity, and stop-bit format.</p>
<h2>A small UART timing model</h2>
<p>This article counts UART data frames. A frame count is not a Unicode character count, a string length, or an automatic description of an application buffer.</p>
<pre><code class="language-text">frameBits = 1 + dataBits + parityBits + stopBits
totalBits = frameCount × frameBits
payloadBits = frameCount × dataBits
timeSeconds = totalBits / baudRate
</code></pre>
<p>For a positive frame count, <code>payloadBitRate = payloadBits / timeSeconds</code>. Payload bits include only the UART data field. They do not subtract application headers, escaping, checksums, retries, or buffering. The time calculation assumes back-to-back frames with no intentional idle gap. Driver scheduling, DMA/FIFO behavior, flow control, USB adapters, and software delays can increase elapsed time.</p>
<p>Microchip's USART documentation describes 8N1 as one start bit, eight data bits, no parity bit, and one stop bit. That is 10 line bits per frame. Device-specific modes and register limits still belong to the target chip's data sheet.</p>
<h2>Example 1: 115200 baud, 8N1, 100 frames</h2>
<p>For 8N1, <code>frameBits = 1 + 8 + 0 + 1 = 10 bits/frame</code>.</p>
<ul>
<li>Line bits: <code>100 × 10 = 1,000 bits</code></li>
<li>Data-field bits: <code>100 × 8 = 800 bits</code></li>
<li>Wire time: <code>1,000 / 115,200 = 0.0086805556 s ≈ 8.68056 ms</code></li>
<li>Data-field bit rate: <code>800 / 0.0086805556 = 92,160 bit/s</code></li>
</ul>
<p>The line rate is 115200 bit/s, while the theoretical data-field rate is 92160 bit/s. In this specific 8-bit example, that is equivalent to 11,520 B/s after dividing by eight. It is not 115200 bytes/s, and it is not an end-to-end application throughput guarantee.</p>
<h2>Example 2: 9600 baud, 7N1, 100 frames</h2>
<p>Seven data bits and one stop bit produce 9 line bits per frame. The stream uses 900 line bits and 700 data-field bits, takes <code>900 / 9,600 = 0.09375 s</code> (<strong>93.75 ms</strong>), and has a data-field rate of approximately <strong>7,466.67 bit/s</strong>.</p>
<p>A 7-bit frame is not automatically an 8-bit byte. If an application starts with arbitrary 8-bit bytes, it needs an explicit packing or encoding layer. This model does not invent one.</p>
<h2>Example 3: 115200 baud, 9N1, 100 frames</h2>
<p>With nine data bits and one stop bit, the stream uses 11 bits per frame, 1,100 line bits, and 900 data-field bits. The wire time is approximately <strong>9.54861 ms</strong>, and the data-field rate is approximately <strong>94,254.55 bit/s</strong>. The 9-bit field also does not define how a higher-level byte stream is encoded.</p>
<h2>Zero frames and practical boundaries</h2>
<p>Zero is a valid frame count. The format still determines <code>frameBits</code>, but total line bits, data-field bits, time, and bit rate are all defined as zero. There is no <code>0/0</code> calculation. Negative, fractional, non-finite, or unrepresentably large frame counts should be rejected.</p>
<p>This calculation answers one narrow question: how long a known number of complete frames would occupy the wire under continuous transmission. It does not model application protocol structure or hardware scheduling. If protocol headers or checksums are sent through UART, count their encoded frames as part of the stream before estimating time.</p>
<h2>A calculator for checking your own parameters</h2>
<p>I develop and maintain the <a href="https://embedded-engineering-toolkit.pages.dev/tools/uart-transmission-time/">UART Transmission Time Calculator</a>. It accepts baud rate, frame count, data bits, parity, and stop bits, then reports theoretical line time and data-field bit rate. It is useful for repeating the arithmetic with your own parameters; it is not a hardware measurement or an official certification.</p>
<p>To reproduce the 7N1 example, enter baud rate <code>9600</code>, number of frames <code>100</code>, data bits <code>7</code>, parity <code>None</code>, and stop bits <code>1</code>. The expected result is 9 bits per frame, 900 total line bits, 700 data-field bits, 93.75 ms, and approximately 7466.67 bit/s.</p>
<h2>References and disclosure</h2>
<ul>
<li><a href="https://ww1.microchip.com/downloads/en/Appnotes/TB3216-Getting-Started-with-USART-90003216B.pdf">Microchip TB3216: Getting Started with USART</a></li>
<li><a href="https://www.microchip.com/en-us/products/microcontrollers/8-bit-mcus/peripherals/communication-connectivity/uart">Microchip UART peripheral overview</a></li>
</ul>
<p>This article was drafted and edited with AI assistance. I reviewed the formulas and wording against the cited source and the calculator's current implementation; the numerical examples are independent arithmetic checks, not hardware measurements. I remain responsible for the published content.</p>
]]></content:encoded></item></channel></rss>