Прерывания внутри класса, связанные с функцией класса

Здравствуйте, у меня есть класс, и я хотел бы прикрепить прерывание внутри класса и прикрепить его к функции класса.

class counter{
  public:

  counter(int pin){
    Ipin=pin;
  }
  void startCounting(){
    attachInterrupt(digitalPinToInterrupt(Ipin),this.addCount,CHANGE);
  }
  void stopCounting(){
    detachInterrupt(digitalPinToInterrupt(Ipin));
  }

  void addCount(){
    count++;
  }

  private:
  int Ipin;
  unsigned long count= 0;
};

Кое-что из приведенного выше кода. Может быть несколько инициализаций этого класса. надеюсь, в зависимости от того, какой вывод использует пользователь.

Есть способ обойти это, когда прикрепление контакта выполняется в цикле или настройке и просто вызывается общедоступная функция класса. Но для меня это не соответствует духу классов, как правильно сделанная библиотека.

Я не очень хорошо разбираюсь в программировании, если бы вы могли научить меня, как это было бы очень признательно.

, 👍0

Обсуждение

I не поддерживается attachInterrupt. Вам нужна функция, которая вызывает нужный метод., @KIIV

@KIIV, как это делают библиотеки с прерываниями?, @Jack

Используя некоторую функцию, которая вызывает метод для определенного объекта. В любом случае вы не можете использовать больше обратных вызовов для одного и того же источника прерывания., @KIIV

Итак, если мы исходим из того, что вы сказали, и, скажем, я должен был создать библиотеку. У меня было бы 2 функции, которые не принадлежат ни к какому классу в .h или .cpp, первая функция прикрепляет прерывание ко второй функции, а вторая функция вызывает метод класса ?? Можно ли вызвать глобальную функцию внутри класса?, @Jack


1 ответ


Лучший ответ:

3

У меня есть сообщение об этой проблеме.

В основном вы не можете присоединить функцию класса с помощью attachInterrupt из-за скрытого указателя "this", который необходимо передать (нестатической) функции класса, где "this" — это конкретный экземпляр класса. Вы можете обойти это следующим образом:

class myClass
  {
  static volatile bool switchChanged;  // объявляем

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);
    }  // конец myClass::begin

  static void switchPressed ()
    {
    switchChanged = true;
    }  // конец myClass::switchPressed

  };  // конец класса myClass

volatile bool myClass::switchChanged;  // определять

myClass foo;  // создаем экземпляр myClass

void setup ()
  {
  foo.begin ();
  }  // конец настройки

void loop ()
  {
  // что бы ни
  }  // конец цикла

Но это не очень хорошо, потому что, как вы заметили, вы действительно понижаете класс до использования статического логического значения.


Еще один способ сделать это — написать "склеивающие" подпрограммы, например:

class myClass
  {
  volatile bool switchChanged;

  static myClass * instances [2];

  static void switchPressedExt0 ()
    {
    if (myClass::instances [0] != NULL)
      myClass::instances [0]->switchPressed ();
    }  // конец myClass::switchPressedExt0

  static void switchPressedExt1 ()
    {
    if (myClass::instances [1] != NULL)
      myClass::instances [1]->switchPressed ();
    }  // конец myClass::switchPressedExt1


  public:

  void begin (const byte whichPin)
    {
    pinMode (whichPin, INPUT_PULLUP);
    switch (whichPin)
      {
      case 2: 
        attachInterrupt (0, switchPressedExt0, CHANGE);
        instances [0] = this;
        break;

      case 3: 
        attachInterrupt (1, switchPressedExt1, CHANGE);
        instances [1] = this;
        break;

      } // конец переключателя
    }  // конец myClass::begin

  void switchPressed ()
    {
    switchChanged = true; 
    }

  };  // конец класса myClass

myClass * myClass::instances [2] = { NULL, NULL };

// экземпляры нашего класса
myClass foo; 
myClass bar;

void setup ()
  {
  foo.begin (2);   // контакт D2
  bar.begin (3);   // контакт D3
  }  // конец настройки

void loop ()
  {
  // что бы ни
  }  // конец цикла

Это все еще не лучшее решение, но оно может дать вам некоторые идеи.


Ваша основная проблема заключается в том, что классы по своей природе могут создаваться много раз, однако у вас есть только небольшое фиксированное количество прерываний на микропроцессоре.

,

Спасибо за отличную ссылку, решение «клея» сработало бы для меня, потому что я использую специально построенную плату и есть фиксированное количество контактов, которые нужно прерывать. Я просто хочу избавить пользователя от хлопот при использовании библиотеки, когда в моем основном классе вызывается start, все прерывания должны быть готовы к работе. По крайней мере, мне не придется выполнять функцию на всех контактах прерывания (60+ контактов = 60+ функций в ближайшее время). Еще раз спасибо за ответ., @Jack

Я могу понять, что это вызовет проблемы, когда количество экземпляров превысит количество прерываний процессора. Хотя это можно исправить, добавив макросы защиты, которые выдают ошибку, если количество экземпляров превышает количество прерываний, но это будет много макросов для каждой платы, которую вы хотите, чтобы ваш класс работал., @Jack