STM32 Blue Pill 4 rotary encoder Timer pertraukimai

Šiam pavizdyje naudosiu PlatformIO IDE su Arduino (https://github.com/stm32duino/Arduino_Core_STM32) framework bei khoih-prog/TimerInterrupt_Generic@^1.11.0 biblioteka paprastesniam darbui su Timer pertraukimais (interrupts).

Taigi, platformio.ini

[env:bluepill_f103c8]
platform = ststm32
board = bluepill_f103c8
board_build.f_cpu = 72000000L
debug_tool = custom
debug_port = :4242
debug_server = $PLATFORMIO_CORE_DIR/packages/tool-stlink/bin/st-util
debug_init_cmds =
  define pio_reset_halt_target
      monitor reset
      monitor halt
  end
  define pio_reset_run_target
      monitor reset
  end
  target extended-remote $DEBUG_PORT
  $LOAD_CMDS
  pio_reset_halt_target
  $INIT_BREAK

framework = arduino

upload_protocol = stlink
upload_flags = -c set CPUTAPID 0x2ba01477 ; jeigu mes klaidą, pakeisti į 0x1ba01477

Iterpiame bibliotekas:

#include <Arduino.h>
#include "TimerInterrupt_Generic.h"

Naudosime Timer3

STM32Timer ITimer3(TIM3);

Encoderiu padėties nuskaitymo funkcija\

volatile int32_t encoder1Count;
volatile int32_t encoder2Count;
volatile int32_t encoder3Count;
volatile int32_t encoder4Count;

void encoder1_read()
{
// tiesioginė prieiga prie įvesčių. žymiai greitesnis būsenos nuskaitymas.

 // encoder 1
  bool currentStateA = GPIOB->IDR & GPIO_PIN_12; // PB12
  bool cvb = GPIOB->IDR & GPIO_PIN_13;  // PB13

  if (currentStateA != lastStateA)
  {
    if (cvb != currentStateA)
    {
      encoder1Count++;
    }
    else
    {
      encoder1Count--;
    }
    lastStateA = currentStateA;
  }

  // encoder 2
  currentStateA = GPIOB->IDR & GPIO_PIN_14; // PB14
  cvb = GPIOB->IDR & GPIO_PIN_15;  // PB15

  if (currentStateA != lastStateA)
  {
    if (cvb != currentStateA)
    {
      encoder2Count++;
    }
    else
    {
      encoder2Count--;
    }
    lastStateA = currentStateA;
  }
  
  // encoder 3
  currentStateA = GPIOA->IDR & GPIO_PIN_3; // PA3
  cvb = GPIOA->IDR & GPIO_PIN_2;  // PA2

  if (currentStateA != lastStateA)
  {
    if (cvb != currentStateA)
    {
      encoder3Count++;
    }
    else
    {
      encoder3Count--;
    }
    lastStateA = currentStateA;
  }

  // encoder 4
  currentStateA = GPIOA->IDR & GPIO_PIN_1; // PA1
  cvb = GPIOA->IDR & GPIO_PIN_0;  // PA0

  if (currentStateA != lastStateA)
  {
    if (cvb != currentStateA)
    {
      encoder4Count++;
    }
    else
    {
      encoder4Count--;
    }
    lastStateA = currentStateA;
  }
}

void setup funkcijoje, nustatome Timer dažnį i 20kHz

ITimer1.setFrequency(20000, encoder1_read);

ir galiausiai, void loop atspauzdiname enkoderių poziciją

void loop() {

  static int32_t prev1Count = 0;
  static int32_t prev2Count = 0;
  static int32_t prev3Count = 0;
  static int32_t prev4Count = 0;

  if (encoder1Count != prev1Count)
  {
    prev1Count = encoder1Count;
    Serial1.print("Encoder 1 counter: ");
    Serial1.println(count);
  }
  if (encoder2Count != prev2Count)
  {
    prev2Count = encoder2Count;
    Serial1.print("Encoder 2 counter: ");
    Serial1.println(count);
  }
  if (encoder3Count != prev1Count)
  {
    prev1Count = encoder3Count;
    Serial1.print("Encoder 3 counter: ");
    Serial1.println(count);
  }
  if (encoder4Count != prev1Count)
  {
    prev1Count = encoder4Count;
    Serial1.print("Encoder 4 counter: ");
    Serial1.println(count);
  }
}

Skanaus 😉 Ir pabaigai, jeigu encoder pulsai viršys 20kHz greičiausiai atsitiks kaip šiame paveiksliuke. Kelis pulsus priskaičiuos kaip vieną.

arduino programavimas - rotary encoder dropping pulses