Объект класса внутри ISR

Мне нужно смоделировать АЦП, который ведет себя как подчиненное устройство I2C. Имитированные значения, которые должен предоставить АЦП, передаются по последовательному порту, сохраняются в атрибуте и запрашиваются ведущим устройством через I2C.

Упрощенное решение заключается в следующем. У меня есть структура ADC, описывающая преобразователь:

struct ADC 
{
  uint32_t register_1;
  uint32_t register_2;

  void write_register_1(uint32_t data){
    register_1 = data;
  }

  void write_register_2(uint32_t data){
    register_2 = data;
  }

  uint8_t read(){
    return register_1;
  }

  // некоторые другие методы настройки...
};

В loop() я читаю серийный номер, чтобы обновить значение ADC::register, а в обработчике onRequest я в конечном итоге отправьте запрошенные данные, обратившись к ADC::register:

ADC adc{};

void setup(){
  // здесь настраиваем adc, Wire и Serial
  Wire.onRequest(slaveTransmitterHandler)
}

void loop(){
  if (Serial.available() > 0)
  {
     // читаем серийный номер, анализируем полученные данные и проверяем их
     uint32_t data = parse_serial(); // делаем что-нибудь, чтобы проверить данные...

     // обновляем атрибут adc
     uint8_t oldSREG = SREG;
     noInterrupts(); // отключаем прерывания для обновления uint32
     adc.write_register_1(data);
     SREG = oldSREG;
  }
}

void slaveTransmitterHandler(){
  Wire.beginTransmission(ADDRESS);
  Wire.write(adc.read());
  Wire.endTransmission();
}

void slaveReceiverHandler(){
  uint32_t i2c_received_data;
  while (Wire.available){
    // заполняем i2c_received_data с помощью Wire.read()
  }
  adc.write_register_2(i2c_received_data);
}

Я не уверен, нужно ли объявлять объект adc как volutable (это означало бы объявление всех методов и переменных ADC) как изменчивый). Безопасно ли использовать объект внутри обработчика I2C, вызываемого прерыванием I2C?

Насколько мне известно, это не так (я не могу найти причину, по которой она должна отличаться от переменных, не принадлежащих классу), но я всегда работал с переменными, не принадлежащими к классу, и никогда с объектами cpp. Кроме того, я не могу найти никакой информации по этой теме.

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

Спасибо.

Лука

Изменить: Некоторые пояснения, поскольку мой вопрос кажется недостаточно ясным: я провожу моделирование HIL, то есть моделирует реальное оборудование с его реальными интерфейсами с моделируемой средой (включая датчики и исполнительные механизмы). Дополнительную информацию см. здесь.

Один из моих датчиков измеряет напряжение и сохраняет его в регистре АЦП (который имеет несколько регистров). Я моделирую поведение регистров АЦП в Arduino, и они будут взаимодействовать через I2C с реальным оборудованием.

Надеюсь, теперь все стало более понятно.

, 👍0

Обсуждение

Я не думаю, что класс здесь должен быть нестабильным. Ничто в ISR ничего не меняет в классе, поэтому нет никаких шансов, что ISR сработает в середине чего-то еще, обращающегося к классу и получающего поврежденные данные. Единственная возможность повреждения здесь — это если ISR запустит функцию записи, но вы, похоже, справились с этим, создав вокруг нее критический раздел. Было бы иначе, если бы ISR записывал данные в объект, но в том виде, в каком они записаны, он только читает из него. Я думаю, тебе здесь хорошо., @Delta_G

@Delta_G Это похоже на ответ. Пожалуйста, напишите один, а не комментарий. Спасибо., @Nick Gammon

Почему вы делаете Wire.onRequest(slaveTransmitterHandler)? Похоже, вы действительно используете I2C, а не имитируете его., @Nick Gammon

@Delta_G, спасибо! Допустим, я также устанавливаю некоторые атрибуты объекта adc в прерывании. Как мне справиться с этим случаем? Я отредактировал исходное сообщение, включив в него этот случай (см. «slaveReceiverHandler»). Должен ли я объявить объект (и все атрибуты и методы класса) как «изменчивый»? Думаю, да, но мне кажется, что мне не совсем понятно, что означает «летучий» при использовании в классе C++ (https://en.cppreference.com/w/cpp/language/cv, эта страница выходит за рамки моего понимания) ., @lumaca96

Это не форум. Если вы хотите расширить вопрос, пожалуйста, **отредактируйте вопрос**. Любые ответы должны касаться вопроса (в отредактированном виде), а не вопроса и случайных комментариев. Ответ также не должен быть в комментарии (это не ваша вина)., @Nick Gammon


1 ответ


0

Если это симуляция, а не использование прерываний, то вам вряд ли нужно объявлять что-то изменчивое. Однако использование библиотеки Wire делает ее менее похожей на симуляцию. Лично я думаю, что ваша проблема недостаточно объяснена. Пожалуйста, опубликуйте весь свой код. Если вы моделируете, вам не нужно беспокоиться об аппаратных прерываниях. Если вы используете библиотеку Wire, вы это сделаете.

Другое ваше сообщение Получить адрес транзакции I2C при регистрации нескольких адресов кажется здесь актуальным.

,

Он использует Arduino для имитации АЦП I2C. Ссылка I2C реальна. Показания АЦП поддельные., @Edgar Bonet

@EdgarBonet прав. Я отредактировал вопрос, добавив некоторые подробности., @lumaca96