Внешнее прерывание и прерывание цикла
- Войдите на сайт для отправки комментариев
Добрый день!
В поиске не смог найти желаемый ответ, если пропустил, укажите где почитать.
Проблема в следующем:
int p = 100; int m = 1; int o = 0; void setup() { pinMode(2, INPUT); digitalWrite(2, HIGH); attachInterrupt(0, mm, FALLING); } void loop() { switch (m){ case 1: for(int i=0; i<m; i++){in();} break; //выполняется 1 раз case 2: for(int i=0; i<m; i++){in();} break; //выполняется 2 раза case 3: for(int i=0; i<m; i++){in();} break; //выполняется 3 раза case 4: for(int i=0; i<m]; i++){in();} break; //выполняется 4 раза } } void mm(){ m++; if(m>4){m=1;} } void in(){ o = 10; st(); o = 20; st(); o = 30; st(); o = 40; st(); } void st(){delay(o);}
Программа выше, убрано всё лишнее, оставлен алгоритм работы, вывод2(прерывание0) замыкается кнопкой на землю, при этом значение m меняется сразу, но выхода из текущего цикла for не происходит. Если идет выполнение цикла for в case 4, которое выполняется, в данном примере, 4 раза, каждый раз занимает, допустим 1 минуту, итого весь цикл работает 4 минуты, если нажать кнопку на 1й минуте, m поменяется, но switch не переключит case пока цикл for не закончится.
Это такая особенность ардуины или есть варианты? Желательно, после срабатывания прерывания прервать выполнение текущего for и обработать switch согласно новой m.
BoBo4kA, начнём с того, что переенные, изменяемые в прерывании принято квалифицировать как волатайл.
Разницы я не заметил, как определить переменную, и, исходя из описания прерываний, счёл данный параметр не нужным, т.к. переменная меняется не только в функции прерывания(этого не видно в привиденном коде). Если подскажите, в чем разница, буду благодарен.
Аппаратно дребезг устраняете?
на мой взгляд не важно почему цикл не прерывается при уменьшении (предположим, что m кешируется в регистре AX проца)
важно, что прерывать цикл следует явным образом, с использованием кода, по тому как иначе хрен разберешь твой код и он будет приводить к непонятным последствиям....
да и вообще про стек параметров при вызовах операторов и функций надо почитать и прикинуть как в этот стек вклиниваются прерывания...
Разницы я не заметил, как определить переменную, и, исходя из описания прерываний, счёл данный параметр не нужным, т.к. переменная меняется не только в функции прерывания(этого не видно в привиденном коде). Если подскажите, в чем разница, буду благодарен.
Для понимания проблемы рабочий код:
Мигает светодиодами на ногах 4,5,6,7, 13й(на плате) показывает состояние переменной m, которая меняется нажиманием кнопки(дребезг, в данном случае, не критичен, т.к. мы видим состояние)
цикл выполняется f раз, за один проход "крутит" светодиоды в одну или в другую сторону, при переключении сначало "докручивает цикл и только потом меняет направление (отрабатывает switch). Возможен ли такой вариант реализации, при которой будет проверять switch сразу при срабатывании прерывания не докручия for?
Radjah, рис с гречкой, в данном случе, неуместны, т.к. я не вижу проблему в работе программы, в то время как вкусовые ощущения от продуктов я различаю.
Возможен ли такой вариант реализации, при которой будет проверять switch сразу при срабатывании прерывания не докручия for?
Вы изначально строите алгоритм недружелюбный к быстрой смене функции. Тем не менее можно сделать то, о чём вы говорите не переписывая всё с ноля. Сделайте переменную i глобальной. уберите "int" из циклов. В void mm() добавьте строку i=f; После этого нажатие кнопки будет запускать другую программу почти мгоновенно.
Идею понял, спасибо! )
Возникла другая проблема дальше, но её удалось решить, способ, предложенный dimax'ом помог.
Проблема была в том, что в switch/case есть другой for, который запускался и вызывал задержку, решение в выделении отдельных переменных под каждый for case'a
Разницы я не заметил, как определить переменную, и, исходя из описания прерываний, счёл данный параметр не нужным, т.к. переменная меняется не только в функции прерывания(этого не видно в привиденном коде). Если подскажите, в чем разница, буду благодарен.
Запомните раз и навсегда, если какая-либо переменная изменяется в обработчике прерываения, её нужно объявлять c volatile. Не важно, меняется ли эта переменная где-то ещё. Если сомневаетесь - информации в интернете достаточно, найдите и почитайте.