Выход из прерывания в нужное место программы

Тема в разделе "Флудилка", создана пользователем CYITEP_BAC9I, 26 июл 2018.

  1. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    вечер всем добрый. более менее освоил компаратор. и даже написал работающий скетч. (пилю свой дозиметр)
    НО, теперь встала проблема. как из прерывания выйти не в то место где прервался основной цикл, а в кусок кода отвечающий за включение выключение генерации шим. частота большая и каждая микросекунда на счету.
    goto ясен баобаб не поможет, а так бы было удобно.
    а еще прекраснее было бы что бы строки
    Код (C++):
    TCCR1A =TCCR1A |(1<<COM1A1);
    TCCR1A =TCCR1A & (~ (1<<COM1A1));
    отработали непосредственно в прерывании.но компилятор вроде и не материться но и не работают эти строки. если с флагами и потом обрабатывать в основном цикле то все отлично.

    суть вопроса можно ли из прерывания, плюнуть на то что было в основном цикле и перейти в нужное место.
    (goto написано для примера)

    Код (C++):
    #define Led 8
    bool switch_1=0;
    void setup() {
      pinMode(Led,OUTPUT);
      //pinMode(7,INPUT);
    ACSR = ACSR |(1<<ACBG)|(1<<ACIE);//включение и разрешение прерываний компаратора по любому событию
      TCCR1A=(1<<COM1A1)|(1<<WGM10); // настройка генерации шим на таймере 1
      TCCR1B=(1<<WGM12)|(1<<CS10); //8 битный шим
      OCR1A=0xC8; //32 64 // скважность
    Serial.begin(9600);
    }


    ISR(ANALOG_COMP_vect)//INT1_vect
    {
    if( ACSR & (1 << ACO) ) //если на компараторе 1 то зажигам диод
    {
      switch_1=1;
     
      //goto pump; //хотел что то вроде этого
      }
      else if( !(ACSR& (1 << ACO)) )
      {
        switch_1=0;
       // goto pump;
     
      }
    }
    void loop() {

      pump:
      if(switch_1==1)
      {
        TCCR1A =TCCR1A |(1<<COM1A1); //включаем накачку  
        Serial.println("1");
        digitalWrite(Led,1);
      }
       else if(switch_1==0)
      {
        TCCR1A =TCCR1A & (~ (1<<COM1A1)); //выключаем накачку
        digitalWrite(Led,0);
        Serial.println("0");
      }

      //остальной кот

    }
    плюс чтоб не плодить посты. пожалуйста посоветуйте как умные люди пишут многоуровневое меню с подпунктами? на if ах сильно огромный "кот" получается, да и работает хреново. а других источников как разбирать скетчи других людей, так и не нашел. уж больно специфическая тема
     
  2. DetSimen

    DetSimen Guest

    Если ты из прерывания не вернешся обратно, это чревато разбалансировкой стека и крахом. Но внутри прерывания можно вызвать функцию установки чего нибуть, главное чтоб она была как можно короче.
    Еще, опытные сишники используют setjump() и longjump(), почитай чонить про них, вдруг разберешьса.
     
    Mitrandir и CYITEP_BAC9I нравится это.
  3. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    пичаль, пока "ниасилю"(((, но буду стараться.
     
  4. DetSimen

    DetSimen Guest

    Вот и мой, разрушенный олкаголем старческий мозг ниасилил.
     
    CYITEP_BAC9I нравится это.
  5. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    вообще пичаль. почитал про эти функции и понял, что ничего не получаться. буду думать другие варианты. одного не пойму чего компилятору надо то? делов то секунда, поменять один бит, а не работает. (в самом обработчике прерывания)
    добавлено позднее. хотя вроде есть выход. через равные промежутки по всему скетчу делать (полностью основной цикл со всеми расчетами и выводом на экран занимает 470 миллисекунд), проверки не изменился ли флаг срабатывания компаратора, если да, по goto переходить в этот кусок кода. ничего умнее не могу придумать.
    всем баю бай. утро вечера мудренее.
     
    Последнее редактирование: 26 июл 2018
  6. Arhat109

    Arhat109 Гик

    Пошукайте про setjump(), longjump(). Но, в целом запрос неверен - так делать на 146% не надо.
     
    CYITEP_BAC9I нравится это.
  7. CYITEP_BAC9I

    CYITEP_BAC9I Гик

    уже понял, ищу выходы
     
  8. DetSimen

    DetSimen Guest

    Скажите, чем отличается Ваш ответ от #2? Зачем толочь воду в ступе?
     
    Сусемьбек нравится это.
  9. Arhat109

    Arhat109 Гик

    Да ничем. Но раз ТС продолжает настаивать - неплохо ему напомнить ишо разок. :)
     
    DetSimen нравится это.
  10. Tomasina

    Tomasina Сушитель лампочек Модератор

    Что-то мне подсказывает, что если возникает ситуация "из прерывания выйти не в то место где прервался основной цикл, а в кусок кода", то логика программы построена неверно.
    К тому же что мешает использовать флаг состояния byte state, а при выходе из прерывания проверять этот флаг и прыгать в нужный блок кода (функцию)?
     
    parovoZZ, CYITEP_BAC9I, Сусемьбек и 2 другим нравится это.
  11. Спасибо. Вроде я такую мысль в 5 посте пытался выразить. Завести флаг. Написать макрос проверки и выхода в нунный кусок кода, и разместить его равномерно в скетче. Чтоб примерно между проверками было не более 5 мс.
    Этот вопрос решил, за что всем спасибо за наводки. Теперь пилю новый булыжник - меню. Наковырял пиндосских скетчей и разбираю. На свитч кейс конечно интересно, но неудобно в подпункты заходить выходить. If ами - громоздко но более удобно для меня. Заодно понял почему хреново работало старое меню. Цикл долгий а проверка кнопок только в начале цикла была. Получалось что быстрые нажатия он и не отрабатывал. Теперь хочу сделать таг. Соорудить прерывания для кажлкаж пина к которому подключены кнопки, при нажатию ставить флаг нажатия. Потом уже в начале скетча все проверять было ли нажатие и выполнять нужные действия
     
  12. SergeiL

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

    5-ый пост:
    :):

     
    Последнее редактирование: 27 июл 2018
  13. Ну и???? Мысль то одна и та же только по другому выражена
     
  14. Igor68

    Igor68 Гуру

    Если вы умеете работать со стеком, то Вам не будет трудно поместить туда адрес нужной функции, куда хотите уйти из прерывания...
    НОООООООООО:
    Если так делать, то стек будет разрастаться, потому как функция из которой ушли в прерывание не будет завершена. Т.К. Вызов функции это - занимаем часть стека, а возврат из неё это - освобождаем ранее занятую часть стека.
    И нарушение этого в народе обзывается "утечка памяти" своего рода. А это КИРДЫК в работе программы.
     
    CYITEP_BAC9I и Сусемьбек нравится это.
  15. ‎arduino.ru/forum/programmirovanie/preryvaniya-est-voprosy-nuzhny-otvety
    здесь решали подобную задачу. Прикольно что тоже вариант проскакивал в основном цикле делать постоянные проверки. А главная проблема как пишут в длинном коде. Если правильно понял скетч ТС отрабатывал за 50 мс. Куда им до моих пол секунды). Но на мысль навели, разбить код на части. While или swicth case и придумать алгоритм переключения. Блин самостоятельно выучить программирование может только Чак Норрис, остальным нужен или учитель или профильный институт.
     
  16. SergeiL

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

    Лично мое мнение, так делать категорически нельзя.
    А если мы попали в прерывание во время выполнения функции вызванной с параметрами, то стек был сдвинут на размер переменных, переданных в функцию, плюс локальные переменные функции, и т.д .
    Мы подменили адрес возврата, и естественно попали в точку, где не скидываются со стека ни параметры функции ни локальные переменные.
    Это явное переполнение стека. :(

    В другой теме увидел, что Вы пишите с двух ников, теперь понятно.

    По поводу решения, я все критичное к обработке в реал тайме вытаскиваю либо в прерывание по изменению, либо в прерывание по таймеру, а в loop оставляю только то, что не критично ко времени реакции.
     
    Последнее редактирование: 28 июл 2018
    Сусемьбек нравится это.
  17. Arhat109

    Arhat109 Гик

    Полностью согласен насчет параметров и стека. Проблема решаема, но явно не силами ТС-а.

    А в целом, попробуйте открыть для себя "автоматное программирование". Оно как раз "самое то" для задач управления и ТЗ легко можно переформулировать под него, от чего оно становится только яснее и проще. (* и такие проблемы уходят сами собой *)

    "более менее освоил компаратор. и даже написал работающий скетч. (пилю свой дозиметр)
    НО, теперь встала проблема. как из прерывания выйти не в то место где прервался основной цикл, а в кусок кода отвечающий за включение выключение генерации шим. частота большая и каждая микросекунда на счету.
    ...
    а еще прекраснее было бы что бы строки
    Код (C++):
    TCCR1A =TCCR1A |(1<<COM1A1);
    TCCR1A =TCCR1A & (~ (1<<COM1A1));
    отработали непосредственно в прерывании.но компилятор вроде и не материться но и не работают эти строки. если с флагами и потом обрабатывать в основном цикле то все отлично.

    суть вопроса можно ли из прерывания, плюнуть на то что было в основном цикле и перейти в нужное место."

    О чем речь? (как работает дозиметр) Как понимаю, о том, что ВВ накачивается импульсно через ШИМ и есть компаратор, сравнивающий с эталоном. Также есть "частица" разряжающая ВВ часть. А ещё надо (в loop) постоянно проводить измерение, дабы не прохлопать частицу..

    Давайте переформулируем задачу в автоматный стиль (КА - конечный автомат), есть:
    1. КА "накачка", у которого есть состояния: "ВВ достаточно" и "ВВ мало" и переходы: "упало-включить накачку" и "достаточно-выключить". Источником новостей является "компаратор".
    2. КА "надзор", который может иметь состояния: "есть ВВ = можно ожидать частицу", "ВВ мало, смотреть не зачем" и "Нет частицы" и "Нашел". Между этими состояниями есть переходы и некоторые из них инициируются "извне" - сменой состояния предыдущего КА, а некоторые поступают из своего источника новостей (входного потока) - АЦП или что там служит измерителем.. пусть будет "датчик".
    3. КА "отображалка" .. ну это то, что рисует на экран, пищит, свистит, моргает или действует как-то на нервы ещё. Оставлю как домашнее задание.

    .. вот теперь, попробуйте изменить программу так, чтобы "состояние" отражалось некоторым ПРИЗНАКОМ (флагом, переменной, свойством класса и т.д.), а изменение состояния - это ДЕЙСТВИЕ (метод класса, функция, процедура и т.д.), которое может в т.ч. происходит и неявно, асинхронно и даже по прерыванию.

    .. упс. А что тогда такое "основной цикл"? :) А основной цикл сводится к банальному перебору проверки состояний КА, чтению "новостных потоков" и вызову действий по переходу.
    Он, кстати, при типовом (класс, библиотека и т.д.) организации КА может быть и ВООБЩЕ одинаковым для любого устройства управления.. :)

    Думаю что ТЗ в таком виде не потребует услилий с goto или сути поднятой темы от слова "совсем". :)
     
    Последнее редактирование: 28 июл 2018
  18. SergeiL

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

    :):):) Спасибо за совет, ..промолчу по поводу того, когда я его открыл для себя... :):):)

    А Вы ESP8266 программировали из под Arduino IDE?
    Там, ваши рекомендации не сработают! ;)
     
  19. Arhat109

    Arhat109 Гик

    Этот подход универсален "в целом" и называется "автоматное программирование". Можно прямо так и гуглить. ESP2866 да ещё и из под ИДЕ .. не не программировал. Вообще мало чего программирую в ИДЕ. Есть нормальные средства и для каждого типа камней они - свои.
    ИДЕ - это же так, "для обучения непрофессионалов".. детишек, вот да .. учу в ИДЕ. :)

    Что конкретно не позволит "так" решать задачу в этой комбинации? Интересно просто..
     
  20. SergeiL

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

    Можете уже начинать гуглить!