So in the meantime I got the answers to my questions.

When CH1 triggers, the TIM3->SR register gets the value of 0x0000001f. I have looked at it in the debugger. The other channels are not even set up, so their interrupts should be disabled, right?

Well as it turns out, the channels, which are "not set up" are rather in their reset states. So the reset register settings apply to them.

It enters the TIM3_IRQHandler function and it executes the ISR of all the channels. Not only that, but it doesn't even reset the CCxIF bits when I tell it to. It just goes over the line and does nothing. According to the debugger, the TIM3->SR value remains unchanged.

Yes, it executes them, because the interrupt flags are set, no matter the settings in the TIMx->DIER register. The TIMx->DIER register serves only to set whether an interrupt is made, not if the interrupt flag sets or not. So what happened is, the CCRx registers of the unused channels were 0, and when the CNT register reached 0, they set the corresponding CCxIF interrupt flags. So in the interrupt handler I have to check not only if the interrupt flag is set for the channel, but if the channel DIER bit is enabled.

The reason all flags appeared to set at once is because in debugging mode the timer clock continued to tick, even when the code execution halted. That explains everything else that was unclear.

Answer from inaseaofsalt on Stack Exchange
🌐
Medium
medium.com › @pqshedy33 › what-is-output-compare-mode-on-stm32-timers-1b231988274b
What is output compare mode on STM32 timers? | by Ampheo | Medium
October 9, 2025 - The Output Compare mode is a fundamental feature of STM32’s timer peripherals. Its core function is to compare the current value of the Timer Counter (CNT) register with a pre-loaded value in the Capture/Compare Register (CCR).
🌐
EmbeddedExpertIO
blog.embeddedexpert.io
STM32 Timers Applications: Output Compare Mode – EmbeddedExpertIO
This is very useful for applications ... Waves and Clocks) By configuring Output Compare to “Toggle on Match,” STM32 timers can generate clean and stable square waves for use as clocks for other devices, audio signals, or simple waveform generation....
Discussions

embedded - Generating waveform using STM32 timer compare - STM32F3Discovery - Stack Overflow
I am attempting to generate a waveform with a period of 33ms. In-between each period, I need to toggle the timer output 5 times with a varying timescale. My initial thought is to do this using a ti... More on stackoverflow.com
🌐 stackoverflow.com
STM32 PWM and Output Compare - Electrical Engineering Stack Exchange
In my configuration of the STM32 I have used two synchronized timers, master and slave. The master generates the PWM (channel 1) TRGO update event, and the slave is configured as external clock 1, trigger timer master, output compare no output channel 1. More on electronics.stackexchange.com
🌐 electronics.stackexchange.com
timer - TIMx CHx in Output Compare Mode using STM32F4 series and Configuring CubeMx - Stack Overflow
My SYSCLK = 100MHz As I want to generate output pulse for 10 microsec., The timer clock frequency would be = 1/10microsec. = 100KHz or 100,000 Hz. ... Now, I also came across a formula to calculate the ARR value after finding the PSC value. (ref:- Programming STM32 book) More on stackoverflow.com
🌐 stackoverflow.com
embedded - STM32 Timer Output compare not working proper - Stack Overflow
I am using STM32L476 Nucleo board and STM32CubeMX. I want to use Output Compare channel 1 for timeout of 2 ms. I have configured the timer, but the timer is not giving interrupts for Output Compare... More on stackoverflow.com
🌐 stackoverflow.com
🌐
DeepBlue
deepbluembedded.com › home › blog › stm32 timers tutorial | hardware timers explained
STM32 Timers Explained Tutorial - Timer Modes Examples Interrupts pwm
January 20, 2024 - All standard IR pulse modulation modes can be obtained by programming the two-timer output compare channels. TIM15 is used to generate the high-frequency carrier signal, while TIM16 generates the modulation envelope.
🌐
Stack Overflow
stackoverflow.com › questions › 78469205 › generating-waveform-using-stm32-timer-compare-stm32f3discovery
embedded - Generating waveform using STM32 timer compare - STM32F3Discovery - Stack Overflow
My thinking is that the DMA is not transferring values from the array to the timer compare register (CRR), some DMA transfer flags are not properly setup or either the CRR has a value of 0 or 33000. Still scratching my head reading the reference manual to find something, will post any update if I can figure this out... new waveform with 6 pulses · timer · embedded · stm32 ·
Find elsewhere
🌐
STMicroelectronics
st.com › resource › en › application_note › an4013-introduction-to-timers-for-stm32-mcus-stmicroelectronics.pdf pdf
AN4013 Application note - Introduction to timers for STM32 ...
February 1, 2026 - These counters are numbered differently. In the STM32C5 · series, the TIM15, TIM16, and TIM17 counters support up, down, and up/down modes autoreload counter modes. ... Low-power timer and high-resolution timer do not have channels directly comparable with channels on regular timer peripherals.
🌐
Medium
medium.com › @csrohit › output-compare-mode-on-stm32f4-timers-6d961162bbe2
Output Compare Mode on STM32F4 Timers | by Rohit Nimkar | Medium
May 15, 2025 - The action taken on a match depends on the OCxM (Output Compare Mode) bits in the CCMRx register: Toggle: The output pin toggles its logic state (high ↔ low). Set/Reset: The output pin is set high or low. PWM: The output pin generates a PWM waveform. ... It monitors the timer counter. When a match occurs, it performs the programmed action on the output pin (see Figure 2 in AN4776). Any STM32F4 board (I’m using an STM32F401, but this works on most STM32F4 MCUs)
🌐
EmbeddedExpertIO
blog.embeddedexpert.io
Working with STM32 and Timers part 6: Output Compare – EmbeddedExpertIO
Posted November 22, 2021 by Husamuldeen ... to the maximum level (set by the ARR), the following will happen: Assigns the corresponding output pin to a programmable value defined by the output compare mode....
🌐
STMicroelectronics Community
community.st.com › t5 › stm32-mcus-products › is-it-possible-to-compare-compare-the-output-using-stm32-s-timer › td-p › 80742
Is it possible to compare compare the output using STM32's timer interrupts
February 17, 2022 - I am currently learning to use timer interrupts using the HAL library on the STMF769I-DISCO. I am trying to get the interrupt to activate when it reaches a certain value. From my understanding, the interrupt activates when the counter period overflows. As I'll have different time periods to compare,...
🌐
STMicroelectronics Community
community.st.com › t5 › stm32-mcus-products › how-do-i-set-a-timer-output-compare-high-or-low › td-p › 696652
Solved: How Do I set a Timer output compare high or low? - STMicroelectronics Community
July 12, 2024 - I am working on a project that uses a PWM on a timer to drive a buzzer. When the buzzer stops I need to set the output compare signal high. The timer set ARR to 250, and the compare value to 125, giving a 4kHz square wave with a 50% duty cycle. I start the timer by enabling it (TIM2->CR1 &= ~TIM_CR1_CEN), and stop the timer by disabling it.
Top answer
1 of 1
1

You don't need the complexity of chained timers to achieve this on STM32. You can either use TIM_RCR for certain timers to have a Nth UEV interrupt change polarity, or you can simply implement a software counter in an UEV interrupt handler to emulate RCR.

But the most important thing is to use preloaded OC register control for correct glitch-free operation. There are two modes of preloaded control that you can use (TIM1 as an example):

  1. Output in PWM mode with preloaded OC control:
TIM1_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM1;

In this mode, TIM_CCR1 is preloaded, i.e. any changes to it will be applied after UEV (update event). In other words, every write operation changes the next duty cycle, not the current.

This mode is mandatory for glitch-free PWM mode operation.

  1. Preloaded commutation control:
TIM1_CR2 = TIM_CR2_CCPC;

In this mode, changes to certain bits in the TIM1_CCMRx and TIM1_CCER registers are preloaded. The values programmed are applied upon COM (commutation event) which can arrive either as a trigger or via TIM1_EGR = TIM1_EGR_COMG.

This mode is required for glitch-free commutation control.


In your code, you change polarity via TIM2_CCER without any preloaded control enabled, hence glitches are unavoidable. It's also worth noting that your code has excessive latency due to weird statements like while(TIM2->CNT);. In correctly written code, changing polarity even without preloaded control will still give good results albeit not ideal.

The initial requirement is: The original firmware generates PWM (duty cycle 50%) and every 8 cycles inverts the signal

It's hard to come with a good solution without further details. It's unknown, for example, whether duty cycle is always fixed at 50% or should change. If it's fixed, we can come up for instance with another approach - use timer PWM mode with preloaded OC control at twice the frequency and have duty cycle alternate between 0% and 100% in a preloaded fashion. At the 8th iteration, alternation changes.

A very simplified interrupt-based example:

void tim1_up_isr(void) {
    static int n;
    if (!(++n & 7)) return; // Change polarity every 8th iteration, i.e. do not alternate
    TIM1_CCR1 ~= TIM1_CCR1; // Alternate duty cycle between 0% and 100%
}

...
TIM1_BDTR = TIM_BDTR_MOE; // Enable main output
TIM1_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM1; // PWM1 mode, buffered CCR1
TIM1_CCER = TIM_CCER_CC1E; // Enable output
TIM1_DIER = TIM_DIER_UIE; // Enable UEV interrupt

The above is just an example of the preloaded PWM control concept and in no way is the most efficient code.

In the ultimate case, when duty cycle can change and on-the-fly polarity/mode change is required, the only correct way is to use both preloaded commutation control and PWM mode with preloaded OC control.

🌐
EmbeddedExpertIO
blog.embeddedexpert.io
Getting Started with STM32F103: Output Compare Mode in Timer – EmbeddedExpertIO
Now, in TIMx capture/compare mode register 1 which is responsible for CH1 and CH2, we need to set OC1M in Toggle on Match Mode as following: ... #include "stm32f1xx.h" int main(void) { RCC->APB2ENR|=RCC_APB2ENR_IOPAEN; /*Configure PA0 as Output Alternate Push/Pull */ GPIOA->CRL|=GPIO_CRL_MODE0; GPIOA->CRL|=(GPIO_CRL_CNF0_1); GPIOA->CRL&=~(GPIO_CRL_CNF0_0); /*Don't remap the pin*/ AFIO->MAPR&=~AFIO_MAPR_TIM2_REMAP; /*Enable clock access to timer2*/ RCC->APB1ENR|=RCC_APB1ENR_TIM2EN; /*Configure timer2*/ TIM2->PSC=8000-1; TIM2->ARR=1000-1; TIM2->CCMR1|=TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1M_1; TIM2->CCER|=TIM_CCER_CC1E; TIM2->CR1|=TIM_CR1_CEN; while(1) { } }
🌐
EmbeddedExpertIO
blog.embeddedexpert.io
Getting Started with STM32G0 and STM32CubeIDE: Timer in Output Compare – EmbeddedExpertIO
• Interrupt/DMA generation on ... In STM32 microcontrollers, the Output Compare (OC) mode in the timer peripheral allows you to generate a waveform with a predefined period and pulse width....
🌐
MathWorks
mathworks.com › stm32 microcontroller blockset › peripherals › timer peripherals
Timer Capture - Output the capture compare register value - Simulink
Run a Simulink model on STM32 processor. ... The channel port output the capture compare register value of the corresponding selected channel. ... Outputs if overrun occurs during reading the capture compare register. ... To enable this port, select the Output status parameter. ... To enable this port, select the Enable timer counter direction output parameter.