почему прерывание работает 1 раз?

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

почему прерывание работает 1 раз? повторный вызов прерывания не получается 


void setup() {

attachInterrupt(0, blink, RISING);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);

pinMode(2, INPUT);

}


void loop() 
{
  digitalWrite(11, HIGH);
  delay (250);
  digitalWrite(11, LOW);
  delay (250);
}

void blink() 
{
     wq:
 if (digitalRead(2)==HIGH)
 {
    digitalWrite(11, HIGH);
    digitalWrite(12, HIGH);
    goto wq;
 }
    else{
      digitalWrite(11, LOW);
      digitalWrite(12, LOW);
      detachInterrupt(0);
   }
}

 

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

5alex5 пишет:

почему прерывание работает 1 раз? повторный вызов прерывания не получается 


void setup() {

attachInterrupt(0, blink, RISING);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);

pinMode(2, INPUT);

}


void loop() 
{
  digitalWrite(11, HIGH);
  delay (250);
  digitalWrite(11, LOW);
  delay (250);
}

void blink() 
{
     wq:
 if (digitalRead(2)==HIGH)
 {
    digitalWrite(11, HIGH);
    digitalWrite(12, HIGH);
    goto wq;
 }
    else{
      digitalWrite(11, LOW);
      digitalWrite(12, LOW);
      detachInterrupt(0);     //  ПОНЯЛ НАДО УДАЛИТЬ ЭТО )
   }
}

 

James
Offline
Зарегистрирован: 26.02.2016

оно у тебя работает только при переходе из "0" в "1"
а в 32 строке ты его вообще выключил, вот оно и работает 1 раз

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

да да, уже осознал )

axill
Offline
Зарегистрирован: 05.09.2011

А что это за "бесконечный" цикл внутри прерывания через goto?

во первых прерывание должно отрабатывать насколько возможно быстро, в вас же здесь зависимость от внешних условий и вполне вероятна ситуация когда не выйдем из прерывания никогда

во вторых использование goto плохая практика даже для Си, а уж для Си++ это совсем не айс

Goto пришла в Си из ассемблера и рассчитана на тех кто знает сто делать, но и то, везде рекомендуется избегать использование goto там где это врзможно. У вас это возможно на 300%

Это не вопрос моды, это вопрос правильного подхода, неловкое применение goto легко может нарушить целостность программы (например выскочив из подпрограммы без восстановления стека)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а зачем 23 строка?)))

James
Offline
Зарегистрирован: 26.02.2016

хм, если это не секретная разработка, можете объяснить, что вы хотите сделать, для чего это прерывание? в общих чертах, логика

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Тогда, наверное так надо было, хотя тоже непонятно зачем цикл внутри обработчика:

void setup() 
{
  attachInterrupt(0, blink, RISING);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(2, INPUT);
}

void loop() 
{
  digitalWrite(11, HIGH);
  delay (250);
  digitalWrite(11, LOW);
  delay (250);
}

void blink() 
{
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);

  while( digitalRead(2)==HIGH ) continue;

  digitalWrite(11, LOW);
  digitalWrite(12, LOW);
}

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

а зачем вторая нога в блинке ?  получается помимо самого прервания на 0 ноге еще чтото должно/может сработать на 2.

так вторую мы можем в обычный луп вынести. вроде.  вообщем пока не до конца ясна картина :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Это уже к автору. Я только подправил его код согласно ДРАКОНу. :)

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

ну так это же внешнее прерывание, от туда и зависимость ) и цикл совсем не бесконечный если обратить внимание на ELSE )

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

И хочу заметить все работает именно так как я хочу )

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

Это может быть АВАРИЙНАЯ КНОПКА да?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Может. Но ТАК не пишут. Если сигнал на ножку 2 не придет долгое время ваш обработчик завесит всю систему .. гарантировано. Поскольку он работает с закрытыми прерываниями в таком режиме подключения. Вам правильно сказали, что эту проверку 2 ноги надо выносить в loop(), а обработчик должен быть как можно короче и никаких "установок" и тем более ожиданий в нем быть не должно "по определению". Получил сигнал - свистнул в loop() и отвалился. А loop() пусть сам разбирается тогда, когда ему удобно "хто пришел, что за штоматолог".. :)

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

а если сигнал не придет долгое время в этом случае ? что будет?

digitalWrite(11, HIGH);
20   digitalWrite(12, HIGH);
21  
22   while( digitalRead(2)==HIGH ) continue;
23  
24   digitalWrite(11, LOW);
25   digitalWrite(12, LOW);

и на сколько это долгий сигнал что то я не могу понять, работает это все одинаково! 

5alex5
5alex5 аватар
Offline
Зарегистрирован: 10.04.2016

И каким образом мне в loop от сюда обращаться? тоже через goto? )

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Из асинхронно выполняемых ветвей графа исполнения в главную ветвь обычно обращаются через установку и проверку семафоров или организацией рандеву.

По-просту, используют глобал. Обработчик только изменяет состояние глобала и завершается. Основной цикл проверяет изменение глобала (семафора) и если надо, то висит в цикле ожидая изменения глобала(семафора). В качестве семафора может указываться и адрес перехода в ожидающей задаче и/или место куда надо сообщить ожидающей задаче результат обработки (механизм рандеву языка АДА). Возможна также организация очередей из семафоров или у входов Рандеву (очередь slave задач, ожидающих данных от master).

В целом, советую найти и почитать книжки по программированию распределенных, параллельных систем и особенно систем реального времени. Ну и заодно найти хотя бы краткое описание языка АДА. В нем собрано наибольшее количество примитивов межзадачного взаимодействия. Ваш обработчик прерывания - по сути "асинхронно испольняемый процесс". И только.