Использование прерываний pcint

Тема в разделе "Arduino & Shields", создана пользователем 64detali, 17 фев 2022.

  1. 64detali

    64detali Нерд

    Всем привет, возникла потребность использовать дополнительный обработчик прерываний PCINT на плате ардуино nano. В связи с этим есть интересные вопросы:
    1) могу ли я используя в группе D02-D07 обработчик INT, еще и добавить PCINT или будет конфликт?
    2) могу ли я использовать в одной из групп PCINT пин на прерывание, а соседние пины по другому назначению или возникнет конфликт?
    upload_2022-2-17_0-0-41.jpeg
     
  2. Asper Daffy

    Asper Daffy Иксперд

    Судя по появлению данного поста, пока не можешь. Если делать правильно, то никакого конфликта не будет.
    Судя по появлению данного поста, пока не можешь. Если делать правильно, то никакого конфликта не будет.
     
  3. 64detali

    64detali Нерд

    Я со вчерашнего вечера начал изучать PCINT, скетч под себя исправил на один пин, работает. Наткнулся на хорошую статью, думаю нормально всё будет. Единственное сейчас думаю оставлять прерывания на D2,D3 на INT или тоже поместить в PCINT.
    Код (C++):
    #define set1Pin 4  // датчик1 на пин D4
    #define set2Pin 5 //датчик2 на пин D5
    volatile int flow_frequency1; // измеряет импульсы на 1 датчике
    volatile int flow_frequency2; // измеряет импульсы на 2 датчике
    uint8_t oldPIND = 0xFF;
    float l_hour = 0.0; // рассчитанные литр/час
    float vol = 0.0;// рассчитанный общий объем в литрах
    float l_hour1 = 0.0; // рассчитанные литр/час
    float vol1 = 0.0;// рассчитанный объем в литрах
    float l_hour2 = 0.0; // рассчитанные литр/час
    float vol2 = 0.0;// рассчитанный объем в литрах
    unsigned long currentTime = 0; //отрезок времени для рассчета
    void pciSetup(byte pin) {
      *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // Разрешаем PCINT для указанного пина
      PCIFR  |= bit (digitalPinToPCICRbit(pin)); // Очищаем признак запроса прерывания для соответствующей группы пинов
      PCICR  |= bit (digitalPinToPCICRbit(pin)); // Разрешаем PCINT для соответствующей группы пинов
    }
    ISR (PCINT2_vect) { // Обработчик запросов прерывания от пинов D0..D7
      uint8_t changedbits = PIND ^ oldPIND;
      oldPIND = PIND;

      if (changedbits & (1 << PD4)) { // Изменился D4
        flow_frequency1++;
      }

      if (changedbits & (1 << PD5)) { // Изменился D5
        flow_frequency2++;
      }
    }
    void setup()
    {

      pinMode(set1Pin,  INPUT_PULLUP); // Подтянем пины-источники PCINT к питанию
      pinMode(set2Pin, INPUT_PULLUP);
      pciSetup(set1Pin); // И разрешим на них прерывания
      pciSetup(set2Pin);
      Serial.begin(9600);

    }

    void loop ()

    {

    // Каждую секунду рассчитываем и выводим на экран литры в час

    if(millis() - currentTime >= 1000)

    {

    currentTime = millis(); // обнуляем отрезок времени

    // первый блок для рассчета  (Частота импульсов датчика = 76 на 1л)
    l_hour1 = (flow_frequency1 * 60 / 76); // расход в л/час
    vol1 = vol1 + l_hour1 / 3600; //объем в литрах
    Serial.print(flow_frequency1); // Отображаем кол-во импульсов подачи
    Serial.println(" импульсов");
    flow_frequency1 = 0; // Сбрасываем счетчик
    Serial.print(l_hour1); // Отображаем л/час
    Serial.println(" л/час");
    Serial.print(vol1); // Отображаем объем топлива
    Serial.println(" л");

    // второй блок для рассчета  (Частота импульсов датчика = 76 на 1л)
    l_hour2 = (flow_frequency2 * 60 / 76); // расход в л/час
    vol2 = vol2 + l_hour2 / 3600; //объем в литрах
    Serial.print(flow_frequency2); // Отображаем кол-во импульсов
    Serial.println(" импульсов");
    flow_frequency2 = 0; // Сбрасываем счетчик
    Serial.print(l_hour2); // Отображаем л/час
    Serial.println(" л/час");
    Serial.print(vol2); // Отображаем объем топлива
    Serial.println(" л");

    }
    }
     
    Последнее редактирование: 17 фев 2022
  4. parovoZZ

    parovoZZ Гуру

    про какой конфликт речь?
    вопроса совсем не понял.

    Кратко по теме. Прерывание PCINT возникает тогда, когда в одном или нескольких пинах возникает условие на прерывание. Но прежде, этим пинам необходимо разрешить прерывание PCINT. Если разрешённых пинов больше, чем один, то по возникновению прерывания PCINT невозможно определить, какой из пинов его вызвал. Поэтому в обработчике прерывания необходимо самостоятельно найти вызвавший прерывание пин (разумеется, если есть такая необходимость).
    Прерывание INT0 или INT1 возникает независимо от PCINT. Т.е. если на INT0 или INT1 можно ещё "повесить" и PCINT, то возникнет сразу два прерывания. Очерёдность их вызова зависит от их приоритета. Приоритет зависит от адреса прерывания. А дальше либо Евстифеев, либо оригинальный даташит.
     
    Рокки1945 нравится это.
  5. parovoZZ

    parovoZZ Гуру

    Внимательно ИЗУЧИ даташит!!! А когда изучишь, то поймёшь разницу и будешь неприятно удивлён!