2024-08-13 01:39 AM
Good morning everyone,
I'd like some help on this problem.
On a WeAct BlackPill board equipped with STM32F411CEU6 I wrote a fairly simple program using the encoder mode on Timer2 to keep up with count and direction.
I activated the interrupt feature as well since I need to generate some signal base on certain counter value.
My problem is the HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) that is call only half of the time.
I know this by a variable which is incremented every time the funcion is called and compare it the the counter value and is exactly half.
I put a breakpoint on HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) and trace the code and notice that both interrupt flag of each input it's handled and the same CaptureCallback is called.
I know there are other ways to manage quadrature encoder but I thought since the feature it's available on the timer I could use it.
Before changing method I'd like to know if I am doing something wrong.
Thanks
Solved! Go to Solution.
2024-08-13 02:36 AM
This may be an inherent limitation.
The counter in encoder mode counts upon both edges, but the interrupts on both edges are disabled:
One way to work around this could be feeding *externally* the signals also to channels 3 and 4 of the same timer, and setting up the interrupt on both edges.
Of course, using Cube/HAL is usually a hindrance for anything other than what can be simply clicked in CubeMX.
JW
2024-08-13 02:36 AM
This may be an inherent limitation.
The counter in encoder mode counts upon both edges, but the interrupts on both edges are disabled:
One way to work around this could be feeding *externally* the signals also to channels 3 and 4 of the same timer, and setting up the interrupt on both edges.
Of course, using Cube/HAL is usually a hindrance for anything other than what can be simply clicked in CubeMX.
JW
2024-08-13 10:29 AM
Thanks JW,
I suspect it's at hardware level, because....
The interrupt flags are both enable and the the interrupt handler has code for each channel and call the same HAL_TIM_IC_CaptureCallback(htim) function.
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
uint32_t itsource = htim->Instance->DIER;
uint32_t itflag = htim->Instance->SR;
/* Capture compare 1 event */
if ((itflag & (TIM_FLAG_CC1)) == (TIM_FLAG_CC1))
{
if ((itsource & (TIM_IT_CC1)) == (TIM_IT_CC1))
{
{
__HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
/* Input capture event */
if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->IC_CaptureCallback(htim);
#else
HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/* Output compare event */
else
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->OC_DelayElapsedCallback(htim);
htim->PWM_PulseFinishedCallback(htim);
#else
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
}
/* Capture compare 2 event */
if ((itflag & (TIM_FLAG_CC2)) == (TIM_FLAG_CC2))
{
if ((itsource & (TIM_IT_CC2)) == (TIM_IT_CC2))
{
__HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC2);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
/* Input capture event */
if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
{
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->IC_CaptureCallback(htim);
#else
HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
The encoder mode it's very usefull, it manage the counter and direction on its own.
Since the encoders channels are already connected to the timer I'll use the capture feature and handle the counter by code.
Thanks again JW
Carlo