是的,我知道这方面有很多线索,我想我读过其中的大部分,但要么我不明白答案,要么我无法使它们适应我的“案例”。
请注意,我的背景是电子设计,而不是软件设计,所以对你们中的一些人来说,我的问题似乎很愚蠢,但是.我被卡住了。
我为物联网设计了一个pcb板。它基于一个ESP32模块。我有5个按钮连接到ESP。ESP32 32-以色列国防军对我来说太复杂了,所以我试着采用Ardiuno框架。现在事情开始变得复杂起来。
为了检测和取消按钮,我创建了一个名为Button的C++类。下面可以看到一具骨架。
class Button {
..
..
private:
void memberCallback() {
...
}
public:
Button(const uint8_t gpio ) {
..
attachInterrup(digitalPinToInterrupt(gpio), memberCallback, FALLING);
..
}
..
}我没有找到任何方法来定义"memberCallback“,而不会导致编译错误或根本不工作。
这必须是一个常见的问题,因此,请建议我的解决方案:)
编辑。好像我表达得不够清楚,抱歉。-我知道,如果我使memberCallback是静态的,它至少会编译。问题是,我计划使用这5个实例。静态回调意味着所有实例都将运行相同的代码。5个实例意味着5个不同的中断。我怎么才能认出他们。
发布于 2020-03-12 15:27:50
ESP32 Arduino Core有一个示例说明了如何在
我将在这里引用代码:
#include <Arduino.h>
#include <FunctionalInterrupt.h>
#define BUTTON1 16
#define BUTTON2 17
class Button
{
public:
Button(uint8_t reqPin) : PIN(reqPin){
pinMode(PIN, INPUT_PULLUP);
attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING);
};
~Button() {
detachInterrupt(PIN);
}
void IRAM_ATTR isr() {
numberKeyPresses += 1;
pressed = true;
}
private:
const uint8_t PIN;
volatile uint32_t numberKeyPresses;
volatile bool pressed;
}重要的是:
#include <FunctionalInterrupt.h> -这让您可以使用std::bind()和一个稍微不同的attachInterrupt()声明来完成这项工作。std::bind(&Button::isr,this)将中断处理程序绑定到对象。IRAM_ATTR,以确保其代码将始终加载在内存中。volatile,以便C++编译器知道它们在没有警告的情况下进行更改。std::bind()是一个标准的C++库函数;有网上有关资讯科技的文件。
也就是说,我担心你在你的中断处理程序中打算做什么。
中断处理程序需要运行很短的时间,它们需要非常小心地调用其他函数,并确保数据结构处于不一致的状态。除非在中断处理程序之外锁定中断(应该尽可能少),否则数据结构很容易处于不一致的状态。
Arduino Core中的示例很好--它只是改变了几个变量。不仅如此,调用函数(如Serial.println() )、分配内存或创建对象都是不安全的。
发布于 2020-03-12 09:23:31
当您查看attachInterrupt的文档时,它说ISR是一个不带任何参数的函数。它的类型是void(*)() (或者很可能是extern "C" void(*)(),但我还没有对确切的类型进行足够深入的研究)。您的memberCallback看起来好像不带参数,但实际上并非如此:在非static成员函数中,您得到了一个隐式参数:this,这是指向需要确定使用哪个Button对象的对象的指针。memberCallback的类型是void (Button::*)(),与void(*)()不兼容。这意味着您将无法直接使用非static成员函数。
正如其他答案中所建议的那样,您可以使用static成员函数。然而,这有两个问题:
static成员(函数和变量)。extern“C”‘。要注册的每个Button都需要一个函数。只有一个看起来像这样的Button:
class Button
{
// ....
public:
void memberCallback();
Button(int gpio, Button*& ptr, void(*isr)()) {
ptr = this;
attachInterrupt(digitalPinToInterrupt(gpio), isr, FALLING);
}
};
Button* button1;
extern "C" void button1ISR() {
button1ISR->memberCallback();
}
// create you Button somewhere, e.g.:
int main() {
Button b1(gpio, button1, button1ISR);
// ...
}发布于 2020-03-12 07:04:17
使您的memberCallback函数保持静态。将代码更改为:
class Button {
..
..
private:
static void memberCallback() {
...
}
public:
Button(const uint8_t gpio ) {
..
attachInterrup(digitalPinToInterrupt(gpio), memberCallback, FALLING);
..
}
..
}https://stackoverflow.com/questions/60648871
复制相似问题