cancel
Showing results for 
Search instead for 
Did you mean: 

HAL TIM IC Capturecallback on multiple functions

Giordano
Associate II
Hello,
I'm beginner in STM32 and would need help with HAL callback function usage.
When I've started to use STM32s after PICs, one of the reasons why I was happy that the timer module encoder receiver function works really well, robust. I did used other interrupts, but somehow I have not used other timer interrupts ... until now. And now I'm stuck.
I try to use an STM32G474 with an I2C oled on, encoder on timer 4, some spi peripherials and want to measure frequency on timer 5. My problem is, with HAL, how can I separate the two actions? Both encoder and time measurement calls the HAL_TIM_IC_CaptureCallback. Both works fine ... as long as there is no interrupt coming in from the other. At the moment the function looks like what I copy below. Can you please help how to separate the 2 actions, how to refer in in(**) to one or the other or any other, but with using HAL.
Thanks!!
JG

 

 

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// If the Interrupt is triggered by 1st Channel
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
RPM_captured = 1;
}

if (RPM_captured)
{

indx_RPM = 0;
count_RPM = 0;
RPM_measure_average = 0;

/* increment the index until some useful data shows up */
while (RPM_data[indx_RPM] == 0) indx_RPM++;

/* Again at very high frequencies, sometimes the values don't change
* So we will wait for the update among the values
*/
while ((MIN((RPM_data[indx_RPM+1]-RPM_data[indx_RPM]), (RPM_data[indx_RPM+2]-RPM_data[indx_RPM+1]))) == 0) indx_RPM++;

/* RPM_measure_average is the difference in the 2 consecutive rise Time */

/* Assign a start value to RPM_measure_average */
RPM_measure_average += MIN((RPM_data[indx_RPM+1]-RPM_data[indx_RPM]), (RPM_data[indx_RPM+2]-RPM_data[indx_RPM+1]));
indx_RPM++;
count_RPM++;

/* start adding the values to the RPM_measure_average */
while (indx_RPM < (SamplesBlockSize))
{
RPM_measure_average += MIN((RPM_data[indx_RPM+1]-RPM_data[indx_RPM]), RPM_measure_average/count_RPM);
count_RPM++;
indx_RPM++;
}

/* Find the average RPM_measure_average, the average time between 2 RISE */
RPM_measure_average = RPM_measure_average/count_RPM;

indx_RPM = 0;

//motor_RPM = 60/((float)RPM_measure_average * 0.00000001);
motor_RPM = 60/(RPM_measure_average * 0.00000001);
platter_RPM = motor_RPM / belt_ratio;
RPM_captured = 0;
RPM_measured = 1;
}

1 ACCEPTED SOLUTION

Accepted Solutions
Saket_Om
ST Employee

Hello @Giordano 

To handle multiple timer interrupts separately using the HAL library in STM32, you have two main options. The first option is to use a single callback function and differentiate the interrupts by checking the timer instance and the active channel within the HAL_TIM_IC_CaptureCallback function (as mentioned by @Tesla DeLorean). The second option is to register separate user-defined callback functions for each timer using the HAL_TIM_RegisterCallback function.

For the first option, you can check htim->Instance and htim->Channel to identify which timer and channel triggered the interrupt.

For the second option, define your custom callback functions and register them for each timer after initializing the timers. Both methods ensure that you can handle interrupts from multiple timers effectively. Here is an example of both approaches:

Single Callback Function with Instance Check:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM4) {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
            // Handle TIM4 Channel 1 interrupt
        }
    } else if (htim->Instance == TIM5) {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
            // Handle TIM5 Channel 1 interrupt
        }
    }
}

Registered Callbacks for Each Timer:

void User_TIM4_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
        // Handle TIM4 Channel 1 interrupt
    }
}

void User_TIM5_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
        // Handle TIM5 Channel 1 interrupt
    }
}

void Register_Callbacks(void) {
    HAL_TIM_RegisterCallback(&htim4, HAL_TIM_IC_CAPTURE_CB_ID, User_TIM4_IC_CaptureCallback);
    HAL_TIM_RegisterCallback(&htim5, HAL_TIM_IC_CAPTURE_CB_ID, User_TIM5_IC_CaptureCallback);
}


int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM4_Init();
    MX_TIM5_Init();

    Register_Callbacks();

    while (1) {
        // Main loop
    }
}
If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

View solution in original post

3 REPLIES 3

Differentiate which TIM instance is being handled, perhaps move the globals into the instance 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Saket_Om
ST Employee

Hello @Giordano 

To handle multiple timer interrupts separately using the HAL library in STM32, you have two main options. The first option is to use a single callback function and differentiate the interrupts by checking the timer instance and the active channel within the HAL_TIM_IC_CaptureCallback function (as mentioned by @Tesla DeLorean). The second option is to register separate user-defined callback functions for each timer using the HAL_TIM_RegisterCallback function.

For the first option, you can check htim->Instance and htim->Channel to identify which timer and channel triggered the interrupt.

For the second option, define your custom callback functions and register them for each timer after initializing the timers. Both methods ensure that you can handle interrupts from multiple timers effectively. Here is an example of both approaches:

Single Callback Function with Instance Check:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM4) {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
            // Handle TIM4 Channel 1 interrupt
        }
    } else if (htim->Instance == TIM5) {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
            // Handle TIM5 Channel 1 interrupt
        }
    }
}

Registered Callbacks for Each Timer:

void User_TIM4_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
        // Handle TIM4 Channel 1 interrupt
    }
}

void User_TIM5_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
        // Handle TIM5 Channel 1 interrupt
    }
}

void Register_Callbacks(void) {
    HAL_TIM_RegisterCallback(&htim4, HAL_TIM_IC_CAPTURE_CB_ID, User_TIM4_IC_CaptureCallback);
    HAL_TIM_RegisterCallback(&htim5, HAL_TIM_IC_CAPTURE_CB_ID, User_TIM5_IC_CaptureCallback);
}


int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM4_Init();
    MX_TIM5_Init();

    Register_Callbacks();

    while (1) {
        // Main loop
    }
}
If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

Yesss!

Thank You. I was thinking the same, but used wrong syntax. Also tried with others suggestion on this syntax ... if (htim==&htim4) ..., but did not work. This "Instance" is new to me, I look after now. It works, but I also want to understand why.

I appreciate your help you gave!!

JG