Arduino Can';不要在图书馆里使用attachInterrupt

Arduino Can';不要在图书馆里使用attachInterrupt,arduino,static-libraries,interrupt,Arduino,Static Libraries,Interrupt,我正在为超声波距离传感器编写一个简单的库,我想尝试使用中断 但是,我无法在attachCallback方法中正确设置函数 我希望在管脚分别变高和变低时调用HCSR04Interrupt::echohight()和HCSR04Interrupt::echoLow() 我在谷歌上搜索了一下,结果一无所获。Ardiuno IDE说: ./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp: In member function 'void HCSR04Interr

我正在为超声波距离传感器编写一个简单的库,我想尝试使用中断

但是,我无法在
attachCallback
方法中正确设置函数

我希望在管脚分别变高和变低时调用
HCSR04Interrupt::echohight()
HCSR04Interrupt::echoLow()

我在谷歌上搜索了一下,结果一无所获。Ardiuno IDE说:

./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp: In member function 'void HCSR04Interrupt::getDistance()':
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp:31: error: argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()'
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp: In member function 'void HCSR04Interrupt::echoHigh()':
./Arduino/libraries/HCSR04/HCSR04Interrupt.cpp:47: error: argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()'
这是我的标题:

#ifndef _HCSR04Interrupt_
#define _HCSR04Interrupt_

#include "Arduino.h"

#define HCSR04_CM_FACTOR 58.0
#define HCSR04_IN_FACTOR 148.0
#define HCSR04_CM_MODE 0
#define HCSR04_IN_MODE 1

class HCSR04Interrupt {
  public:
    double distance;

    HCSR04Interrupt(int trigger_pin, int echo_pin, void (*callback)());

    void setUnits(int units);

    void getDistance();
  private:
    int _trigger_pin;
    int _echo_pin;
    int _units;
    unsigned long _micros_start;
    void (*_callback)();

    void initialize();
    void echoHigh();
    void echoLow();
};

#endif
以及我的实现(由于无法通过attachInterrupt步骤,因此未完成):


Arduino中断处理程序只能是函数。您正在尝试使对象的方法成为中断处理程序。因此编译器会抱怨

更确切地说,对象方法类似于函数,但它们好像接受了一个“隐藏”参数,该参数指定了对象实例。因此,它们实际上具有与普通函数不同的类型签名。当函数正在寻找的是普通函数指针时,这不允许传递方法指针


解决方案是将
echoHigh()
echoLow()
移出
HCSR04Interrupt
类,使它们成为普通函数。

因此编译器(而非IDE)会准确地告诉您出了什么问题:

argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()
因此,虽然
attachInterrupt()
接受类型为
void(*)(
)的函数指针,但您试图向其传递一个非静态成员函数,,而您不能。您可以尝试使成员函数
为静态
并强制转换:

static void echoHigh();

// ...

attachInterrupt(_echo_pin - 2, reinterpret_cast<void (*)()>(&echoHigh), RISING);
static void echohight();
// ...
连接中断(_echo_pin-2,重新解释投射(&echohight),上升);

我通过创建一个基类来解决这个问题,该基类表示整个硬件(在这种情况下,这是有意义的)

然后,任何函数指针都可以传递给子组件类,并由singleton处理,singleton的成员变量和方法都是静态的

示例标题(未测试):


当我偶然发现这个问题,但还没有一个公认的答案时,我写下了我的发现,这对我很有用:

中断必须由全局包装器调用。此包装器需要调用类的
handleinterup
函数。因此,它必须了解类。这可以通过将其存储在全局变量中来实现。如果应该使用类的多个实例,则必须使用多个这样的全局变量。但由于中断管脚数量很少,因此您可以为每个管脚编写一个全局变量和函数:

MyClass theInstance_pin3 = NULL;
MyClass theInstance_pin7 = NULL;

// Somewhere, fill in an initialized copy of MyClass,
// and set theInstance_pin3 or theInstance_pin7 to it

void ISR_3()
{
   if (theInstance_pin3)
       theInstance_pin3->handleInterrupt();
}
void ISR_7()
{
   if (theInstance_pin7)
       theInstance_pin7->handleInterrupt();
}
作为参考,请参见:

attachInterrupt要求其指向的功能是静态的。这会导致attachInterrupt中向上的所有成员函数都是静态的。我成功地做到了这一点。
// Sub-component
class LampButton {
public:
    LampButton(int pin, void(*pushHandler)());
}

// Sub-component
class LampLed {
public:
    LampLed(int pin);
    void toggle();
}

// Singleton represents the hardware in it's entirety
class Lamp {
public:
    // Call this instead of a constructor
    static void initialize(int buttonPin, int ledPin);

    // Function implemented inline for clarity - don't do this
    static void handleButtonPush() {
        led.toggle();
    }

private:
    static LampButton button;
    static LampLed led;
}
MyClass theInstance_pin3 = NULL;
MyClass theInstance_pin7 = NULL;

// Somewhere, fill in an initialized copy of MyClass,
// and set theInstance_pin3 or theInstance_pin7 to it

void ISR_3()
{
   if (theInstance_pin3)
       theInstance_pin3->handleInterrupt();
}
void ISR_7()
{
   if (theInstance_pin7)
       theInstance_pin7->handleInterrupt();
}