{"id":3708,"date":"2025-08-24T08:35:45","date_gmt":"2025-08-24T08:35:45","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3708"},"modified":"2025-08-24T08:35:48","modified_gmt":"2025-08-24T08:35:48","slug":"stm32-timers-applications-pwm-input-mode","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3708","title":{"rendered":"STM32 Timers Applications:\u00a0PWM Input Mode"},"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\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-1024x683.png\" alt=\"\" class=\"wp-image-3709\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-1024x683.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-300x200.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-768x512.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-1150x767.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-750x500.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-400x267.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM-250x167.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/ChatGPT-Image-Aug-24-2025-at-10_40_00-AM.png 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>PWM Input mode on STM32 timers is a powerful feature that allows the microcontroller to directly measure the characteristics of an incoming PWM signal, such as its frequency and duty cycle. By configuring the timer\u2019s input capture channels appropriately, the signal\u2019s high time and period can be automatically captured and processed with minimal CPU intervention.<\/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 to PWM input mode.<\/li>\n\n\n\n<li>STM32CubeIDE setup.<\/li>\n\n\n\n<li>Firmware development.<\/li>\n\n\n\n<li>Connection.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction to PWM Input Mode:<\/h2>\n\n\n\n<p>PWM Input mode on STM32 timers is widely used when an external PWM signal needs to be measured and analyzed, such as in motor control, sensor interfaces, or communication with other devices that encode data into PWM pulses. In this mode, the timer is configured to operate with two input capture channels: one channel measures the period of the PWM signal, while the other captures the high time of the pulse. By comparing these two captured values, both the duty cycle and the frequency of the signal can be determined precisely.<\/p>\n\n\n\n<p>Internally, the timer hardware takes care of synchronizing the capture events, eliminating the need for complex software routines to measure pulse widths. This makes the measurement accurate even at high input frequencies and ensures that CPU load remains low. For example, in motor speed monitoring, the incoming PWM from a speed sensor can be directly connected to the timer input, and the timer hardware will continuously capture the signal\u2019s characteristics without requiring constant polling.<\/p>\n\n\n\n<p>The main advantage of using PWM Input mode is that the process is entirely handled in hardware. This ensures robustness, reduces jitter, and improves measurement precision compared to software-based timing methods. Additionally, when combined with interrupts or DMA, the captured values can be transferred seamlessly into memory for further processing, allowing real-time systems to handle PWM measurements efficiently.<\/p>\n\n\n\n<p>Because of these features, PWM Input mode is a cornerstone technique in many embedded applications, ranging from servo control feedback, ultrasonic sensor measurements, and digital communication decoding, to general-purpose frequency or duty cycle monitoring. It provides a reliable bridge between the analog world of pulse signals and the digital logic of the microcontroller, making it one of the most practical uses of STM32\u2019s advanced timer peripherals.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeIDE Setup:<\/h2>\n\n\n\n<p>Open STM32CubeIDE after selecting the workspace and create new project as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"355\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-1024x355.jpg\" alt=\"\" class=\"wp-image-2940\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-1024x355.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-300x104.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-768x266.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-1536x532.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-2048x709.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-1150x398.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-750x260.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-400x139.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-26-00-250x87.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Select the MCU:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"832\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-1024x832.jpg\" alt=\"\" class=\"wp-image-2941\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-1024x832.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-300x244.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-768x624.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-1536x1248.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-2048x1664.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-1150x934.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-750x609.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-400x325.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/10\/2024-10-26_16-27-14-250x203.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Give the project a name:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"813\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-813x1024.jpg\" alt=\"\" class=\"wp-image-3710\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-813x1024.jpg 813w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-238x300.jpg 238w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-768x968.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-750x945.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-400x504.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56-250x315.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-46-56.jpg 984w\" sizes=\"(max-width: 813px) 100vw, 813px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Once the project has been created, STM32CubeMX window will appear.<\/p>\n\n\n\n<p>From Clock configuration, set the system clock to maximum (100MHz in this case) and note the timer frequencies as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"517\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-1024x517.jpg\" alt=\"\" class=\"wp-image-3711\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-1024x517.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-300x151.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-768x387.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-1536x775.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-2048x1033.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-1150x580.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-750x378.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-400x202.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_09-48-03-250x126.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Notice that the timers have 100MHz clock frequency.<\/p>\n\n\n\n<p>Next, we shall configure TIM2 to work in PWM input mode.<\/p>\n\n\n\n<p>Head to timers section from Pinout and Configuration, select TIM2 and configure it as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clock Source: Internal Clock<\/li>\n\n\n\n<li>Combined Channels: PWM Input in CH1<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"775\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-1024x775.jpg\" alt=\"\" class=\"wp-image-3712\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-1024x775.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-300x227.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-768x581.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-1150x871.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-750x568.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-400x303.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48-250x189.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-48-48.jpg 1482w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, in parameter Settings:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prescaler to 0 which means maximum speed.<\/li>\n\n\n\n<li>Counter period to maximum (32-bit 0xFFFFFFFF in this case).<\/li>\n\n\n\n<li>Enable auto-reload preload.<\/li>\n\n\n\n<li>Keep the rest as default.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"957\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-957x1024.jpg\" alt=\"\" class=\"wp-image-3713\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-957x1024.jpg 957w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-280x300.jpg 280w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-768x821.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-750x802.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-400x428.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34-250x267.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-52-34.jpg 1150w\" sizes=\"(max-width: 957px) 100vw, 957px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, enable DMA for TIM2_CH1 in circular mode as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"784\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-1024x784.jpg\" alt=\"\" class=\"wp-image-3714\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-1024x784.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-300x230.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-768x588.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-1536x1176.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-1150x880.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-750x574.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-400x306.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04-250x191.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-04.jpg 1568w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, we shall disable the interrupt for the DMA channel related to the timer as follows:<\/p>\n\n\n\n<p>From system core, open NVIC, disable Enforce DMA interrupt and disable the DMA interrupt for the channel as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"956\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-1024x956.jpg\" alt=\"\" class=\"wp-image-3715\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-1024x956.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-300x280.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-768x717.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-1536x1433.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-1150x1073.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-750x700.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-400x373.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56-250x233.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-05-56.jpg 1946w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This way, we will ensure that no DMA interrupt generation will happen and impact the performance our MCU.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, we shall configure TIM5 to generate PWM signal as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"860\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-860x1024.jpg\" alt=\"\" class=\"wp-image-3717\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-860x1024.jpg 860w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-252x300.jpg 252w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-768x915.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-1290x1536.jpg 1290w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-1150x1369.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-750x893.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-400x476.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10-250x298.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-09-10.jpg 1520w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/figure>\n\n\n\n<p>With these parameter, we shall generate PWM signal with 1 MHz frequency and 50% duty cycle. For more information about how to configure the timer in PWM mode, please refer to <a href=\"https:\/\/blog.embeddedexpert.io\/?p=3363\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=3363\" target=\"_blank\" rel=\"noreferrer noopener\">this<\/a> guide.<\/p>\n\n\n\n<p>That all for the configuration. Save the project and it should be generated.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.  Firmware Development:<\/h2>\n\n\n\n<p>Once the project is generated, main.c shall be opened.<\/p>\n\n\n\n<p>Once the main.c has been opened, in user 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;}\">uint32_t CCR1_Value;<\/pre><\/div>\n\n\n\n<p>This variable will hold the measured pulse length (Period) which will determine the frequency of the measured PWM.<\/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;}\">uint32_t CCR2_Value;<\/pre><\/div>\n\n\n\n<p>This will hold the measured length of the pulse (Duty cycle of the PWM signal).<\/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;}\">uint32_t frequency;\n\nfloat duty;<\/pre><\/div>\n\n\n\n<p>These value shall hold the frequency and duty of the signal.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, in user begin 2 in main function, start TIM2_CH1 in input capture in DMA 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_DMA(&amp;htim2, TIM_CHANNEL_1, &amp;CCR1_Value, 1);<\/pre><\/div>\n\n\n\n<p>Start TIM2_CH2 in input capture normal 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(&amp;htim2, TIM_CHANNEL_2);<\/pre><\/div>\n\n\n\n<p>Start the PWM signal:<\/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_PWM_Start(&amp;htim5, TIM_CHANNEL_1);<\/pre><\/div>\n\n\n\n<p>Next, in user code begin 3 in while 1 loop:<\/p>\n\n\n\n<p>First, calculate the frequency of the signal 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;}\">frequency=100000000\/(CCR1_Value);<\/pre><\/div>\n\n\n\n<p>Since the timer will trigger 100 million times per second and CCR1 hold how many pulses from these 100M lasted, by dividing 100M by the captured value, we can get the frequency. CCR1_Value is being updated by DMA, no need to read it manually.<\/p>\n\n\n\n<p>Next, we shall read CCR2 to determine the duty cycle 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;}\">CCR2_Value=HAL_TIM_ReadCapturedValue(&amp;htim2, TIM_CHANNEL_2);<\/pre><\/div>\n\n\n\n<p>Calculate the duty cycle by dividing CCR2\/CCR1 *100 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;}\">duty=(((float)CCR2_Value\/(float)CCR1_Value))*100.0;<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Repeat the cycle each 10 milliseconds:<\/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_Delay(10);<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<p>Build the project and start a debugging session as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"43\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-1024x43.png\" alt=\"\" class=\"wp-image-3512\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-1024x43.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-300x13.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-768x32.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-1536x65.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-1150x48.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-750x31.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-400x17.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image-250x10.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/06\/image.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Connection:<\/h2>\n\n\n\n<p>Since TIM2_CH1 and TIM5_CH1 are PA0 and PA5 respectively. Hence, the connection as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"828\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-1024x828.jpg\" alt=\"\" class=\"wp-image-3718\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-1024x828.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-300x243.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-768x621.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-1536x1242.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-1150x930.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-750x607.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-400x324.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54-250x202.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_11-30-54.jpg 1936w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>Add CCR1_Value, CCR2_Value, duty and frequency to Live Expression<\/p>\n\n\n\n<p>1MHz test:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"370\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-1024x370.jpg\" alt=\"\" class=\"wp-image-3719\" style=\"width:840px;height:auto\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-1024x370.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-300x108.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-768x278.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-1150x416.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-750x271.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-400x145.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37-250x90.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-34-37.jpg 1400w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>10MHz test:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"317\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-1024x317.jpg\" alt=\"\" class=\"wp-image-3720\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-1024x317.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-300x93.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-768x238.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-1150x356.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-750x232.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-400x124.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52-250x77.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-33-52.jpg 1414w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>1KHz:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"433\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-1024x433.jpg\" alt=\"\" class=\"wp-image-3721\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-1024x433.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-300x127.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-768x324.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-1150x486.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-750x317.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-400x169.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39-250x106.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/08\/2025-08-24_10-35-39.jpg 1406w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>It is usable to 5MHz, beyond this, it will drift in terms of measurement.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PWM Input mode on STM32 timers is a powerful feature that allows the microcontroller to directly measure the characteristics of an incoming PWM signal, such as its frequency and duty cycle. By configuring the timer\u2019s input capture channels appropriately, the signal\u2019s high time and period can be automatically captured and processed with minimal CPU intervention. [&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-3708","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\/3708"}],"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=3708"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3708\/revisions"}],"predecessor-version":[{"id":3722,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3708\/revisions\/3722"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}