Decoding PWM using cross-coupled timers on the STM32F372

The STM32F1xx has some neat features that allow you to cross-couple timers in interesting ways.

In the last post on timers, I synchronized 2 timers by using a master-slave configuration where the master resets the slave on every cycle. This time I use 2 cross-coupled channels of one timer in order to measure a PWM train frequency and mark:space ratio.

The trick to measure PWM is to use one counter to measure the period and the second to measure mark time, the latter reset by the first period counter on every cycle:


Here’s how it works:

  • The pulse train is applied to the pin of Timer 1 channel 1 (T1C1)
  • T1C1 edge detector outputs rising and falling edge signals as shown below.
  • The MUXs are cleverly designed so that you can use the edge signals from one channel to trigger the input of another channel. In this case, falling edge on channel 1 starts counter 2. This is set up in the CCER register.
  • The CCMR1 register is finally used to pick which channel’s edge causes the counter to start. In this case, we want the falling edge of timer1 C1 to start counter 2.
  • The rising edge of the next pulse causes the SMCR block to reset both counters. The value in Counter 1 will be the period and the value in counter 2 the mark. I use the SYSTICK timer to generate an interrupt every 2 seconds for reading the counter values.


Here is code for the STM32F372 that implements PWM detection. The approach for STM32F100 is the same strategy, though there are differences in register lay out:

You May Also Like

About the Author: Liam

Leave a Reply

Your email address will not be published. Required fields are marked *