Skip to main content
Associate
August 26, 2026
Question

The reason why TIM14->CCR1 = 50 and TIM9->CCR2 = 49 coexist

  • August 26, 2026
  • 5 replies
  • 149 views

The reason why TIM14->CCR1 = 50 and TIM9->CCR2 = 49 coexist

1. Background and Configuration

· Chip: STM32F407ZGTx
· Connection: TIM14_CH1 (PF9) outputs PWM, connected via jumper to TIM9_CH1 (PE5) for input capture

TIM14 (PWM output) configuration:

· Clock 50 MHz, prescaler 4999, counting frequency 10 kHz
· Up-counting mode, ARR = 199, CCR1 = 50
· PWM Mode 1, active high

TIM9 (input capture) configuration:

· Clock 50 MHz, prescaler 4999, counting frequency 10 kHz
· Slave mode: Reset mode, trigger source TI1FP1 (rising edge)
· CH1: rising edge direct capture (CCR1)
· CH2: falling edge indirect capture (CCR2)

2. Observed Phenomenon

In the capture interrupt, the following registers are read:

```c
uint16_t IC1_Width = __HAL_TIM_GET_COMPARE(&htim9, TIM_CHANNEL_1); // TIM9->CCR1
uint16_t IC2_Pulse = __HAL_TIM_GET_COMPARE(&htim9, TIM_CHANNEL_2); // TIM9->CCR2
uint16_t CCR       = __HAL_TIM_GET_COMPARE(&htim14, TIM_CHANNEL_1); // TIM14->CCR1
```

LCD display results:

Register Value Meaning
TIM14->CCR1 50 PWM compare threshold set by user
TIM9->CCR1 199 Rising edge capture value (period)
TIM9->CCR2 49 Falling edge capture value (pulse width)

Core confusion: Why is TIM14's CCR1 50, while TIM9 captures the falling edge of the same PWM waveform and CCR2 is 49? The two differ by 1. Is this expected behavior of the STM32 timer? I asked an AI, and it told me: when the falling edge triggers, TIM9's CNT has not yet become 50, it is still 49.

So CCR2 = 49. The counter increment and the edge detection latching occur in the same clock cycle, but the latching action occurs before the counter increment. Inside the STM32 timer, when the counting clock edge arrives, the hardware first checks whether there is an input capture event (falling edge). If there is, it immediately latches the current CNT value (which is still the old value 49) into the CCR, and then the CNT performs the +1 operation to become 50.

Therefore, the falling edge latches the pre-increment value of 49. Is this statement correct?

5 replies

waclawek.jan
Super User
August 26, 2026

Most likely the two timers don’t run synchronously, TIM9 lags behind TIM14. I see that you try to synchronize them by using master-slave interconnection, but maybe there’s something incorrect there. Hard to judge without seeing content of all TIM registers.

You can check this by removing the connection and setting both TIM14 and TIM9 to output PWM and observe both by oscilloscope/logic analyzer.

JW

Associate
August 27, 2026

STM32F407 PWM Input Capture Phenomenon Description

Phenomenon Description

As suggested, tests were performed with an oscilloscope: both TIM14 and TIM9 were configured as PWM outputs with identical parameters (ARR=199, CCR=50). The rising edges of the two PWM signals are perfectly aligned with no phase shift, which indicates there is no synchronization lag between the two timers.

In this experiment, TIM9 is used to capture the PWM signal output by TIM14 via jumper wires.

• Read value of TIM14’s CCR register: 50 (the Pulse width configured in IOC is also set to 50)

• Captured CCR value obtained by TIM9: 49
Note: CCR here refers to pulse width.
Complete Timer Register Configuration & IOC Settings

1. Clock Tree

External high‑speed crystal HSE = 8 MHz
PLLM=4, PLLN=100, PLLP=2 → PLL clock = 100 MHz
SYSCLK = 100 MHz
HCLK = 100 MHz
APB1 = 25 MHz (divided by 4) → TIM14 timer clock = 25×2 = 50 MHz
APB2 = 25 MHz (divided by 4) → TIM9 timer clock = 25×2 = 50 MHz

2. IOC Configuration (from .ioc project file)

TIM14 (PWM Generation)

• TIM14 Channel: TIM_CHANNEL_1

• Prescaler: 4999

• Period: 199

• Pulse: 50

TIM9 (PWM Input Capture)

• Prescaler: 4999

• Period: 50000

NVIC

• TIM1_BRK_TIM9_IRQn enabled, Preemption priority = 0, Sub‑priority = 0

Pins

• PF9 → TIM14_CH1 (PWM output)

• PE5 → TIM9_CH1 (input capture, externally jumpered to PF9)

3. TIM14 Register Configuration (PWM Output, MX_TIM14_Init())
htim14.Instance               = TIM14;
htim14.Init.Prescaler         = 4999;          // PSC prescaler
htim14.Init.CounterMode       = TIM_COUNTERMODE_UP; // Up‑counting mode
htim14.Init.Period            = 199;           // ARR auto‑reload
htim14.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

// PWM Channel 1
sConfigOC.OCMode       = TIM_OCMODE_PWM1;       // CCMR1.OC1M=110 PWM Mode 1
sConfigOC.Pulse        = 50;                    // CCR1 compare value
sConfigOC.OCPolarity   = TIM_OCPOLARITY_HIGH;   // Active high
sConfigOC.OCFastMode   = TIM_OCFAST_DISABLE;

// GPIO: PF9, AF9, push‑pull output, no pull‑up/pull‑down
Key registers:

• TIM14_PSC = 4999

• TIM14_ARR = 199

• TIM14_CCR1 = 50

• TIM14_CCMR1 = 0x0060 (OC1M=110 PWM1, OC1PE=0)

• TIM14_CCER = 0x0001 (CC1E=1 enabled, CC1P=0 rising edge)

• TIM14_CR1 = 0x0000 (ARPE=0, edge‑aligned, up‑counting)

• TIM14_CR2 = 0x0000 (MMS=000, no TRGO output)
Important: TIM14_CR2.MMS=000. TIM14 does not generate TRGO trigger signal; master timer mode is not configured.
4. TIM9 Register Configuration (Input Capture, MX_TIM9_Init())
htim9.Instance               = TIM9;
htim9.Init.Prescaler         = 4999;          // PSC prescaler
htim9.Init.CounterMode       = TIM_COUNTERMODE_UP; // Up‑counting mode
htim9.Init.Period            = 50000;         // ARR auto‑reload
htim9.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
htim9.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

// Clock source: internal clock
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

// Slave mode: Reset mode
sSlaveConfig.SlaveMode        = TIM_SLAVEMODE_RESET;       // SMCR.SMS=100
sSlaveConfig.InputTrigger     = TIM_TS_TI1FP1;             // SMCR.TS=101, trigger source TI1FP1
sSlaveConfig.TriggerPolarity  = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
sSlaveConfig.TriggerFilter    = 0;

// Channel 1: rising‑edge direct capture, CCR1 stores period value
sConfigIC.ICPolarity  = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter    = 0;

// Channel 2: falling‑edge indirect capture, CCR2 stores pulse width
sConfigIC.ICPolarity  = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter    = 0;

// GPIO: PE5, AF3, push‑pull input, no pull‑up/pull‑down
// NVIC: TIM1_BRK_TIM9_IRQn, priority 0,0
Key registers:

• TIM9_PSC = 4999

• TIM9_ARR = 50000

• TIM9_CCMR1 = 0x0201 (CC2S=10 indirect TI1, CC1S=01 direct TI1)

• TIM9_CCER = 0x0031 (CC2P=1 falling‑edge, CC2E=1 enabled; CC1P=0 rising‑edge, CC1E=1 enabled)

• TIM9_SMCR = 0x0054 (SMS=100 reset mode, TS=101 select TI1FP1)

• TIM9_CR1 = 0x0000

• TIM9_DIER = 0x0002 (CC2IE=1, enable channel‑2 capture interrupt)

5. Key Points

There is no master‑slave hardware interconnection between TIM14 and TIM9:

• TIM14_CR2.MMS=000: TIM14 does not generate TRGO trigger signal

• TIM9_SMCR.TS=101: TIM9’s trigger source is its own pin PE5 (TI1FP1), not TIM14’s internal TRGO.

TIM9 Reset Mode: TIM9 counter is cleared when the rising edge of external PWM arrives at pin PE5, not triggered by internal signal from TIM14.
This is standard PWM input‑capture configuration: slave mode is used to measure PWM period, not to synchronize with the source timer.

6. Oscilloscope Verification Result

TIM9 was re‑configured as PWM output (ARR=199, CCR=50). PF9 (TIM14) and PE5 (TIM9) were observed on oscilloscope:
The rising edges of both PWM signals are perfectly aligned, with no phase shift or lag.

It proves that the two timers run synchronously (both clocked at 50 MHz with identical prescaler, started consecutively in code). The captured CCR2 value of 49 is not caused by timer synchronization lag.

TDK
August 27, 2026

If you use TIM14 as input and TIM9 as output, do you get the same result? Could be a slight delay between timers (even if they are synchronous).

"If you feel a post has answered your question, please click ""Accept as Solution""."
waclawek.jan
Super User
August 27, 2026

TIM9 Reset Mode: TIM9 counter is cleared when the rising edge of external PWM arrives at pin PE5, not triggered by internal signal from TIM14.

 

OK I see. I overlooked that in your first post, sorry. But it would be enough to post the complete set of registers, I react to them better than to narrative (as I’m used to debug by observing the registers’ content), and there’s no need for .ioc or the generated code. 

This is then the source of what you observe. It takes somewhere between one to three cycles (sadly ST does not specify how many) between the detected edge and the moment when the actual reset occurs. 

Try the same experiment without prescaling in the timers, i.e. use both TIMx_PSC=0 and say TIM14_ARR=10000 TIM14_CCR1=5000; TIM9_ARR=65535. You should see TIM9_CCR1 to be something like 9998 and TIM9_CCR2 4498 or so, and that gives you the reset’s lag.

JW

 

PS. Btw. TIM14’s maximum specified clock frequency is 42MHz, since it is at APB1.

waclawek.jan
Super User
August 31, 2026

The reset lag had been characterized for a particular setup by ​@Tesla DeLorean in the past.

JW