cancel
Showing results for 
Search instead for 
Did you mean: 

Timer Input capture auto restart

federico.massimi
Associate III

Hi, I'm making a simple firmware to measure the frequency of some clocks, I'm using a timer IC + DMA, like this:

HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, CH1_captures, 2);

Then in the callback I do this:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
		printf("CH1 frequency: %.2f\r\n", capture_to_freq(htim, CH1_captures[0], CH1_captures[1]));
		HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, CH1_captures, 2);
	}
}

The capture_to_freq() function is just a function that calculates the frequency from the capture instants.

I derived the code from some examples taken on the internet, but in none of these the HAL_TIM_IC_Start_DMA() function was called again in the callback. The question is, is it okay to call the HAL_TIM_IC_Start_DMA() function in the callback on every interrupt event or is there a way to configure the timer or DMA to restart automatically?

2 REPLIES 2

Which STM32?

> The question is, is it okay to call the HAL_TIM_IC_Start_DMA() function in the callback on every interrupt event

If such usage is not documented for Cube/HAL in its documentation/sources, you are on your own.

But Timers and DMA are relatively simple and there's little reason not to write proper register-based code for them, where you can simply rely on the description of these modules in RM.

JW

federico.massimi
Associate III

Which STM32?

STM32L476RGT3

Maybe I explained my problem badly, I'll try to be clearer:

I need to measure the frequency of 6 clocks, so I will use 2 timers, 3 inputs for each timer. But let's do the reasoning only for one, the situation is the same for the other as well.

I need the timer to never stop, because otherwise if I restart it on interrupt of one channel, it is also reset for the other channels and nothing works anymore.

I have to go from this:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
		CH1_freq = capture_to_freq(htim, CH1_captures[0], CH1_captures[1]);
		HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, CH1_captures, 2);
	} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
		CH2_freq = capture_to_freq(htim, CH2_captures[0], CH2_captures[1]);
		HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_2, CH2_captures, 2);
	} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) {
		CH3_freq = capture_to_freq(htim, CH3_captures[0], CH3_captures[1]);
		HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_3, CH3_captures, 2);
	}
}

to this:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
		CH1_freq = capture_to_freq(htim, CH1_captures[0], CH1_captures[1]);
	} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
		CH2_freq = capture_to_freq(htim, CH2_captures[0], CH2_captures[1]);
	} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3) {
		CH3_freq = capture_to_freq(htim, CH3_captures[0], CH3_captures[1]);
	}
}

But if I remove the HAL_TIM_IC_Start_DMA() from the callback, everything works only until the first interrupt and stops.

Configuring the timer at the register level wouldn't help me, because my problem is that I don't know which parameter I'm configuring wrong, so even going to RM, I'll do exactly the same configuration I did with the HALs.

PS: this is my timer configuration:

htim1.Instance = TIM1;
  htim1.Init.Prescaler = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;