STM32F411CE hardware encoder

Post your cool example code here.
Post Reply
User avatar
Bakisha
Posts: 139
Joined: Fri Dec 20, 2019 6:50 pm
Answers: 5
Contact:

STM32F411CE hardware encoder

Post by Bakisha »

Hello
After having some experiments with encoder on breadboard with STM32F411CE (WeAct board), i am made simple example to use it with timer working in hardware encoder mode. Tested with all combinations of pins that can be used for encoder input. I didn't use any debounce hardware, encoder module have 10k pull-ups. No noticeable jitter, but not accurate at high-speed. Should be enough for some LCD menu or something. Tested also with internal pull-ups, but i found them unreliable.

Code: Select all

// pins must be channel 1 and channel 2 on a timer that support hardware encoder mode
/*
  STM32F411CE:
  +----------+-----------+-----------+
  |          |  CLK      |  DT       |
  +----------+-----------+-----------+
  | TIMER1   |  PA8      |  PA9      |
  +----------+-----------+-----------+
  | TIMER2   |  PA0      |  PA1      |
  |          |  PA5      |  PB3      |
  |          |  PA15     |           |
  +----------+-----------+-----------+
  | TIMER3   |  PA6      |  PA7_ALT1 |
  |          |  PB4      |  PB5      |
  +----------+-----------+-----------+
  | TIMER4   |  PB6      |  PB7      |
  +----------+-----------+-----------+
  | TIMER5   |  PA0_ALT1 |  PA1_ALT1 |
  +----------+-----------+-----------+
*/

#define pinCLK PB4
#define pinDT  PB5

// TIMER9-11 don't support hardware encoder mode

HardwareTimer *MyEncoder ; // encoder connected to ch1/ch2 of TIMx

void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  delay(4000);
  Serial.println("START");

  // pinMode(pinCLK, INPUT_PULLUP);   // internal pull-up
  // pinMode(pinDT , INPUT_PULLUP);   // but unreliable

  // Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished.
  TIM_TypeDef *Instance  = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(pinCLK), PinMap_PWM);
  uint32_t     channel_1 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pinCLK), PinMap_PWM));
  uint32_t     channel_2 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pinDT ), PinMap_PWM));

  MyEncoder = new HardwareTimer(Instance);
  MyEncoder->pause();
  MyEncoder->setOverflow(65536  , TICK_FORMAT);
  MyEncoder->setPrescaleFactor(1);
  MyEncoder->setMode(channel_1, TIMER_INPUT_CAPTURE_FALLING, pinCLK);
  MyEncoder->setMode(channel_2, TIMER_INPUT_CAPTURE_FALLING, pinDT );

  Instance->SMCR |= TIM_ENCODERMODE_TI12;    // set encoder moder (counting both rising and falling edges on both channels) 

  MyEncoder->resume();

  if (Instance == TIM1) {
    Serial.println("Encoder is on TIM1");
  }

  if (Instance == TIM2) {
    Serial.println("Encoder is on TIM2");
  }

  if (Instance == TIM3) {
    Serial.println("Encoder is on TIM3");
  }

  if (Instance == TIM4) {
    Serial.println("Encoder is on TIM4");
  }

  if (Instance == TIM5) {
    Serial.println("Encoder is on TIM5");
  }

  delay(1000);

}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println(int16_t( MyEncoder->getCount() ) / 4);

  delay(random(1000) + 1);

}
Post Reply

Return to “Code snippets”