cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble triggering TIM2 capture compare from TRC

Mttjcksn
Associate III

Hi there,

I'm using the STM32H7 and I need to get one of the SAI FS signals to go through a pre-scaler and trigger a capture compare on TIM2 CC3.

The only solution for this seems to be to use SAI2_FS_A -> TIM5_ETR1 -> TIM5_TRGO -> TIM8_ITR3 -> TIM8_TRGO -> TIM2_ITR1 (Yikes!)

The first few steps of this are working, and I can see a trigger interrupt firing on TIM8. The problem seems to be getting this signal into TIM2 for capture compare.

TIM8 is in slave reset mode, with no channels enabled and TRGO generated from Reset.

TIM2 is not in slave mode, ITR1 as trigger input, and has Channel 3 configure to capture compare triggered by TRC.

If I put TIM2 into slave trigger mode, I can see and trigger interrupt occur on TIM2, so I assume that the TIM8_TRGO -> TIM2_ITR1 is configured correctly. Capture compare 3 never occurs whether slave trigger mode is enabled or disabled.

Where might I be going wrong?

Relevant code is below.

Many thanks!

TIM2 init:

static void MX_TIM2_Init(void)
{
 
  /* USER CODE BEGIN TIM2_Init 0 */
 
  /* USER CODE END TIM2_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
 
  /* USER CODE BEGIN TIM2_Init 1 */
 
  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 199999999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
  sSlaveConfig.InputTrigger = TIM_TS_ITR1;
  if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICSelection = TIM_ICSELECTION_TRC;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
TIM2->DIER |= 0b1001000;
  /* USER CODE END TIM2_Init 2 */
 
}

TIM8 init:

static void MX_TIM8_Init(void)
{
 
  /* USER CODE BEGIN TIM8_Init 0 */
 
  /* USER CODE END TIM8_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
  /* USER CODE BEGIN TIM8_Init 1 */
 
  /* USER CODE END TIM8_Init 1 */
  htim8.Instance = TIM8;
  htim8.Init.Prescaler = 65535;
  htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim8.Init.Period = 65535;
  htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim8.Init.RepetitionCounter = 0;
  htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim8) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_ITR3;
  if (HAL_TIM_SlaveConfigSynchro(&htim8, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM8_Init 2 */
  TIM8->DIER |= 0b1000000;
  /* USER CODE END TIM8_Init 2 */
 
}

5 REPLIES 5

> If I put TIM2 into slave trigger mode, I can see and trigger interrupt occur on TIM2, so I assume that the TIM8_TRGO -> TIM2_ITR1 is configured correctly.

Sounds so.

> Capture compare 3 never occurs whether slave trigger mode is enabled or disabled.

Are you sure? Exactly how do you observe it? And what if you try a different channel?

Read out and check the content of TIM2 registers.

JW

Thanks for the reply, JW​.

I am checking by reading the TIM2 registers and nothing is appearing in CCR3, despite the counter running.

I​ also have TIM2 CC3 interrupt enabled (That's how I will be reading it eventually), and it never fires.

I​ enabled CC on channel 2 triggered via TRC, but that also has no effect.

T​hanks

Mttjcksn
Associate III

Argh I thought I had solved this for a minute, but actually I don't think I have.

I added the following line to enable the Capture compare:

TIM2->CCER |= 0b100000000;

 And I suddenly got the CC3 interrupt, but I think it was actually the output compare matching 0 in the CC3 register with the counter value of 0. I think this is the case because it only fired once.

Should I need to enable the channel like this for input capture?

Cheers,

Matt

 > Should I need to enable the channel like this for input capture?

Yes. From the description of the CCER.CENx bit:

CC1 channel configured as input:

This bit determines if a capture of the counter value can actually be done into the input

capture/compare register 1 (TIMx_CCR1) or not.

You can't get a compare event if you have the given channel in CCMR.CCxS set to capture.

JW

Mttjcksn
Associate III

I got this to work by manually enabling the relevant interrupts of timer 2 (There's probably a nice way of using HAL for this..):

TIM2->DIER |= 0b1001000;
 
TIM2->CCER |= 0b100000000;

and starting the capture compare with HAL:

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);

Yay, thanks.