Library 26- Rotary encoder on STM32F4

A rotary encoder, also called a shaft encoder is an electro-mechanical device than converts the angular position or motion of a shaft to an analog or digital. There are 2 types of rotary encoders:

  • Incremental – output indicates just rotation clockwise or counterclockwise
  • Absolute – output indicates current position for encoder

For that purpose I made a one simple library. This library works for incremental rotary encoders. It uses an interrupt to handle rotations. On the rotary encoders inside are basically 2 pushbuttons. And because they are mehanical, you can also expect some debouncing. STM32F4 is a fast device and will handle this debouncing what you don’t want. For that you have to make a good filtering. I made a schematic. how to properly connect rotary encoder to STM32F4 to disable debouncing effect.

Properly connected rotary encoder to STM32F4 device

Properly connected rotary encoder to STM32F4 device



  • Operate with up to 16 rotary encoders at a time.
  • External interrupt based detection, not TIM’s input.
  • Version 2.0 – March 22, 2015
    • Library rewritten to support up to 16 rotary encoders
    • It is not compatible with older versions


    • STM32F4xx
    • STM32F4xx RCC
    • STM32F4xx GPIO
    • STM32F4xx EXTI
    • STM32F4xx SYSCFG
    • MISC
  • TM
    • defines.h
    • TM EXTI
    • TM GPIO

Rotary encoder has 3 pins. pins A, B and C (common). My library uses only A pin to be connected to interrupt, B can be whatever else.

You set your pins when you initialize your custom rotary encoder. And, if you need, you can use up to 16 rotary encoders. This number depends on EXTI feature. It supports 16 interrupt lines at a time, because rotary encoder uses one pin (typically pin A) for interrupt source.




Rotary encoder result

Rotary encoder result

This example uses default settings, PD0 and PD1 are in use.

View project on Github, download library below.

TM STM32F4 Rotary Encoder Library


Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Артем Тихонович

    Do you try to connect encoder to timer inputs and using hardware encoder reading using timer encoder mode? BEst regards.

    • This could also be possible, but It’s not so good idea on any of STM32F401 devices because they have a small amount of timers.
      You are right, it’s better to have hardware, if your MCU has lot of timers 🙂

      • Артем Тихонович

        Big thanks! I planning to make a smart house controller with encoder controlled panel i planing to use stm32f1 or stm32f0 -))

  • Tosh

    Hello, i compile you project and have error. I newbee in this, please help link and run.

    .TargetsSTM32F429_Discoveryproject.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_Init (referred from tm_stm32f4_ili9341.o).

    .TargetsSTM32F429_Discoveryproject.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_SendHalfWord (referred from tm_stm32f4_ili9341.o).

    .TargetsSTM32F429_Discoveryproject.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_Working (referred from tm_stm32f4_ili9341.o).

  • Tosh

    Hello, during the assembly of the project at the stage I got a linking error, please help to understand what could be the reason. I just started training and really helps your website in this, thank you.

    • Recently I’ve updated ILI9341 library which is included in example project. I forgot to add new libs to project.
      You may redownload repository again with corrected project.

      Thanks for reporting.

      • Tosh

        Thanks for so fast reply!

  • alexander della vedova

    how to reset encoder counter when change direction?

  • Christos Bartzis

    Hi! congrats for your great work. I have some questions. I m using STM32F429I -Disco and in my project i m using a HEDS5540 500p/r, incrimental encoder. I used your encoder code and as i can see the ”absolute” is increasing really fast all the time. Does it count the pulses/degrees/rotations? Additionally, the ”diff from last check” shows me a number which is 1/4 of the real rpm.(measured with a rev counter divice in laboratory). Can you think why is this happening?

    • Hi,

      lib counts pulses and absolute is absolute pulses you have in systems.
      Diff from last check works like how many new pulses were detected between 2 TM_RE_Get function calls.

      • Christos Bartzis

        Thanks for your quick reply! You helped me a lot.

  • Simone Grech

    First of all thank you very much for this amazing tutorial.I would like to ask you if it is possible to use this type of encoder with this code and if it is possible to use this method to implement a cascaded control loop for a DC motor application where this encoder code will be used to measure the speed of the motor and then feed it back to the pid controller?thank you

    • If it hasoutput like normal rotary encoder, then yes.

      I would suggest timer for this process instead of interrupt driven lib.

      • Simone Grech

        How can this problem be tackled by timers?Can you explain yourself in more detail thank you very much

        • Easily. Checking datasheet first would give you a clue how to make it work.
          Using timer input capture you can count encoder values.

          • Simone Grech

            thank you very much

  • Emil

    Thanks for the guide (and the whole site), it’s very helpful. I’m not very used to working with C and I don’t really understand the dependencies in the project. Do I need to use more header-files than is discribed on this page? For example main.c wants to include tm_stm32f4_ili9341.h, and some header files include even more header files. How can I know which files are relevant?

    • Required are those which are on Dependencies section described. Easiest for you would be to download my github repository and open project directly from there. It will compile it and you can test it. Later you can start from there to modify for your needs.

      • Emil

        Hey! Never expected such a fast answer, been working on this all day with little result. I’ve downloaded the repository but how can I open it from CoIDE properly, since there is no .coproj file? And will it really compile, I mean the functions above are defined in tm_stm32f4_rotary_encoder.h but that is not included in the github-repo? And if it is, they are never declared anyway?

        • I’m not trying to offsense you now but I think you should learn C little bit more.
          File is included in Github repository under STM32_LIBRARIES folder and there is also .c file with function declarations.

          You can compile project using Keil uVision and not Coocox directly.

          • Emil

            No offense taken. You are right. Thanks a thousand times for your fast replies!

  • Entropy

    Hello, shouldn’t both the TM_RE_t RE1_Data and RE2_Data; been declared “volatile” since they are shared with EXTI Interrupt routine and main() ?

    • Proper way would be but this depends on optimization level.

  • Disc

    Heya, thanks for the guide. I’ve downloaded the software to my Discovery but it is not working optimally. When i rotatate clockwise the Absolute value is increasing really precisely. But when I rotate counter-clockwise nothing happens unless I rotate about half a complete rotation in one go. Do you know why this is? I am using this Rotary Encoder: .

  • Alex

    hello, this is a very good tutorial. I’ve tried it in STM32F429
    Discovery and succeed. later, I tried again using STM32F407 Discovery
    with the same tutorial but to no avail. when using STM32F407 Discovery,
    when I connect it to pin a program does not count. but when the pin is
    not connected, the program count its own. Can you help me?

    • I don’t know where you have connected encoder, but did you check board schematics if you have anything else connected there?

      • Alex

        whether this tutorial can be used for STM32F407xx Discovery?

  • tandel

    Hi need qudrature encoder reading on stm32f1xx series with built in encoder reading hardware but i dont understand that for example my timer is zero at startup and when i rotate it clockwise then it will be lets say 200 count but when i rotate anticlockwise then lets say 4000 count revese but i think couter can count only positive values correct me if i am wrong , so how do all this stuff work ? And stm32f103 has only 16bit counter so how do i get 32bit count ?

    • In anticlockwise, timer will overflow and start on max value of timer, if that is what you are asking.

      Do you really need 32bit? In relative you dont.

      • tandel

        Lets forget 32bit counting for now ,first i want to count 16bit encoder counter as as stm32f1 has buit in 16bit timer for counting, now for example my encoder is connected with motor and when i rotate motor in one direction it should count for example 2000 and othe direction it should be -1000 means first motor rotates 2 revolution and after that 3 revolution 3000 in other direction so 2000 – 3000 = -1000

  • Johan Smit

    Hi Tilen,
    I am surprised that you do not mention that STM32F4 can do encoder inputs directly on TIM2-5. Page 614 of ST RM0090 refers.
    I have used direct encoder inputs on timers in STM32F103, and now is moving to STM32F407. The DMA type encoder inputs of the STM32F103 is a very nice feature, and I will surely use it again on STM32F407.
    Rotary encoders now mostly use electronics, not contacts, and do not need debouncing.
    Thank you for your libraries and tutorials.
    Best Regards
    Johan Smit

    • You can use it, that’s for sure. If you have “bad” contacts, it is harder to use it. If you have electric one, you are safe.

    • abdul rahmat hd

      hi smit, could you send your listing program encoder use stm32f407 discovery plsss?

  • Tmoc

    How can I detect wich side the rotary encoder is going ?
    I tried to use something like:
    uint32_t side;
    side = RE1_Data.Diff;

    Used debug and nothing found on this variable.