Using Output Compare Timers on STM32

I recently had to use an STM32 to generate a signal for an infrared control scheme. This specific example code was written for a STM32F103 using the STM32F1 HAL v1.1.0. However, the timer control code is very similar across the entire STM32 family so this should be quite portable.

In the following code, I am setting up timer 3 (TIM3) to toggle at 38khz. The counter is operating in count-up output compare mode. This is where the timer counts up at the clock speed divided by a prescaler (PSC), toggling a pin when the counter value (CNT register) passes a certain value (CCRx register, or Pulse in HAL-speak). When the CNT equals the ARR register (Period), it resets to 0. The timer can also operate in countdown mode, where the ARR value is loaded in to CNT when it reaches 0. This cycle repeats indefinitely.

Here's the output on my scope to verify (note the 38.5khz at the bottom - the variation is likely due to using the internal oscillator, rather than an external crystal):

scope output

If you need to toggle at a slower frequency, you can increase the prescaler and/or period. On the 16 bit general timers, the slowest you can toggle is (given a 64mhz clock with a prescaler & period of 0xFF) is 64000000 / 65535 / 65535 / 2 = 0.007450808hz, or approximately 134 seconds

There are a couple of gotchas that you need to be careful of. The first, is making sure you enable the clocks for both the timer, and the GPIO that you are using. Secondly, when setting the prescaler, under the hood, 1 is being added to it. So a value of 0 avoids prescaling, and a value of 1 halves the clock speed. Finally, make sure you've set the GPIO pin to the appropriate alternate function.

I recommend taking a look at ST's AN4013 application note which goes in to detail about all of the different timer modes.