Вопрос про внешние прерывания

Тема в разделе "Arduino & Shields", создана пользователем DKo, 30 янв 2016.

  1. Megakoteyka

    Megakoteyka Оракул Модератор

    Там же есть режим, когда прерывание возникает по любому фронту. А в прерывании определяете состояние пина, запоминаете время и ставите флаг для обработки в основном цикле.
    Попробуйте логику типа такой:
    Код (C++):
    bool btnPressed = false;
    bool btnReleased = false;
    long pressTime, releaseTime;

    interrupt() {
      if(digitalRead(...) == true) {
        btnPressed = true;
        btnReleased = false;
        pressTime = millis();
      }
      else {
        btnReleased = true;
        releaseTime = millis();
      }
    }

    void loop() {
      if(btnPressed && btnReleased) {
        long time = releaseTime - pressTime;
        btnPressed = false;
        btnReleased = false;
        ...
      }
    }
     
    Последнее редактирование: 31 янв 2016
    DKo нравится это.
  2. AlexU

    AlexU Гуру

    Теоретически можно. Адрес, с которого должно продолжится выполнение программы после выхода из обработчика прерывания, хранится в стеке. Если этот адрес подменить на адрес функции loop(), то после выхода из обработчика прерывания, выполнение продолжится с начала функции loop(). Но изменяя содержимого стека, Вы должны чётко понимать, что делаете.
     
    DKo нравится это.
  3. Onkel

    Onkel Гуру

    очень бы не советовал так делать, тем более начинающим. Дейстра бы такой совет не одобрил бы. Лучше хорошенько подумать над структурой алгоритма без подмены значений программного счетчика.
     
  4. Onkel

    Onkel Гуру

    рационально подумать над структурой алгоритма, а долгие вычисления разбивать на фрагменты, ну вроде как распараллеливать по времени, чтобы время прокрутки цикла loop() не было большим. Хотя я не могу представить себе, что такое можно делать десять миллисекунд? FFt разве что.
    И возвращение в начало должно быть структурировано - что там в регистрах, когда вы насильно подменяете программный счетчи?
     
  5. DKo

    DKo Нерд

    Да, спасибо, точно так осознал уже и сделал)
     
  6. DKo

    DKo Нерд

    Действительно, проще немного переделать алгоритм
     
  7. TotCambIKoka

    TotCambIKoka Нерд

    Подниму тему. Интересует все же использование delay() в функции аппаратного прерывания.
    Что ж... чтоб вы товарищи телепаты не гадали что и зачем мне это - расскажу про свой проект:
    Суть в том что я хочу включать комп не кнопкой большим пальцем ноги, а тумблером на три положения on-off-on ( чтобы включить или выключить, мне нужно тумблер из одного крайнего положения перещелкнуть в другое, для имитации длительного нажатия - поставить и удерживать тумблер в среднем положении), для этого планировал к штырям материнки запаралелиться с помощью npn транзистора или оптопары. И вот сама проблема в том что мне необходимо подать импульс 0.1 с, а как сделать это без delay() я незнаю.
    Ниже недописанный кусок моего кода:
    Код (C++):
    #define SER 11
    #define LATCH 10
    #define CLK 9
    #define POW_LED 13
    #define FLASH_LED 12
    #define TO_MOTHER_BOARD 8

    unsigned int vals[12] = {0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047};

    void setup() {
      pinMode(TO_MOTHER_BOARD, OUTPUT); // на мать импульс
      pinMode(FLASH_LED, OUTPUT);// синхронизирован с исмпульсом на мать
      pinMode(POW_LED, OUTPUT); // есть питание
      pinMode(SER, OUTPUT);
      pinMode(LATCH, OUTPUT);
      pinMode(CLK, OUTPUT);
      attachInterrupt(0, tumbler, FALLING);//либо FALLING либо LOW для экстр выключения
    }
    void tumbler() {  // СПАСАТЬ ЗДЕСЬ Т_Т
      digitalWrite(TO_MOTHER_BOARD, HIGH);
      digitalWrite(FLASH_LED, HIGH);
      delay(100);
      digitalWrite(TO_MOTHER_BOARD, LOW);
      digitalWrite(FLASH_LED, LOW);


    }

    void loop() { //в лупе у нас гистограмный индикатор на 12 диодов через 2 74hc595

      int pot = analogRead(0);
      pot = constrain(pot, 5, 1000);
      pot = map(pot, 5, 1000,  0, 11);
      digitalWrite(LATCH, LOW);//низкий - начало отправки
      shiftOut(SER, CLK, MSBFIRST, highByte(vals[pot]));
      shiftOut(SER, CLK, MSBFIRST, lowByte(vals[pot]));
      digitalWrite(LATCH, HIGH);
      delay(100);
    }
    По схеме: второй пин моей мини про прижат к земле через 10к резистор, в положении тумблера ON на порт идет HIGH c 5 вольт, питание буду брать с разьема молекса блока питания
     
  8. Ты используй прерывания со второго таймера, а внутри них delay(), так как эта функция прерывания с 1 таймера работает)
     
  9. Onkel

    Onkel Гуру

    использовать delay() внутри прерывания нельзя, если это не 1-2 мкс конечно.
    arduino ide- file- примеры- ...blink без delya и будет вам щастье.
     

  10. Тогда можно сделать два разных прерывания на RISING и на FALLING, в RISING запоминать millis(), а в FALLING тоже брать millis() и заносить в переменную разность нового и старого millis(). А после обработки этой разности в основной программе обнулять эту переменную.