attachInterrupt

vlad072
Offline
Зарегистрирован: 01.08.2017

При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

А как ещё должно быть? В идеале функция прерывания должна состоять с одной строки.

А потом скетчем обработать.

Вот пример для ESP8266.  В свою программу вживлял. Нажимаешь кнопку -меняется флаг. Диод горит. Повторно нажимаешь - меняетс флаг. Диод гаснет. 

[code]
const byte interruptPin = D7;
volatile int flag = 0;
void setup() {pinMode (D6, OUTPUT);
pinMode (interruptPin, INPUT_PULLUP);
attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}
void loop() {digitalWrite (D6, flag);}
void blink () {flag = !flag;}
[/code]

 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Полностью это описано в даташите на микроконтроллер. Если умеете читать, то поймете это достоверно.

vlad072
Offline
Зарегистрирован: 01.08.2017

mykaida пишет:

Полностью это описано в даташите на микроконтроллер. Если умеете читать, то поймете это достоверно.

Не в обиду, но, нет прямого ответа на прямой вопрос - не#%й флудить. Достали такие умники.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

vlad072 пишет:

Не в обиду, но, нет прямого ответа на прямой вопрос - не#%й флудить. Достали такие умники.

Да ну, что Вы, кто же на убогих обижается? Или Вы это считаете за вопрос?

vlad072 пишет:

При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?

 

vlad072
Offline
Зарегистрирован: 01.08.2017

Муж_Долговой пишет:

А как ещё должно быть? В идеале функция прерывания должна состоять с одной строки.

А потом скетчем обработать.

Вот пример для ESP8266.  В свою программу вживлял. Нажимаешь кнопку -меняется флаг. Диод горит. Повторно нажимаешь - меняетс флаг. Диод гаснет. 

[code]
const byte interruptPin = D7;
volatile int flag = 0;
void setup() {pinMode (D6, OUTPUT);
pinMode (interruptPin, INPUT_PULLUP);
attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}
void loop() {digitalWrite (D6, flag);}
void blink () {flag = !flag;}
[/code]

Если брать за пример Ваш код, то после строки

attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}

переменная flag станет 1 даже при спокойно себе заземлённом пине. У вас так?

Приходится ставить такой вот костыль:

...
byte _saval = alarm; // костыль 1
attachInterrupt(0, shock, FALLING);
alarm = _saval; // костыль 2

....

void shock() { alarm |= 1; }

 

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Извини. Нет. Не так. Эта строка вообще не при чём. Функция обработки прерывания - 8 строка.

Мне нельзя тебе, старожилу, замечания делать ... а то будет, как тогда.

P.S. Этот скетч работает на Nodemcu V3 ESP8266 без всяких костылей. Он для демонстрации как работает и настраивается прерывание. А в сетапе и лупе можно добавлять любой нужный код.

b707
Offline
Зарегистрирован: 26.05.2017

vlad072 - вы бы целиком свой код выложили, а не на чужих обрывках что-то показывали. Может там какая простенькая ошибка. А то будет, как в ветке "Оперативка" - мусолили на пустом месте 20 сообщений, умные вопросы про стек задавали - а по факту выяснилось, что вы макроса F() не знаете.

negavoid
Offline
Зарегистрирован: 09.07.2016

Ну эээ да :) b707 опередил. Накрайняк уж, можно сделать cli() перед ататчем и sei() после и посмотреть результат.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

vlad072 пишет:

При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?

 

Если условия для прерывания были выполнены хоть когда-нибудь до его разрешения, то взводится соответствующий флаг и как только прерывание разрешается, то оно и происходит. Что бы этого избежать, надо флаг перед разрешением прерывания сбросить. Какой флаг и как сбрасывать - зависит от конкретного прерывания

vlad072
Offline
Зарегистрирован: 01.08.2017

asam пишет:

Если условия для прерывания были выполнены хоть когда-нибудь до его разрешения, то взводится соответствующий флаг и как только прерывание разрешается, то оно и происходит. Что бы этого избежать, надо флаг перед разрешением прерывания сбросить. Какой флаг и как сбрасывать - зависит от конкретного прерывания

В точку, спасибо. Можно подробней, как сбросить флаги 0-го и 1-го (пины ардуино 2, 3) внешних прерываний atmega368 ?

Green
Онлайн
Зарегистрирован: 01.10.2015

Не знаю как поступает attachInterrupt, но когда настраиваешь вручную, то сам заботишься о том что бы флаг был сброшен. Если это необходимо. EIFR = 1<<INTF0.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vlad072 пишет:
atmega368 ?
Дайте, пожалуйста, ссылку на даташит, а то я не могу найти.

bwn
Offline
Зарегистрирован: 25.08.2014

ЕвгенийП пишет:

vlad072 пишет:
atmega368 ?
Дайте, пожалуйста, ссылку на даташит, а то я не могу найти.

Это Сколковская разработка, секретная. Прочитавшему даташит, в течении пяти лет, запрещено выносить голову из лаборатории.))))

vlad072
Offline
Зарегистрирован: 01.08.2017

upd atmega328

У Атмег не такая большая линейка, так что легко догадаться что опечатка, и имеется ввиду либо 328 либо 168 что по сути одно и то же, с чем ещё можно спутать?? Но нет же, опять набежали Петросяны которым скучно и понеслась.. На весь топик три ответа по теме, два по делу.. пц...

Green
Онлайн
Зарегистрирован: 01.10.2015

bwn пишет:

Это Сколковская разработка, секретная.

"Перед прочтением уничтожить!"

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Пишут, что помогает чистка флага EIFR=_BV(INTF0);

Либо использование LOW level на режим обработки прерывания.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vlad072 пишет:
опять набежали Петросяны которым скучно и понеслась.. На весь топик три ответа по теме, два по делу.

Т.е. Вы опечатались, а  виноват я - мудак и петросян? Мда, как Вы выражаетесь, 

vlad072 пишет:
...пц...

vlad072
Offline
Зарегистрирован: 01.08.2017

AlexanderNO пишет:

Пишут, что помогает чистка флага EIFR=_BV(INTF0);

Спасибо, нашёл, вдруг кому пригодится:

..как только, вы вызовете функцию attachInterrupt прерывание возникает немедленно, даже если событие произошло час назад. Чтобы избежать этого, вы можете вручную сбросить флаг. Например:

 

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vlad072, EIFR=x   это не очень хороший способ сброса флага, т.к. если флага  не было - то он установится.  Лучше EIFR=EIFR

vlad072
Offline
Зарегистрирован: 01.08.2017

dimax пишет:

vlad072, EIFR=x   это не очень хороший способ сброса флага, т.к. если флага  не было - то он установится.  Лучше EIFR=EIFR

Да, кстати, вот что не понятно. При возникновении прерывания соответствующие флаги EIFR устанавливаются в 1. Что бы их сбросить, нужно их опять же установить в 1. Это как? В единицу записываем единицу и получаем 0 ??

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vlad072, именно. Ноль туда записать невозможно.

vlad072
Offline
Зарегистрирован: 01.08.2017

И ещё вопрос. Можно ли использовать аппаратные прерывания вообще без обработчика, просто отвлеживая в цикле соответствующие флаги?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vlad072 пишет:

В единицу записываем единицу и получаем 0 ??

"Есть многое на свете, друг Горацио
Что и не снилось нашим мудрецам"
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vlad072 пишет:

И ещё вопрос. Можно ли использовать аппаратные прерывания вообще без обработчика, просто отвлеживая в цикле соответствующие флаги?

Да, если не записывать  в регистр PCMSK то прерывание не будет вызвано.

vlad072
Offline
Зарегистрирован: 01.08.2017

На сколько я понял векторы на ардуино - ноги D2, D3 разрешает регистр EIMSK, а PCMSK использкется для PCINT портов, или я что то путаю?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vlad072, ну да eimsk. psmsk аналогично для групповых прерываний.

vlad072
Offline
Зарегистрирован: 01.08.2017

Получается и разрешать / запрещать прерывания не к чему, просто когда нам нужно читаем флаги и всё? Естественно если стоит задача просто "не пропустить" перепад уровня на ножке ардуины, а не "отработать немедленно".

vlad072
Offline
Зарегистрирован: 01.08.2017

Аппаратные прерывания на пинах 2, 3 ардуины использовал для контроля датчика удара. Сделал следующим образом:

//.......
void setup() {
  DDRD &= ~0x0C; PORTD |= 0x0C; EICRA = 0x0A; EIFR = EIFR; // D2,D3: input, pullup, falling, reset
//...........
}
void loop() {
  if ( locked ) { // флаг включённой охранки
    switch EIFR {
      case 1: alarm |= 0x02; break; // сильный удар (тревога)
      case 2: alarm |= 0x01; break; // слабый удар (предупреждение)
      case 3: alarm |= 0x02;
    } EIFR = EIFR;
    //........
  }
  //...........
}

Всё "как бы" работает, но вся ардуина превратилась просто в одну "антенну". При касании рукой даже шины питания взводятся оба флага. Подтянул ПИНы к +5 аппаратно резистором (вплоть до 1 кОм) - не помогает. Придавил пины на землю кондёрами по 0.1uF - лучше, но всё равно проблема есть. Кто может предположить, что за чёрт??

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

наводки

vlad072
Offline
Зарегистрирован: 01.08.2017

ua6em пишет:

наводки

так это понятно. Но почему то при "классическом" способе слежения за прерываниями c attachInterrupt функции обработки не вызываются от "каждого чиха". Видимо я что то намудрил с флагами не так. Вопрос - что?

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Вполне себе вызываются.

vlad072
Offline
Зарегистрирован: 01.08.2017

sadman41 пишет:

Вполне себе вызываются.

В любом случае это должна быть "нифига себе" наводка, как минимум от машины Тесла а не от руки, чтобы довольно короткий провод, подключенный на +5В через резистор 1кОм, преодалев заряд конденсатора в 0.1мкФ даже на пикосекунду сдвинуть в лог. ноль... Чё то не клеится, как электронщик я не могу этого объяснить.

На кой вообще тогда механизм прерываний, если цифровой пин все мизерные наводки собирает?

ВН
Offline
Зарегистрирован: 25.02.2016

vlad072 пишет:
В любом случае это должна быть "нифига себе" наводка, как минимум от машины Тесла а не от руки ...

требования по защите  "от руки" весьма немного отличаются "от машины Тесла", так что когда как-то пришлось проходить сертификацию по этому делу, то в качестве тестера выступала пьезозажигалка.

Многие процессорные и плисочные девайсы не выносят ее разряда даже на расстоянии 5-20см, не говоря уж о прямом разряде на замлю платы, а тем более земля -тестовый контакт, но для систем с  Touch Memory это просто проза жизни.

ГОСТ есть на стойкость к энергии разрядов, и если в вашей системе есть хоть один проводник для щупанья руками, вы его должны соблюдать в сертифицируемых девайсах.

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

vlad072, обычно эти явления из-за плохого питания, плохой разводки, земляных петель, из-за отсутствия земли там, где оно должна быть, и.т.п. Возьмите отдельную голую плату ардуино, запитайте её автономно от аккумулятора, залейте этот скетч. Есть эффект ложных срабатываний? Если нет, то подключите ваш бп. Появилось? Если нет, то подключайте что у вас там висит на контроллере. В какой-то момент станет ясно после чего это возникает.

vlad072
Offline
Зарегистрирован: 01.08.2017

dimax спасибо за конструктивные советы. Видимо дело не в прерываниях а в атмеге вцелом. Просто при "обычных" разовых опросах пинов типа digitalRead  подвох практически не проявляется, а когда каждый единычный непроизвольный перепад уровня в любой момент времени неизбежно обнаружится (в случае с прерывниями) - вот они грабли. Пришёл к тому что при использовании прерывний ВСЕ входные пины надо землить через кондёры, ну и конечно питание обвязать по максимуму кондёрами.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Vlad072, от конденсатора на входе тоже есть побочные явления при очень крутых фронтах.
Неиспользуемые входы нужно перевести в output. У STM точно такие же проблемы кстати, так что это лишь высокая чувствительность МК к "игольчатым" помехам. При digitalRead шанс попасть такую помеху крайне мал, так что может показаться что все в порядке

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А когда переводишь неиспользуемые порты на вывод лучше делать их High илм Low. И имеет ли смысл завожить их на землю или Vcc?

vlad072
Offline
Зарегистрирован: 01.08.2017

dimax пишет:
Vlad072, от конденсатора на входе тоже есть побочные явления при очень крутых фронтах. Неиспользуемые входы нужно перевести в output.

Конденсаторы конечно нужно выбирать разумно, в зависимости от назначения пина. Поставил на "дубовые кнопочные" и аналоговые входы по 0.47uF, на USART 0.01uF, на "кнопочные" PULLUP по 0.033uF. Неиспользуемых у меня нет ни единого.

vlad072
Offline
Зарегистрирован: 01.08.2017

asam пишет:

А когда переводишь неиспользуемые порты на вывод лучше делать их High илм Low. И имеет ли смысл завожить их на землю или Vcc?

Неиспользуемые я бы всё таки поставил INPUT и завёл прямиком на землю.