Many (although not all) of the STM32 timers have an Encoder Mode option in the Slave-mode Controller. When set, the timer's counter counts according to edges on CH1 and CH21 up and down, changing direction (as indicated by the TIMx_CR1.DIR bit) according to the order of edges, so that it allows connecting a quadrature encoder.
There are essentially two modes available2. In one, edges of only one channel contribute to counting - this mode is often called "x2", as there are two counts per the quadrature cycle. In the other mode, edges of both channels are counted, this is "x4" mode.
Sometimes, users wish to use the "x1" mode (or would like to have counted even less edges, for whatever reason), where only one edge is counted per quadrature cycle (e.g. only upgoing in one direction of movement and only downgoing in the other direction, only on one channel). This is often required for encoders used in manually turned "knobs" with detents, as their mechanism usually generates one full quadrature cycle per detent. It appears, that using prescaler (set to 1, i.e. dividing by 2) would solve the problem.
However, after setting prescaler3 to nonzero, the counter starts to behave strangely. While the encoder is turned/moved only to one direction, it works quite OK, but as soon as direction changes, counts may start to be missing, or behave "strange" and "unpredictible".
The root of the problem is in the fact, that the prescaler counter counts only in one direction. While the Encored-mode logic decodes the order of edges and changes the TIMx_CR1.DIR bit accordingly, this applies only to the "main" counter (CNT), but not the prescaler counter. The following diagram illustrates this effect for TIMx_SMCR.SMS=0b001 (Encoder mode 1 - Counter counts up/down on TI1FP1 edge depending on TI2FP2 level) - counter increments/decrements according to indicated direction, when prescaler counter transitions from 1 (= value set in TIMx_PSC) to 0:
_____________________ CH2 _________________________..._| ___ ___ ___...___ ___ ___ CH1 _____| |___| |___| |___| |___| |___ UP/DOWN U D U D U U D U D U PRESC 0 1_ 0 1_ 0 1_ 0 1_ 0 1 \_+ \_+ \_- \_- CNT 5 5 6 6 7 7 6 6 5 5
Note, that at the beginning the encoder was moving only one edge up and down, yet it produced an ever increasing value in CNT; and after moving one more edge in the middle of the diagram, again moving up and down produces an ever decreasing value.
There is only one remedy to this problem: if "x1" or other "divided" mode is desired, prescaler can't be used, rather, the resulting count has to be post-processed (divided) after reading it out from TIMx_CNT, in software.