2023-03-07 08:28 AM
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?
2023-03-07 10:29 AM
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
2023-03-07 12:34 PM
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;