{"id":4002,"date":"2025-11-29T16:26:50","date_gmt":"2025-11-29T16:26:50","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4002"},"modified":"2025-11-29T16:26:52","modified_gmt":"2025-11-29T16:26:52","slug":"stm32-timers-applications-timer-cascading","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4002","title":{"rendered":"STM32 Timers Applications:\u00a0Timer Cascading"},"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\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-1024x683.png\" alt=\"\" class=\"wp-image-4003\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-1024x683.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-768x512.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-1150x767.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-750x500.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM-250x167.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/ChatGPT-Image-Nov-29-2025-at-06_31_33-PM.png 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Cascading two 16-bit timers on the STM32 allows you to build a fully synchronized 32-bit extended timer, overcoming the counting limitations of a single 16-bit peripheral. By configuring one timer as the master and the other as its hardware-driven slave, both counters operate as one continuous 32-bit unit\u2014ideal for long-duration timing, precise period measurements, and high-resolution event capture.<\/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>Theory.<\/li>\n\n\n\n<li>STM32CubeMX setup.<\/li>\n\n\n\n<li>Importing project to STM32CubeIDE.<\/li>\n\n\n\n<li>Firmware.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction:<\/h2>\n\n\n\n<p>In many embedded applications, timing precision and extended measurement ranges are absolutely essential. Although STM32 microcontrollers provide high-performance general-purpose timers, most of these peripherals are limited to a 16-bit counter width, meaning they can represent a maximum count of 65,535 before overflowing. For tasks that require long-duration measurements, high-resolution timestamping, wide-range frequency analysis, real-time profiling, pulse counting, or long-window event accumulation, a 16-bit counter is usually insufficient. Reaching longer timing intervals typically requires either reducing the timer clock (losing resolution) or manually handling overflow interrupts\u2014which increases CPU load and creates timing uncertainty at high clock speeds.<\/p>\n\n\n\n<p>To overcome these limitations without compromising timing resolution or relying on software-driven overflow handling, we can\u00a0<strong>cascade two 16-bit timers into one virtual 32-bit timer<\/strong>. This hardware-driven chaining allows Timer A to overflow and automatically clock Timer B, creating a continuous 32-bit count that rolls over after 4,294,967,295 counts. This technique preserves the full speed and accuracy of the timer clock while enabling timing windows that are 65,536 times longer than a single 16-bit counter can achieve. Cascading timers is therefore a powerful method for building extended-range counters, precise period measurement units, long-interval timestamp generators, and low-latency totalizers\u2014without burdening the core processor.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Theory:<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1. What Does Cascading Two Timers Mean?<\/strong><\/h2>\n\n\n\n<p>In STM32 architecture, \u201ccascading\u201d or \u201cchaining\u201d timers refers to a master\u2013slave configuration where one timer\u2019s&nbsp;<strong>update event (UEV)<\/strong>&nbsp;acts as an input trigger or external clock for another timer. When the master timer completes a full 16-bit cycle and overflows, it issues a trigger output (TRGO). This TRGO is routed internally through the microcontroller\u2019s timer interconnect matrix and is used as a clock source for the slave timer. Each overflow of the master results in one increment of the slave counter.<\/p>\n\n\n\n<p>This results in a&nbsp;<strong>combined 32-bit counter<\/strong>, where:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The\u00a0<strong>master timer<\/strong>\u00a0counts the low 16 bits.<\/li>\n\n\n\n<li>The\u00a0<strong>slave timer<\/strong>\u00a0counts the high 16 bits.<\/li>\n\n\n\n<li>Together they form:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>Combined_32bit_Value = (Slave_Count &lt;&lt; 16) | Master_Count\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>STM32 Timer Interconnect: Trigger and Clock Sharing<\/strong><\/h2>\n\n\n\n<p>STM32 timers include a flexible internal routing system called&nbsp;<strong>TIMx Internal Trigger (ITRx)<\/strong>.<br>Each timer has dedicated internal trigger lines:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ITR0<\/strong><\/li>\n\n\n\n<li><strong>ITR1<\/strong><\/li>\n\n\n\n<li><strong>ITR2<\/strong><\/li>\n\n\n\n<li><strong>ITR3<\/strong><\/li>\n<\/ul>\n\n\n\n<p>These lines allow one timer\u2019s TRGO to be used as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>External clock mode 1 source<\/li>\n\n\n\n<li>Trigger for reset<\/li>\n\n\n\n<li>Trigger for gating<\/li>\n\n\n\n<li>Trigger for synchronization of start\/stop events<\/li>\n<\/ul>\n\n\n\n<p>In cascaded 32-bit mode, the slave timer is set to&nbsp;<strong>External Clock Mode 1 (SMS = 111)<\/strong>, using the master timer\u2019s TRGO as its input clock.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Master Timer (Low-Order 16 Bits)<\/strong><\/h2>\n\n\n\n<p>The master timer operates normally as a 16-bit up-counter.<br>Its configuration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PSC (prescaler) determines timer tick frequency<\/li>\n\n\n\n<li>ARR sets the period<\/li>\n\n\n\n<li>Update event occurs every time the counter rolls over<\/li>\n\n\n\n<li>TRGO (Trigger Output) is configured to emit on update event<\/li>\n<\/ul>\n\n\n\n<p>Since ARR = 0xFFFF for a full 16-bit cycle, every overflow equals exactly&nbsp;<strong>65,536 ticks<\/strong>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Slave Timer (High-Order 16 Bits)<\/strong><\/h2>\n\n\n\n<p>The slave timer is configured in:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>External Clock Mode 1<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SMS = 111 (external clock mode)<\/li>\n\n\n\n<li>TS = ITRx (selecting TRGO from the master)<\/li>\n\n\n\n<li>PSC = 0 (slave must count each incoming tick)<\/li>\n\n\n\n<li>ARR = 0xFFFF<\/li>\n<\/ul>\n\n\n\n<p>This means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Each overflow of the master increments the slave by 1<\/li>\n\n\n\n<li>The slave overflows only after (65,536 \u00d7 65,536) ticks<\/li>\n\n\n\n<li>Total count range = 4,294,967,296 ticks<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Result: True Hardware 32-Bit Counter<\/strong><\/h2>\n\n\n\n<p>Because the slave increments only on master overflow, the combined counter behaves like a native 32-bit timer:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No interrupts required<\/li>\n\n\n\n<li>No software overhead<\/li>\n\n\n\n<li>Perfect synchronization<\/li>\n\n\n\n<li>Zero jitter<\/li>\n\n\n\n<li>Full hardware speed<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><\/h3>\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>ext, from system core, select RCC and select either Crystal \/ Ceramic oscillator in case your board has external oscillator or bypass the oscillator in case of Nucleo board. Since this guide uses STM32F446 Nucleo-64, bypass oscillator will be used 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-10-16-1024x662.jpg\" alt=\"\" class=\"wp-image-3992\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-10-16-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Clock configuration, set the input frequency to 8MHz, PLL source to HSE and set HCLK frequency to 180MHz. Press enter to set the correct parameters.<\/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\/2025\/11\/2025-11-29_18-54-35-1024x662.jpg\" alt=\"\" class=\"wp-image-4004\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-54-35-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, from pinout and configuration, select TIM1 from timers and set Channel and Input capture direct mode as follows:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"362\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-1024x362.jpg\" alt=\"\" class=\"wp-image-4005\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-1024x362.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-300x106.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-768x271.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-1536x543.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-1150x406.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-750x265.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-400x141.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27-250x88.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_18-57-27.jpg 1676w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, configure the timer as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set prescaler to 18-1. This will reduce the timer frequency to 10MHz.<\/li>\n\n\n\n<li>Set counter period to 10000-1, this will set maximum frequency of 10KHz.<\/li>\n\n\n\n<li>Set trigger Event selection to Update event.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"700\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-1024x700.jpg\" alt=\"\" class=\"wp-image-4006\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-1024x700.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-300x205.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-768x525.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-1150x786.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-750x513.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-400x273.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41-250x171.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-03-41.jpg 1390w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, enable TIM1 capture compare interrupt as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"702\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-1024x702.jpg\" alt=\"\" class=\"wp-image-4007\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-1024x702.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-300x206.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-768x527.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-1150x789.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-750x514.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-400x274.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19-250x171.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-06-19.jpg 1382w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, enable TIM3 and set Slave mode to External Clock Mode 1 and trigger source to ITR0.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"376\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-1024x376.jpg\" alt=\"\" class=\"wp-image-4008\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-1024x376.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-300x110.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-768x282.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-1536x564.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-1150x422.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-750x276.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-400x147.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15-250x92.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-08-15.jpg 2036w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Leave the parameters as is.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>From Project Manager:<\/p>\n\n\n\n<p>Give the project a name, set the location, set toolchain\/IDE to STM32CubeIDE and click on Generate Code.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"535\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-1024x535.jpg\" alt=\"\" class=\"wp-image-4010\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-1024x535.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-300x157.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-768x402.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-1536x803.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-2048x1071.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-1150x601.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-750x392.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-400x209.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-29_19-10-18-1-250x131.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for STM32CubeMX.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Import 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 size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"639\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-1024x639.jpg\" alt=\"\" class=\"wp-image-4011\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-1024x639.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-300x187.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-768x479.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-1536x959.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-1150x718.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-750x468.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-400x250.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27-250x156.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-28_10-03-27.jpg 1794w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5.  Firmware Development:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Open the main.c file.<\/p>\n\n\n\n<p>In user code begin PV, declare the following 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;}\">volatile uint8_t Is_First_Captured=0;\n\nvolatile uint16_t counter1,counter3;\n\nfloat frequency;<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Is_First_Capture is related to detecting the first rising edge of the pulse.<\/li>\n\n\n\n<li>counter1 and counter 3 to store the value of counter for TIM1 and TIM3 respectively.<\/li>\n\n\n\n<li>frequency is the calculated frequency.<\/li>\n<\/ul>\n\n\n\n<p><\/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 HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)\n\n{\n\n\tif (htim-&gt;Channel == HAL_TIM_ACTIVE_CHANNEL_1)\n\t\t{\n\t\t\tif (Is_First_Captured==0) \/\/ if the first rising edge is not captured\n\t\t\t{\n\t\t\t\tTIM1-&gt;CNT = 0;\n\t\t\t\tTIM3-&gt;CNT = 0;\n\t\t\t\tIs_First_Captured = 1;  \/\/ set the first captured as true\n\t\t\t}\n\n\t\t\telse   \/\/ If the first rising edge is captured, now we will capture the second edge\n\t\t\t{\n\t\t\t\tcounter1 = TIM1-&gt;CNT;\n\t\t\t\tcounter3 = TIM3-&gt;CNT;\n\n\t\t\t\tfrequency = ((float)10000000)\/(float)((counter3*10000)+counter1);\n\n\t\t\t\tIs_First_Captured = 0; \/\/ set it back to false\n\t\t\t}\n\t\t}\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>For more information about input capture, please refer to <a href=\"https:\/\/blog.embeddedexpert.io\/?p=3492\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=3492\" target=\"_blank\" rel=\"noreferrer noopener\">this<\/a> guide.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In user code begin 2 in main function, start timer 1 in capture mode and timer 3 in base 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_TIM_IC_Start_IT(&amp;htim1, TIM_CHANNEL_1);\n  HAL_TIM_Base_Start(&amp;htim3);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the guide.<\/p>\n\n\n\n<p>Build the project and start a debugging session and add frequency to the live expression.<\/p>\n\n\n\n<p>Note: I will use OLED to display the frequency, for how to interface the OLED display, you can refer to <a href=\"https:\/\/blog.embeddedexpert.io\/?p=3700\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=3700\" target=\"_blank\" rel=\"noreferrer noopener\">this guide<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>10KHz Pulse signal<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/IMG_8691.heic\" alt=\"\" class=\"wp-image-4012\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>100KHz pulse signal.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/IMG_8692.heic\" alt=\"\" class=\"wp-image-4013\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>200KHz pulse signal:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/IMG_8693.heic\" alt=\"\" class=\"wp-image-4014\" \/><\/figure>\n\n\n\n<p>0.5Hz pulse signal:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/IMG_8694.heic\" alt=\"\" class=\"wp-image-4015\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Please note that you can read up to 300KHz. Beyond this, we need to use DMA. <\/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>Cascading two 16-bit timers on the STM32 allows you to build a fully synchronized 32-bit extended timer, overcoming the counting limitations of a single 16-bit peripheral. By configuring one timer as the master and the other as its hardware-driven slave, both counters operate as one continuous 32-bit unit\u2014ideal for long-duration timing, precise period measurements, and [&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-4002","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\/4002"}],"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=4002"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4002\/revisions"}],"predecessor-version":[{"id":4016,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4002\/revisions\/4016"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}