首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过传递类方法使用Wire.onRequest?

通过传递类方法使用Wire.onRequest?
EN

Stack Overflow用户
提问于 2019-02-16 10:05:33
回答 1查看 923关注 0票数 0

我有一个Arduino草图,将致力于一个Arduino UNO,我正试图让uno通过i2c连接与覆盆子圆周率。问题是使用wire.h库,当我这样使用它时,方法Wire.onRequest工作得很好。

代码语言:javascript
复制
#include <Wire.h>
#define COMM_DELAY 50
#define SLAVE_ADDRESS 0x04

int current_rule = 0;

void initI2c() {
  // initialize i2c as slave
  Wire.begin(SLAVE_ADDRESS);

  // define callbacks for i2c communication
  Wire.onReceive(receiveData);
}

// callback for received data
void receiveData(int byteCount) {
  while (Wire.available()) {
    current_rule = Wire.read();
  }
}

但是,当我试图用类方法得到这个精确的结果时,我会得到一个错误:invalid use of non-static member function ( Wire.onRequest(this->receiveData)行将被标记为红色)。

就像这样:

代码语言:javascript
复制
void (*funptr)();
typedef void (*Callback)(byte);
class Comm{
public:
  int callback_list_size = 0;
  bool option_debug;
  byte option_address;
  int option_comm_delay;
  void(*callback_list[256]);
  byte *rules;

  // function for receiving data. raspberry -> arduino
  // Whenever the master sends new data, this method will call the appropriate callback.
  void receiveData()
  {
    byte data;
    Serial.println("[INFO] Received new data from master");
    while (Wire.available())
    {
      data = Wire.read();
    }
    for (int i = 0; i < callback_list_size; i++)
    {
      if (rules[i] == data){
        funptr = callback_list[i];
        funptr();
        }
    }
  }

  // function for sending data. Called when raspberry request data. arduino -> raspberry
  // Whenever the master requests data, this method will be called. For now we don't need this but anyway.
  void sendData(int s)
  {
    if (option_debug)
      Serial.println("[INFO] Master requests data!");
  }

  /* Constructor that takes 3 parameters at max. Only the adress is mandatory others are optional and will be filled with default values
     :address - adress of slave(arduino) - Example 0x04
     :delay - a delay is needed because I2C clock is quite slow compared to the CPU clock - 50
     :debug - for debug purposes if true debug info will be sent to Serial interface - true/false 
  */
  Comm(byte address, int delay = 50, bool debug = false)
  {
    option_address = address;
    option_comm_delay = delay;
    option_debug = debug;
    if (debug)
      Serial.println("[INFO] Comm Object Created!");
  }

  // Function needs to be called to initialize the communication channel.
  void initI2c()
  {
    Wire.begin(option_address);
    Wire.onReceive(this->sendData);
    Wire.onRequest(this->receiveData);
    if (option_debug)
      Serial.println("[INFO] I2C channel initialized");
  }

  // Function to add new callback for a rule.
  // This function returns id of passed callback
  int addCallback(Callback func, byte rule)
  {
    callback_list_size++;
    // Enlarge rules array to keep 1 more byte
    byte *temp = new byte[callback_list_size];       // create new bigger array.
    for (int i = 0; i + 1 < callback_list_size; i++) // reason fo i+1 is if callback_list_size is 1 than this is the first initializition so we don't need any copying.
    {
      temp[i] = rules[i]; // copy rules to newer array.
    }
    delete[] rules; // free old array memory.
    rules = temp;   // now rules points to new array.
    callback_list[callback_list_size - 1] = &func;
    rules[callback_list_size - 1] = rule;
    return callback_list_size;
  }
};

Comm *i2c_comm;
void loop()
{
}
void setup()
{
  Serial.begin(9600);
  initI2C();
}


void initI2C()
{
  i2c_comm = new Comm(0x04, 50, true);
  i2c_comm->initI2c();

  //Callback Definitions
  i2c_comm->addCallback(&rule_1, 0x01);
      i2c_comm->addCallback(&rule_2, 0x02);
          i2c_comm->addCallback(&rule_3, 0x03);
              i2c_comm->addCallback(&rule_4, 0x04);
}

我还试图使receiveData方法成为静态的。但在这种情况下,我遇到了如下错误:invalid use of member Com::callback_list_size in static member function

这对我来说是有意义的,因为静态方法不知道我说的是哪个callback_list_size。

所以我对如何处理这样的问题感到很困惑?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-16 12:55:40

你快到了。一般来说,在C++中,您需要为回调函数传递一个静态类方法。

当您试图访问Comm类实例的一个成员时,您在将方法更改为静态之后收到的错误是预期的,在没有“this”的静态方法中不能这样做。

这里有许多需要考虑的技术之一,但请阅读SO post Using a C++ class member function as a C callback function

无论如何,这里的方法是利用指向实例的静态指针。

代码语言:javascript
复制
class Comm {
private:
    static Comm* pSingletonInstance;

    static void OnReceiveHandler() {
        if (pSingletonInstance)
            pSingletonInstance->receiveData();
    }
    static void OnSendHandler(int s) {
        if (pSingletonInstance)
            pSingletonInstance->sendData(s);
    }
    void initI2c() {
        Comm::pSingletonInstance = this; // Assign the static singleton used in the static handlers.
        Wire.onReceive(Comm::OnSendHandler);
        Wire.onRequest(Comm::OnReceiveHandler);
        Wire.begin(option_address);
    }
}
// static initializer for the static member.
Comm* Comm::pSingletonInstance = 0;

同样,有很多方法可以绕过这个问题,但上面是一个简单的方法,很可能适合您的项目。如果需要管理Comm的多个实例,则必须执行完全不同的操作。

祝好运!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54721928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档