I'm using STWINKT1 board connected to encoder to timer 3. I want to get a interrupt every time that the encoder count is 300, so the code in the interrupt is:

void  TIM3_IRQHandler(void){
    // do things here

    //reset the encoder so ill start counting again
    __HAL_TIM_SET_COUNTER(&encoderTimer, 0);
    //clear the interrupt

But no matter how I define the encoder I get an interrupt each pulse- this is useless and consumes CPU without any reason. This is how I define the encoder & start it:

void Init_Encoder_TIM(void){
    TIM_Encoder_InitTypeDef Config = {0};
    TIM_MasterConfigTypeDef MasterConfig = {0};

    //define the encoder clock
    encoderTimer.Instance = TIM_ENCODER;
    encoderTimer.Init.Prescaler = 0;
    encoderTimer.Init.CounterMode = TIM_COUNTERMODE_UP;
    encoderTimer.Init.Period = 0xFFFF;
    encoderTimer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    encoderTimer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    Config.EncoderMode = TIM_ENCODERMODE_TI1;
    Config.IC1Polarity = TIM_ICPOLARITY_RISING;
    Config.IC1Prescaler = TIM_ICPSC_DIV1;
    Config.IC1Filter = 0;
    Config.IC2Polarity = TIM_ICPOLARITY_RISING;
    Config.IC2Prescaler = TIM_ICPSC_DIV1;
    Config.IC2Filter = 0;
    if (HAL_TIM_Encoder_Init(&encoderTimer, &Config) != HAL_OK)
    MasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    MasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&encoderTimer, &MasterConfig) != HAL_OK)
    HAL_TIM_Encoder_Start_IT(&encoderTimer, TIM_CHANNEL_ALL);

I tried to set the prescaler to 300 but it didn't work. I tried to set the period to 300 but it didn't work either. I tried to set the CCR3 manually to 300 and activate the interrupt channel and it didn't work as well.

To be clear: The interrupt works, I get interrupt but for each encoder pulse instead of every 300 pulses.

Hope you will know how to help me Itay


1 Answer 1


First things first.

Does your timer actually keep track of your encoder pulses properly without the interrupt? For example, if you get it to just constantly spit out the encoder count over a terminal, does it make sense as you slowly rotate the encoder back and forth and all around? There's zero point worrying about the interrupt if you have not verified that the configuration that allows the timer to properly track the encoder works.

I bring this up because from the way you are talking about the setting the timer period to get the interrupt to fire it sounds like you have not bothered setting up the timer to count the encoder separately from the encoder count interrupt.

If you already had your basic encoder counting configuration setup then you would know that you are supposed to set the period as a full revolution of the encoder, along with a GPIO with an interrupt as the index pulse to reset the count (unless your specific STM32 supports a dedicated indexing signal for the timer). You would also not have tried to blindly adjust the period or prescaler hoping your interrupt would start working because you would know that would break what you already had working.

There's only place left to put in an count value for the interrupt and that is the capture compare register. If your timer was already counting your encoder properly then it is extremely straightfoward to set up an interrupt to trigger at a count: You just write the value to the capture compare register and enable the interrupt flag.

If 300 is the full revolution of your encoder (and you never did say if this was the case or not) then there are additional ways you can trigger an interrupt. If this is the case, then you can also directly use use the timer's update interrupt which triggers whenever the timer rollsover and wrapsaround, or just use the interrupt that triggers off the index signal.

  • \$\begingroup\$ i verified that the count is correct and i get the pulse counts correctly (both forward and backward), 300 is not full revolution, its just a point in the movement, as I use the encoder as distance measure, i tried setting CCR3 to 300 and using HAL to enable the interrupt but for some reason the interrupt didnt fire no matter what ( and i moved the encoder more then enough) \$\endgroup\$
    – Finci
    Commented Dec 13, 2020 at 11:07
  • \$\begingroup\$ Hmmmm. I think the HAL might be doing something unexpected then. When I worked with it directly using registers that is all I had to do, if I recall. I do not see any other steps in the code I wrote a while ago. \$\endgroup\$
    – DKNguyen
    Commented Dec 13, 2020 at 18:14
  • \$\begingroup\$ By the way, I used a /1 for both the timer prescaler and the capture/compare prescaler. I never managed to get sensible results with any other prescale values. You may also need to trigger an update event to load the prescaler value into the shadow register. \$\endgroup\$
    – DKNguyen
    Commented Dec 13, 2020 at 19:37
  • \$\begingroup\$ I can only set the prescaler to 1,2,4,8 in mine. Not an arbitrary integer like 300. Can your STM32 actually do that? \$\endgroup\$
    – DKNguyen
    Commented Dec 13, 2020 at 19:53
  • \$\begingroup\$ i think stm32 can do it, ill try to set the registers directly and activate the interrupt directly without hal, may be then it will work correctly \$\endgroup\$
    – Finci
    Commented Dec 14, 2020 at 6:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.