Arduino, как посчитать внешние прерывания внутри массива объектов?

Я начинаю играть с Arduino IoT (ESP32). Я прочитал конфигурацию GPIO из файла на SD-карте. У меня проблема с внешними прерываниями. Мне нужно посчитать количество прерываний для данного 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){

-1

Решение

Я просмотрел ваш код несколько раз и не могу найти ваш ISR. Я знаю, как справиться с такой проблемой в простом C-коде: вы просто определяете массив с одним элементом для каждого контакта прерывания и увеличиваете этот элемент из соответствующего ISR. Я не знаю, как связать это с тем, что вы показали.

Часть, которая часто вызывает проблемы, состоит в том, что вам обычно нужно определить переменные, общие для основного кода и ISR, как volatile. Невыполнение этого требования может вызвать проблемы, которые действительно трудно найти из-за того, что компилятор оптимизирует все, что он решает, не изменилось (в ISR или основном коде).

С наилучшими пожеланиями,

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]