cancel
Showing results for 
Search instead for 
Did you mean: 

Capture Control Auto Reload Register Interrupt Flag

GIkar
Associate III

Hello,

i want to measure time between high and low pulse from a ultrasonic sensor. The time is set to 1ms. It works until i reach the end of the time ARR.

To differentitat betwenn a distance like 1cm and 11cm (10cm end of the counter) i have to counte the timer reloads. In CubeMX is checked all the interrupts on but in eigther don't found the right interrupt or i don't activate all interrupts for Capture control timer (TIM1).

Did anyone know how to get the ARR Interrupt of the capture control?

Thanks.

Gendo

9 REPLIES 9
Bob S
Principal

The "update" interrupt is what you need here (TIM_IT_UPDATE if you are using HAL, which I presume you are since you are using CubeMX). Whether this specific interrupt gets enabled by default by the HAL code depends on which TIM_***_Start_***() function you call. It sounds like you are calling HAL_TIM_IC_Start_IT(), correct? You can always manually enable that interrupt using the __HAL_TIM_ENABLE_IT(). Then make sure you have a HAL_TIM_PeriodElapsedCallback() function defined.

GIkar
Associate III

Hello Bob,

year that's wath you do but it doesn't work. Thaht's the problem.

int main()

{

.....

 HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);

 HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);

....

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if(htim->Instance == TIM1 ) // CH1 von Input Capter Compaire abfragen

{

__NOP();

Capture_status=1;

}

}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_1 )

{

CaptureCompaireValue[0]=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);

}

if(htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_2 )

{

CaptureCompaireValue[1]=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);

}

}

GIkar
Associate III

0690X00000AAA48QAH.jpg0690X00000AAA4IQAX.jpg0690X00000AAA43QAH.jpg

You'd never need to ask this question if you'd avoid Cube/CubeMX, and read the RM and program the timer accordingly.

You'd simply set up the timer to run and to perform the input capture, then enable the two interrupts by setting TIMx_DIER.UIE and TIMx_DIER.CCxIW, locate the interrupt vectors - for TIM1 they may be separate, see the Interrupt chapter in RM and/or the startup code - and write the ISRs.

Cube/CubeMX inevitably support only a limited subset of the much wider possibilities, covering the "usual usage cases", so you have to apply kludges to work around its limitations. Bob's expertize in this field is far from being trivial and reaches far beyond mere clicking in CubeMX.

JW

Hello Jan,

good to know. This why i don't found all the things from the ADC Datasheet of the STM32 in CubeMX...

So i have to change the timer pre-settings below by my self?

static void MX_TIM1_Init(void)

{

 /* USER CODE BEGIN TIM1_Init 0 */

 /* USER CODE END TIM1_Init 0 */

 TIM_ClockConfigTypeDef sClockSourceConfig = {0};

 TIM_SlaveConfigTypeDef sSlaveConfig = {0};

 TIM_MasterConfigTypeDef sMasterConfig = {0};

 TIM_IC_InitTypeDef sConfigIC = {0};

 /* USER CODE BEGIN TIM1_Init 1 */

 /* USER CODE END TIM1_Init 1 */

 htim1.Instance = TIM1;

 htim1.Init.Prescaler = 0;

 htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim1.Init.Period = 0xffff;

 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 htim1.Init.RepetitionCounter = 0;

 htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 if (HAL_TIM_Base_Init(&htim1) != HAL_OK)

 {

  Error_Handler();

 }

 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

 if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)

 {

  Error_Handler();

 }

 if (HAL_TIM_IC_Init(&htim1) != HAL_OK)

 {

  Error_Handler();

 }

 sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;

 sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;

 sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_BOTHEDGE;

 sSlaveConfig.TriggerFilter = 0;

 if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

 if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

 sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;

 sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

 sConfigIC.ICFilter = 0;

 if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)

 {

  Error_Handler();

 }

 sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;

 sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

 if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)

 {

  Error_Handler();

 }

 /* USER CODE BEGIN TIM1_Init 2 */

 //__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_UPDATE);

 /* USER CODE END TIM1_Init 2 */

}

GIkar
Associate III

I found the code in the timer interrupt that i want.

 /* TIM Update event */

 if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)

 {

  if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)

  {

   __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);

#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)

   htim->PeriodElapsedCallback(htim);

#else

   HAL_TIM_PeriodElapsedCallback(htim);

#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */

  }

 }

But how can i set the "TIM_FLAG_UPDATE" for TIM1?

TIM1->TIM_FLAG_UPDATE =1;  ?

GIkar
Associate III

This function is what i need but my IDE don't knot it:

void TIM_ITConfig(TIM_TypeDef * TIMx,uint16_t TIM_IT,FunctionalState NewState )

Enables or disables the specified TIM interrupts.

Parameters:

  • TIMx,: where x can be 1 to 14 to select the TIMx peripheral.TIM_IT,: specifies the TIM interrupts sources to be enabled or disabled. This parameter can be any combination of the following values:
  • TIM_IT_Update: TIM update Interrupt source
  • TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  • TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  • TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  • TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  • TIM_IT_COM: TIM Commutation Interrupt source
  • TIM_IT_Trigger: TIM Trigger Interrupt source
  • TIM_IT_Break: TIM Break Interrupt source

int main()
{
.....
 HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
 HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);

No, that will not work (as you discovered). That code is starting the timer in input capture mode, enabling channel 1 interrupt only. The 2nd line attempts to RE-START the timer in input capture mode enabling channel 2 interrupt only. The 2nd call will fail, and if you had checked the return status it would have been HAL_BUSY, not HAL_OK. Lesson #1 - always check the return code from HAL "start" functions!!!!!!!!!!!

You should be able to call HAL_TIM_IC_Start_IT() one time, then use the __HAL_TIM_ENABLE_IT() macro just to enable the channel 2 interrupt. Like this:

int main()
{
  .....
  HAL_StatusTypeDef halsts;
 
  halsts = HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);
  if ( halsts != HAL_OK )  {
    // Report the error here, somehow
    // printf( "Timer init failed, sts %d\n", halsts );
  }
 __HAL_TIM_ENABLE_IT(&htim1, TIM_CHANNEL_2);

ANiko.9
Associate

__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);