I2C OLED конфликтует с прерыванием

Я использую Nmradcc.h в сочетании с OLED I2C.

Файл nrmadcc.h использует прерывание 0 на контакте 2, OLED использует A4 и A5.

После инициализации OLED и функции

Проблема в том, что я могу использовать Funktion с Interrupt или OLED, но не вместе. Но я хочу. Могу ли я остановить функцию прерывания с помощью nointerrupt, а не I2C и иначе, или есть лучшая война?

Спасибо, Берт


#include <SPI.h>                  ////
#include <Wire.h>                 ////
#include <Adafruit_GFX.h>         ////
#include <Adafruit_SSD1306.h>     ////
#include <DCC_Decoder.h> 
#define kDCC_INTERRUPT 0

Adafruit_SSD1306 display(128, 64, &Wire, -1);   ////

////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
// Введите количество аксессуаров/функций, которыми вы хотите управлять
////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
const byte maxaccessories=1;
////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////

typedef struct {
  int               address;          // Адрес для ответа
  byte              mode;             // 0=непрерывный, 1=одноразовый, 2=мигающий
  byte              output;           // Состояние аксессуара: 1=включено, 0=выключено (только для внутреннего использования)
  int               outputPin;        // Выходной контакт Arduino
  byte              highlow;          // Состояние выходного контакта: 1=ВЫСОКИЙ, 0=НИЗКИЙ
  boolean           finished;         // Ячейка памяти, в которой говорится, что ваншот завершен
  int               durationonMilli;  // время включения oneshot или flasher в мс
  int               durationoffMilli; // время выключения ваншота или флешера в мс
  boolean           isAnalog;         // false=цифровой, true=аналоговый, отправляет AnalogValue на выходной контакт.
  byte              analogValue;      // импульс со значением модуляции (ШИМ), который записывается на вывод. Диапазон: 0–255
                                        // перейдите на http://arduino.cc/en/Reference/AnalogWrite, чтобы узнать, какие контакты поддерживают аналоговый выход ШИМ
  unsigned long     onMilli;          // для внутреннего использования
  unsigned long     offMilli;         // для внутреннего использования
} 
DCCAccessoryAddress;
DCCAccessoryAddress accessory[maxaccessories];

////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
// Заполняем атрибуты для каждого аксессуара/функции
// КОПИРУЕМ - ВСТАВЛЯЕМ столько раз, сколько у вас есть функций. Сумма должна быть такой же, как в строке 17 выше!
////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
void ConfigureDecoderFunctions() // Количество аксессуаров должно быть таким же, как в строке 26 выше!
{
  accessory[0].address = 1;    // адрес ДКК
  accessory[0].mode = 0;       // Непрерывно. HIGH, пока DCC снова не выключит адрес.
  accessory[0].outputPin = 13; // Пин Arduino, к которому подключена функция.
  accessory[0].output = 0;     // Исходное состояние (0 или 1) вывода после запуска.

  for(int i=0; i<maxaccessories; i++)
  {
    if (accessory[i].outputPin)
    {
      pinMode( accessory[i].outputPin, OUTPUT );
      // Установить начальное состояние (только для режима 0, непрерывно)
      if (!accessory[i].mode && accessory[i].output) digitalWrite(accessory[i].outputPin, HIGH);
      else digitalWrite (accessory[i].outputPin, LOW);
      }
    }
  }  // КОНЕЦ Конфигурации функций декодера

  ////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
  // обработчик дополнительных пакетов DCC
  ////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
  void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
  {
    // Преобразование формата адреса пакета NMRA в человеческий адрес
    address -= 1;
    address *= 4;
    address += 1;
    address += (data & 0x06) >> 1;

    boolean enable = (data & 0x01) ? 1 : 0;

    for (int i=0; i<maxaccessories; i++)
    {
      if (address == accessory[i].address)
      {
        if (enable) accessory[i].output = 1;
        else accessory[i].output = 0;
      }
    }
  } //END BasicAccDecoderPacket_Handler

////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
// Настройка (выполнить один раз)
////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
void setup() 
{ 
  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
  ConfigureDecoderFunctions();
  DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
  pinMode(2,INPUT_PULLUP); //Прерывание 0 внутренним подтягивающим резистором (можно избавиться от внешнего 10k)
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW); // выключаем светодиод Arduino при запуске
  for (int n=0; n<maxaccessories; n++) accessory[n].output = 0; //все сервоприводы на минимальный угол и функции на 0

  display.display();
  display.clearDisplay();

} // КОНЕЦ настройки

////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
// Основной цикл (непрерывный)
////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////
void loop()
{
  static int addr = 0;

  DCC.loop(); // Библиотека цикла DCC

  if( ++addr >= maxaccessories ) addr = 0; // Следующий адрес для проверки

  if (accessory[addr].output == 1)
  {
    if (accessory[addr].mode == 0) accessory[addr].highlow=1; // непрерывно

    if (accessory[addr].mode == 1) // одноразовый
    {
      if (!accessory[addr].highlow && !accessory[addr].finished)
      {
        accessory[addr].highlow = 1;
        accessory[addr].offMilli = millis() + accessory[addr].durationonMilli;
      }
      if (accessory[addr].highlow && millis() > accessory[addr].offMilli)
      {
        accessory[addr].highlow = 0;
        accessory[addr].finished = true;
      }
    }

    if (accessory[addr].mode == 2) // прошивальщик
    {
      if (!accessory[addr].highlow && millis() > accessory[addr].onMilli)
      {
        accessory[addr].highlow = 1;
        accessory[addr].offMilli = millis() + accessory[addr].durationonMilli;
      }
      if (accessory[addr].highlow && millis() > accessory[addr].offMilli)
      {
        accessory[addr].highlow=0;
        accessory[addr].onMilli = millis() + accessory[addr].durationoffMilli;
      }
    }

      display.setCursor(90, 50);  ////
      display.setTextSize(2);     ////
      display.print(F("ON")) ;    ////

  }
  else // аксессуар[адрес].output == 0
  {
    accessory[addr].highlow=0;
    if (accessory[addr].mode == 1) accessory[addr].finished = false;

      display.setCursor(90, 50);  ////
      display.setTextSize(2);     ////
      display.print(F("OFF")) ;    ////

  }

  if (accessory[addr].highlow)
    {
      if (accessory[addr].isAnalog) analogWrite (accessory[addr].outputPin, accessory[addr].analogValue);
        else digitalWrite (accessory[addr].outputPin, HIGH);
    }
  else 
    {
      if (accessory[addr].isAnalog) analogWrite (accessory[addr].outputPin, 0);
        else digitalWrite( accessory[addr].outputPin, LOW);
  }
  display.display();
} //КОНЕЦ цикла

В этом примере OLED-экран I2C не работает. Когда я меняю место

Adafruit_SSD1306 display(128, 64, &Wire, -1);

и

DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );

Прерывание DCC не работает, OLED работает.

, 👍1

Обсуждение

Пожалуйста, отредактируйте вопрос, если у вас есть дополнительная информация или обновления., @VE7JRO


1 ответ


3

Для работы I2C требуется точное время. Если прерывания срабатывают, когда Arduino пытается прочитать или записать шину I2C, произойдет сбой. Я подозреваю, что вам придется отключать прерывания каждый раз, когда вы читаете/записываете в шину I2C, а затем снова включаете их, когда закончите.

,

Спасибо, поэтому все, что вызывалось отображением, мне нужно использовать nointerrupts ()?, @Bert Booltink