cancel
Showing results for 
Search instead for 
Did you mean: 

Timer synchronisation

Repwoc
Associate III

I am using a STM32G4 MCU and STM32CubeIDE. 

I want to synchronise two timers (TIM3 and TIM15) that are generating PWM signals so that they both start at the same time. 

TIM3 is set to 250 kHz and the PWM is modulated via DMA on channel 1.  The modulated signal is a 10 kHz sine wave.

TIM15 is set to 10 kHz and the PWM is a simple 50% duty cycle.

I need the timers to start together to ensure that the PW Modulated 10 kHz sine wave (TIM3) is synchronised to the 10 kHz PWM (TIM15).

I thought it would be straight forward enough. 

I have configured TIM15 as master.  In CubeMX I have set Master/Slave Mode (MSM bit) to "Enable (Trigger delayed for master/slaves simultaneous start)" and Trigger Event Selection to "Enable (CNT_EN)".

I have configured TIM3 as a slave.  In CubeMX I have set Slave Mode to "Trigger Mode" and Trigger Source to "ITR6" (per the reference manual).

To the CubeIDE generated code I have added:

  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, BDPos_CCRValue_Buffer, CCRValue_BufferSize);
  HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_1);

  /* USER CODE END 2 */

BDPos_CCRValue_Buffer and CCRValue_BufferSize are a pointer to the sine wave data buffer and the buffer size.

When I run the code the timers are not synchronised.  After debugging through the code I found that TIM3 starts immediately on executing HAL_TIM_PWM_Start_DMA and does not wait for TIM15 to be started.  TIM15 starts when this code is executed:

    /* Enable the Capture compare channel */
    TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
{
  uint32_t tmp;

  /* Check the parameters */
  assert_param(IS_TIM_CC1_INSTANCE(TIMx));
  assert_param(IS_TIM_CHANNELS(Channel));

  tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */

  /* Reset the CCxE Bit */
  TIMx->CCER &= ~tmp;

  /* Set or reset the CCxE Bit */
  TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
}

TIM15 starts when the last line is executed (ie after /* Set or reset the CCxE Bit */).

Is there a way to make TIM3 wait for TIM15 to start?

Thanks.

 

8 REPLIES 8
Repwoc
Associate III

Sorry there is a typo - should be:

TIM3 starts when this code is executed:

waclawek.jan
Super User

The main point of synchronization is, that in the slave timer, you are not supposed to set TIMx_CR1.CEN in software, but you should leave it cleared (i.e. at 0), and it has to be set by the hardware through the slave-mode controller set to Trigger mode, when TRGI arrives to it from the master.

Also, the master timer won't generate TRGO, if it's set to generate TRGO upon Trigger in TIMx_CR2.MMS, but it is not Triggered (through its slave-mode controller, from some other master).

I don' use Cube/HAL. Those functions may or may not do what you need; they are open source so you can find out yourself.

JW

Repwoc
Associate III

-- in the slave timer, you are not supposed to set TIMx_CR1.CEN in software

I'm not.

TDK
Super User

Should be working. The correct checks are done in HAL. The timer is only enabled if slave mode is not enabled.

stm32g4xx-hal-driver/Src/stm32g4xx_hal_tim.c at 788fe2faa8b83e730bd7baf1024c9aa05be1d657 · STMicroelectronics/stm32g4xx-hal-driver

 

After HAL_TIM_PWM_Start_DMA is called, is the CEN bit set?

If you comment out "HAL_TIM_PWM_Start(&htim15" you still see a PWM signal on TIM3?

If you feel a post has answered your question, please click "Accept as Solution".
Repwoc
Associate III

>> After HAL_TIM_PWM_Start_DMA is called, is the CEN bit set?

Yes.  It is set before running HAL_TIM_PWM_Start_DMA and after, ie it doesn't change.

>> If you comment out "HAL_TIM_PWM_Start(&htim15" you still see a PWM signal on TIM3?

Yes.  The signal on TIM3 starts before HAL_TIM_PWM_Start(&htim15 executes.

When HAL_TIM_PWM_Start_DMA(&htim3 is executed the signal starts on TIM3 when the  TIMx->CCER bit 0 (CC1E) is set in TIM_CCxChannelCmd().

 

> It is set before running HAL_TIM_PWM_Start_DMA

So where does it get set? Step through your code and find out. It is not enabled at reset.

If you feel a post has answered your question, please click "Accept as Solution".
Repwoc
Associate III

If I reset the CEN bit before HAL_TIM_PWM_Start_DMA executes then the signal from TIM3 does not start until TIM15 is started.  However it is not synchronised with TIM 15.

 

Repwoc
Associate III

>> So where does it get set? Step through your code and find out.

Do you mean where in the HAL code?  I don't know yet.  The only code I have added are the two lines to start the timers.