5

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

但是我无法在attachCallback方法中正确设置我的功能。

当引脚分别变为高电平和低电平时,我想要HCSR04Interrupt::echoHigh()并调用它。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 步骤):

#include "Arduino.h"
#include "HCSR04Interrupt.h"

HCSR04Interrupt::HCSR04Interrupt(int trigger_pin, int echo_pin, void (*callback)()) {
  _trigger_pin = trigger_pin;
  _echo_pin = echo_pin;
  _callback = callback;

  initialize();
}

void HCSR04Interrupt::setUnits(int units) {
  _units = units;
}

void HCSR04Interrupt::initialize() {
  pinMode(_trigger_pin, OUTPUT);
  pinMode(_echo_pin, INPUT);

  digitalWrite(_trigger_pin, LOW);
}

void HCSR04Interrupt::getDistance() {
  //Listen for the RISING interrupt
  attachInterrupt(_echo_pin - 2, echoHigh, RISING);

  //The trigger pin should be pulled high,
  digitalWrite(_trigger_pin, HIGH);

  //for 10 us.
  delayMicroseconds(20);

  //Then reset it.
  digitalWrite(_trigger_pin, LOW);
}

void HCSR04Interrupt::echoHigh() {
  _micros_start = micros();

  detachInterrupt(_echo_pin - 2);
  attachInterrupt(_echo_pin - 2, echoLow, FALLING);
}

void HCSR04Interrupt::echoLow() {
  detachInterrupt(_echo_pin - 2);

  unsigned long us = micros() - _micros_start;

  distance = us;

  (*_callback)();
}
4

4 回答 4

5

所以编译器(而不是 IDE)会告诉你到底出了什么问题:

argument of type 'void (HCSR04Interrupt::)()' does not match 'void (*)()

因此,虽然attachInterrupt()采用 type 的函数指针void (*)(),但您试图向它传递一个非静态成员函数,但您不能这样做。您可以尝试制作成员函数static和强制转换:

static void echoHigh();

// ...

attachInterrupt(_echo_pin - 2, reinterpret_cast<void (*)()>(&echoHigh), RISING);
于 2013-03-27T20:48:39.540 回答
2

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

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

解决方案是将您的echoHigh()echoLow()移出HCSR04Interrupt课堂,并使它们成为简单的功能。

于 2013-03-27T20:47:36.020 回答
1

当我偶然发现这个问题并且它没有被接受的答案时,我写了我发现的东西,这对我有用:

中断必须由全局包装器调用。这个包装器需要调用handleInterupt类的一个函数。因此它必须知道类。这可以通过将其存储在全局变量中来完成。如果应该使用该类的多个实例,则必须使用多个这样的全局变量。但是由于中断引脚只是几个,您可以为每个引脚编写一个全局变量和函数:

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();
}

作为参考,请参阅: http: //forum.arduino.cc/index.php? topic=41713.0 或http://forum.arduino.cc/index.php?topic=160101.0

于 2016-01-17T18:51:12.060 回答
0

我通过创建一个代表整个硬件的单例基类来解决这个问题(无论如何在这种情况下这有点道理)。

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

示例标题(未经测试):

// 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;
}
于 2014-11-30T10:59:53.147 回答