2020-04-21 05:57 AM
Hello!
I want to use a simple rotary encoder with STM32F429.
I programmed the TIM4 timer into 'ENCODERMODE_X4' mode.
Is there a way for me to detect the rotation of the rotary knob by interrupt?
I don't want to do periodically TIMx->CNT sampling if there is more elegant method.
Thanks!
2020-04-21 06:25 AM
We use a external line interrupt configuration(on our STM32F301) on the input pins attached to the encoders pulse outputs.
Here is the setup for one of the two encoders pulse outputs(our encoder input is coming in GPIO_PC14):
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource14);
// Configure EXTI line
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
Once set up and the interrupts are enabled, you will get an EXTI15_10_IRQHandler interrupt on every falling edge of the encoder input as the user turns the encoder.
2020-04-22 12:44 AM
Thanks for the help!
In the meantime, I tried the following:
I enabled CC interrupt on TIM4 Channel1. When an interrupt occurs due to a rising edge on TI1, I read the TIM4-> CNT register in the interrupt handler.
It is working, however I have two concerns with this workaround:
2020-04-22 05:12 AM
I remember we played around a bit before we decided on this solution. Our interrupt is triggered off encoder A and when we get the interrupt we sample the encoder B level. If the encoder B level is high during encoder A interrupt, the encoder is turning one way. If encoder B is low, it is turning the other.
Here is a sloppy example:
void EXTI15_10_IRQHandler(void)
{
volatile uint32_t encoderB;
//encoderA = GPIO_ReadInputDataBit(GPIOC, ENCODER_A);
encoderB = GPIO_ReadInputDataBit(GPIOC, ENCODER_B);
if((EXTI->IMR & EXTI_IMR_MR14) && (EXTI->PR & EXTI_PR_PR14))
{
if (encoderB)
{
tempSetPoint++;
if(tempSetPoint > flashData.setHigh)
tempSetPoint = flashData.setHigh;
}
else
{
tempSetPoint--;
if(tempSetPoint < flashData.setLow)
tempSetPoint = flashData.setLow;
}
encHead++;
encHead &= (NUM_ENCODER_SAMPLES-1);
// Clear the interrupt flag
EXTI->PR = EXTI_PR_PR14;
}
else if(EXTI->PR & EXTI_PR_PR14)
{
// Clear the interrupt flag
EXTI->PR = EXTI_PR_PR14;
}
}
Hope this helps.
2020-04-24 01:52 AM
Thanks a lot!
I was a little busy, but now I managed to deal with the topic a bit.