STM32 Timers – Output Compare
In the introductory tutorial, we discussed main building blocks of STM32 Timers. The tutorial can be accessed via the following link.
The heart of STM32 Timer is known as Timer Kernel or Time Base. The Timer kernel (Time Base) lets you count a specific number of counts. For more details on configuring and programming Time Base, refer to the following tutorial.
With Timer Base, Timers can only count specific counts as configured and subsequently can generate single overflow/update event. The problem is normally Microcontrollers have limited onchip timers. Adding more timers not only increases complexity but also power consumption which itself is one of the major constraint in embedded systems. In order to solve the problem, each timer hardware (depends on timer e.g. Basic Timer, GP Timers, Advanced Timers) is equipped with addition hardware knows as Timer Channels. Let’s introduce Timer channels before moving further to channel programming. so:
- What is STM32 Timers Channels?
The Timer Channels Unit:
A timer channel is the part of timer hardware by means of which a timer peripheral can interact with its onchip/offchip hardware.
Each timer can drive up to four different channels that can be configured as:
- Input Capture
- Output Compare
- PWM Mode
- One-pulse Output
The focus of this tutorial is on Output Compare. Other features like Input Capture, PWM etc. will be discussed in their relevant tutorials.
Timer Channels as Output Compare: 
When configured as an output, the timer channel is used to generate a set of possible waveforms. As long as the channel is configured in output mode, the content of the TIMx_CCRy channel register is compared to the content of the timer counter.
Based on the results of this continuous logic comparison and based on the configured output sub-mode (like PWM1 mode or Inactive mode), the timer channel internal output OCyREF is either set or reset.
The timer channel internal output OCyREF is then fed into the channel output stage. The channel output stage applies a set of conditioning operations on the OCyREF signal based on a set of configured parameters (like channel polarity configuration or dead-time generation among others).
The output signal of the channel output stage is mapped to the microcontroller pins as an alternate function.
That’s enough introduction to Timers channels configured as output. Let’s get back to programming Timers channel.
In this tutorial we will configure all four channels of Timer-4 in Output Compare mode. The reason why Timer-4 is chosen is because Timer-4 channels output stage signals are mapped to GPIOD Pin#12,13,14,15 as alternate function, Figure-2; also the GPIOD Pin#12,13,14,15 are connected to four onboard separate LEDs. In a cycle of 500ms each LED is Blinked by Timer-4 Output Compare channel.
The tutorial requires programming the following steps:
- Configure GPIOD LED Pins as Alternate Function AF2 (Timer-4 function)
- Configure Time base
- Configure Timer Channel
1. Configuring GPIO as Alternate Function:
The first step is to configure GPIOD Pin#12,13,14,15 as an alternate function so that GPIO pins are not available for general purpose IO. In order to internally connect GPIOD pins to Timer-4 output compare signal (As alternate Function), GPIOD pins must be configured to AF2. For more details on how to configure GPIO Pins as alternate function, refer to the following tutorial:
2. Time Base Configuration:
For illustration purpose we have programmed Timer-4 time-base to count time equal to 500ms time slot. The time-base continuous counts for 500ms delay. Programming time-base is straight forward and well explained in before mentioned tutorial with link given bellow.
After each 125ms, one of four channels, CH1,2,3,4 sequentially toggles GPIOD Pins#12,13,14,15 respectively, Figure-3.
3. Configuring Timer Channels:
The last step, which is the heart of this tutorial, is configuring and programming the timer channels. We will explain this portion in detail.
Programming Timer channel is very simple and straight forward. Following are the steps to configure Timer channel.
- Configuring Channel as an Output Compare
- Configuring Channel Trigger Points
- Starting Output Compare Logic
3.1 Configuring Channel as an Output Compare:
Before a Timer channel can be used, the channel direction needs to be configured properly as input/output. Channel direction can be selected by setting CCxS-bits in TIMy_CCMRz register where x=Channel No (1-4), y=Timer No, z=1(CH#1,2),2(CH#3,4)-Figure4,5.
In order to set channel as output, CCxS-bits must be cleared for channel x. By default, channel is configured as output.
/* Set all four channel to output mode (default mode) */ __clearbit(TIM4->CCMR1, 0U); __clearbit(TIM4->CCMR1, 1U); __clearbit(TIM4->CCMR1, 8U); __clearbit(TIM4->CCMR1, 9U); __clearbit(TIM4->CCMR2, 0U); __clearbit(TIM4->CCMR2, 1U); __clearbit(TIM4->CCMR2, 8U); __clearbit(TIM4->CCMR2, 9U);
The next step is to set what should be done to OCxREF signal. According to , following states can be set via OCxM[2:0] when TIMx_CNT=TIMx_CCR (described later).
- frozen â€“ signal state is ignored, nothing happens
- set active (forced high)
- set inactive (forced low)
The following table summarizes Output Compare Modes.
|001||Set High on match|
|010||Set Low on match|
|100||Force inactive level – OCxREF is forced low.|
|101||Force active level – OCxREF is forced high.|
|110||PWM mode 1|
|111||PWM mode 2|
In our case, we want to toggle OCxREF when TIMx_CNT=TIMx_CCR so OCxM[2:0] need to be set to 0b011.
/* Timer channel to toggle OCxREF signal upon compare. Default value OCxM[2:0] = 0b000 */ __setbit(TIM4->CCMR1, 4U); __setbit(TIM4->CCMR1, 5U); __setbit(TIM4->CCMR1, 12U); __setbit(TIM4->CCMR1, 13U); __setbit(TIM4->CCMR2, 4U); __setbit(TIM4->CCMR2, 5U); __setbit(TIM4->CCMR2, 12U); __setbit(TIM4->CCMR2, 13U);
3.2 Configuring Channel Trigger Points:
As per the tutorial requirement describe earlier (Figure-3), channel-1 should trigger and toggle CH1REF (connected to GPIOD Pin#12) at 125ms (count=2000) from the time base starting point. Similarly Channel-2,3,4 should toggle GPIOD Pins#13,14,15 at 4000, 6000, and 8000 of TIM4_CNT register.
The triggering point for each channel can be set via TIMx capture/compare register (TIMx_CCRy) where x=timer no., y=Channel no. – Figure-6.
/* Set Compare Trigger Points */ TIM4->CCR1 = 2000U; TIM4->CCR2 = 4000U; TIM4->CCR3 = 6000U; TIM4->CCR4 = 8000U;
3.3 Kick Start Output Compare Logic:
The last step is to start output compare logic for active comparison. This can be done by writing 1 to CCxE in TIMx capture/compare enable register (TIMx_CCER) – Figure-7.
/* Enable Output Compare Channel */ __setbit(TIM4->CCER, 0U); __setbit(TIM4->CCER, 4U); __setbit(TIM4->CCER, 8U); __setbit(TIM4->CCER, 12U);
For complete source code refer to the Github links given at the start of this tutorial.
 – Reference manual-RM0090