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
This post pulls together the work from prior posts on the timers, ADC, DMA and GPIU for the STM32F372.
The idea is to get the MCU to do periodic ADC measurements and store the results away on its own without needing the CPU to intervene. This means no interrupts or polling, just the peripheral blocks working together on their own. This type of design is becoming more and more common in the low power world where the CPU and its subsystem is kept asleep, leaving the peripherals to do their job with the CPU only woken when some control needs doing.
The demo works like this:
Timer 2 is set up to produce a PWM train with a 5 second period. I use 2 channels in the same counter with the same mark:space ratio settings so that the first can drive the ADC whilst the second flashes an LED so that I know something is happening…
Timer2 has a nice feature where you can set it to send a Trigger Event at each Update Event (UEV). Here I set the UEV to be when the counter spills over the period
For this demo I used 3 of the counter timers on the STM32F372 to generate pulse trains of differing frequencies, made more interesting by adding 2 things:
(1) Chaining of timers using synchronization. Surprisingly, even when 2 timers driven by the onboard clock of the F372 are started at the same time, within 30 secs they have often drifted apart by as much as 500mS. This could be caused by differing path lengths on the SoC. The problem can be solved by using the on-board triggering mechanism which allows one timer to generate triggers that will drive another at selectable events. I used this feature to reset the second timer to the first on every cycle, thereby minimizing drift.
(2) Generating a periodic interrupt using the CortexM3 core SYSTICK clock. The SYSTICK clock only has a couple of configuration registers and is much simpler than the CTC Timers. Easy.
The programmers’ models for the timers used in the STM32F1xx and F37x series are similar. I guess ST reused the same IP blocks… There