-1

问题

我开始玩 Arduino IoT (ESP32)。我从 SD 卡上的文件中读取了 GPIO 配置。我有外部中断的问题。我需要计算给定 GPIO 上的中断数。

我写了一个存储GPIO配置的类,并将这个类的对象放在一个全局数组中。如何计算给定引脚上的中断,以便通过使用适当的对象方法获得结果?

我尝试了不同的解决方案,但问题在于 ISR 方法,它必须是静态的。此方法无法访问对象字段,因此我不知道在哪里以及如何增加中断计数器。

我把代码分成几个文件。我只附上解决这个问题所必需的。

这支撑了我的项目。请帮忙。

主文件:

#define GPIO_CONFIG_FILE "cfg/gpio.txt"
#define WIFI_AP_CONFIG_FILE "cfg/ap.txt"
#define WIFI_STA_CONFIG_FILE "cfg/sta.txt"
#define AVAILABLE_GPIO_CNT 7
#define LED_BUILTIN_OLIMEX 33
#define BTN_BUILTIN_OLIMEX 34

#include "FS.h"
#include "SD_MMC.h"
#include "GPIO_CONFIG.h"

GPIO_CONFIG gpio[AVAILABLE_GPIO_CNT];
uint32_t gpio_int_cnt[AVAILABLE_GPIO_CNT] = {0};

void setup() {
  if (checkSdCard()) {
    setUpPinsFromFile(GPIO_CONFIG_FILE);
  }
}

void loop() {
}

GPIO_CONFIG.h

#ifndef GPIO_CONFIG_h
#define GPIO_CONFIG_h

#include "Arduino.h"
#define ID_LENGTH 7

class GPIO_CONFIG {
  public:
    GPIO_CONFIG();
    void setUp(const char * key);
    void printConfig();
    uint8_t number();
    uint8_t mode();
    uint16_t multiplier();
    bool inversion();
    char * id();
    static void isr();
    static uint32_t int_cnt();

  private:
    uint8_t gp_number;
    uint8_t gp_mode;
    uint16_t gp_multiplier;
    uint32_t gp_init_value;
    bool gp_inversion;
    char gp_id[ID_LENGTH];
    //    const uint8_t gp_mode_array[4] = {INPUT, OUTPUT, INPUT_PULLUP};
};
#endif

GPIO_CONFIG.cpp

#include "GPIO_CONFIG.h"
GPIO_CONFIG::GPIO_CONFIG() {
  gp_number = 0;
  gp_multiplier = 1;
  gp_inversion = false;
  gp_init_value = 0;
}

void GPIO_CONFIG::setUp(const char * key) {
  //nr|id|name|mode|multi|inv|init
  char cfg[sizeof(key)];
  for (uint8_t b = 0; b < sizeof(key); ++b) {
    cfg[b] = key[b];
  }

  //PIN_NUMBER
  char * tok = strtok(cfg, "|");
  gp_number = atoi(tok);

  //ID
  tok = strtok(NULL, "|");
  for (int b = 0; b < sizeof(tok); b++) {
    if (b < ID_LENGTH) {
      gp_id[b] = tok[b];
    } else {
      break;
    }
  }
  gp_id[ID_LENGTH - 1] = '\0';

  //NAME
  strtok(NULL, "|");

  //MODE
  tok = strtok(NULL, "|");
  gp_mode = atoi(tok);

  //MULTIPLIER
  tok = strtok(NULL, "|");
  gp_multiplier = atoi(tok);

  //INVERSION
  tok = strtok(NULL, "|");
  gp_inversion = (atoi(tok) > 0);

  //INITIAL VALUE
  tok = strtok(NULL, "|");
  gp_init_value = atoi(tok);

  //0-in; 1-out; 2-int
  if (gp_mode != 1) {
    if (gp_inversion) { //sterowanie podstawowe przez vcc
      pinMode(gp_number, INPUT_PULLUP);
    } else {
      pinMode(gp_number, INPUT);
    }
    if (gp_mode > 2) {
      attachInterrupt(digitalPinToInterrupt(gp_number), isr, FALLING);
    }
  } else {
    pinMode(gp_number, OUTPUT);
  }
}

void GPIO_CONFIG::printConfig() {
#ifdef DEBUG
  Serial.print("GPIO_CONFIG:");
  Serial.print(" -no:");
  Serial.print(gp_number);
  Serial.print(" -id:");
  Serial.print(gp_id);
  Serial.print(" -mode:");
  Serial.print(gp_mode);
  Serial.print(" -multi:");
  Serial.print(gp_multiplier);
  Serial.print(" -inv:");
  Serial.print(gp_inversion);
  Serial.println("");
#endif
}

uint8_t GPIO_CONFIG::number() {
  return gp_number;
}

uint8_t GPIO_CONFIG::mode() {
  return gp_mode;
}

uint16_t GPIO_CONFIG::multiplier() {
  return gp_multiplier;
}

bool GPIO_CONFIG::inversion() {
  return gp_inversion;
}

char * GPIO_CONFIG::id() {
  return gp_id;
}

void GPIO_CONFIG::isr() {
//  gpio_int_cnt[0]++;
}

uint32_t GPIO_CONFIG::int_cnt() {
//  return gpio_int_cnt[0];
}

@EDIT 2018/01/04 08:10 我对文件添加了一些更改:

主 .ino 文件

isr_ptr isrptr[AVAILABLE_GPIO_CNT];

GPIO_CONFIG.h

#define AVAILABLE_GPIO_CNT 7

class GPIO_CONFIG;
typedef /*static*/ void (*isr_ptr)();
extern isr_ptr isrptr[AVAILABLE_GPIO_CNT];
extern GPIO_CONFIG gpio[AVAILABLE_GPIO_CNT];

(...)

public:
  void setIndex(const uint8_t * i);
  uint8_t index();

(...)

private:
  uint8_t gp_index;
  uint32_t gp_cnt_value;

GPIO_CONFIG.cpp

void GPIO_CONFIG::setIndex(const uint8_t * i){
  gp_index = *i;
  isrptr[gp_index] = &isr;
}

uint8_t GPIO_CONFIG::index(){
  return gp_index;
}

void GPIO_CONFIG::setUp(const char * key) {
  (...)
  attachInterrupt(digitalPinToInterrupt(gp_number), isrptr[gp_index], FALLING);
  (...)
}

void GPIO_CONFIG::isr() {
  for(uint8_t i=0; i<AVAILABLE_GPIO_CNT; ++i){
    if(&isrptr[i] == &gpio[i].isr()){ //here is my actualy problem. how can i compare this?
      gpio[i].increment_cnt_value();
      break;
    }
  }
}

uint32_t GPIO_CONFIG::int_cnt() {
  return gp_cnt_value;
}

解决方案

在这里,我放置了必须修改的短片段:

GPIO_CONFIG.cpp

isrptr[gp_index] = &isr;isrptr[gp_index] = isr;

if(&isrptr[i] == &gpio[i].isr){if(isrptr[i] == gpio[i].isr){

4

1 回答 1

0

我已多次查看您的代码,但找不到您的 ISR。我知道如何在简单的 C 代码中处理此类问题:您只需为每个中断引脚定义一个包含一个元素的数组,然后从其各自的 ISR 中递增该元素。我不知道如何将其与您所展示的内容联系起来。

经常引起麻烦的部分是您通常需要将主代码和 ISR 之间共享的变量定义为 volatile。不这样做可能会导致很难找到的问题,因为编译器会优化掉它认为没有改变的东西(在 ISR 或主代码中)。

此致,

于 2018-01-03T14:46:34.940 回答