attachInterrupt
- Войдите на сайт для отправки комментариев
Пт, 01/03/2019 - 23:33
При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?
А как ещё должно быть? В идеале функция прерывания должна состоять с одной строки.
А потом скетчем обработать.
Вот пример для ESP8266. В свою программу вживлял. Нажимаешь кнопку -меняется флаг. Диод горит. Повторно нажимаешь - меняетс флаг. Диод гаснет.
1
[code]
2
const
byte
interruptPin = D7;
3
volatile
int
flag = 0;
4
void
setup
() {pinMode (D6, OUTPUT);
5
pinMode (interruptPin, INPUT_PULLUP);
6
attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}
7
void
loop
() {digitalWrite (D6, flag);}
8
void
blink () {flag = !flag;}
9
[/code]
Полностью это описано в даташите на микроконтроллер. Если умеете читать, то поймете это достоверно.
Полностью это описано в даташите на микроконтроллер. Если умеете читать, то поймете это достоверно.
Не в обиду, но, нет прямого ответа на прямой вопрос - не#%й флудить. Достали такие умники.
Не в обиду, но, нет прямого ответа на прямой вопрос - не#%й флудить. Достали такие умники.
Да ну, что Вы, кто же на убогих обижается? Или Вы это считаете за вопрос?
При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?
А как ещё должно быть? В идеале функция прерывания должна состоять с одной строки.
А потом скетчем обработать.
Вот пример для ESP8266. В свою программу вживлял. Нажимаешь кнопку -меняется флаг. Диод горит. Повторно нажимаешь - меняетс флаг. Диод гаснет.
1
[code]
2
const
byte
interruptPin = D7;
3
volatile
int
flag = 0;
4
void
setup
() {pinMode (D6, OUTPUT);
5
pinMode (interruptPin, INPUT_PULLUP);
6
attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}
7
void
loop
() {digitalWrite (D6, flag);}
8
void
blink () {flag = !flag;}
9
[/code]
Если брать за пример Ваш код, то после строки
1
attachInterrupt ( digitalPinToInterrupt (interruptPin), blink, RISING);}
переменная flag станет 1 даже при спокойно себе заземлённом пине. У вас так?
Приходится ставить такой вот костыль:
1
...
2
byte
_saval = alarm;
// костыль 1
3
attachInterrupt(0, shock, FALLING);
4
alarm = _saval;
// костыль 2
5
6
....
7
8
void
shock() { alarm |= 1; }
Извини. Нет. Не так. Эта строка вообще не при чём. Функция обработки прерывания - 8 строка.
Мне нельзя тебе, старожилу, замечания делать ... а то будет, как тогда.
P.S. Этот скетч работает на Nodemcu V3 ESP8266 без всяких костылей. Он для демонстрации как работает и настраивается прерывание. А в сетапе и лупе можно добавлять любой нужный код.
vlad072 - вы бы целиком свой код выложили, а не на чужих обрывках что-то показывали. Может там какая простенькая ошибка. А то будет, как в ветке "Оперативка" - мусолили на пустом месте 20 сообщений, умные вопросы про стек задавали - а по факту выяснилось, что вы макроса F() не знаете.
Ну эээ да :) b707 опередил. Накрайняк уж, можно сделать cli() перед ататчем и sei() после и посмотреть результат.
При вызове attachInterrupt функция прерывания отрабатывает. Т.е. в момент активации прерывания оно как бы разово наступает. Так и долно быть, кто знает достоверно?
Если условия для прерывания были выполнены хоть когда-нибудь до его разрешения, то взводится соответствующий флаг и как только прерывание разрешается, то оно и происходит. Что бы этого избежать, надо флаг перед разрешением прерывания сбросить. Какой флаг и как сбрасывать - зависит от конкретного прерывания
Если условия для прерывания были выполнены хоть когда-нибудь до его разрешения, то взводится соответствующий флаг и как только прерывание разрешается, то оно и происходит. Что бы этого избежать, надо флаг перед разрешением прерывания сбросить. Какой флаг и как сбрасывать - зависит от конкретного прерывания
В точку, спасибо. Можно подробней, как сбросить флаги 0-го и 1-го (пины ардуино 2, 3) внешних прерываний atmega368 ?
Не знаю как поступает attachInterrupt, но когда настраиваешь вручную, то сам заботишься о том что бы флаг был сброшен. Если это необходимо. EIFR = 1<<INTF0.
Это Сколковская разработка, секретная. Прочитавшему даташит, в течении пяти лет, запрещено выносить голову из лаборатории.))))
upd atmega328
У Атмег не такая большая линейка, так что легко догадаться что опечатка, и имеется ввиду либо 328 либо 168 что по сути одно и то же, с чем ещё можно спутать?? Но нет же, опять набежали Петросяны которым скучно и понеслась.. На весь топик три ответа по теме, два по делу.. пц...
Это Сколковская разработка, секретная.
"Перед прочтением уничтожить!"
Пишут, что помогает чистка флага EIFR=_BV(INTF0);
Либо использование LOW level на режим обработки прерывания.
Т.е. Вы опечатались, а виноват я - мудак и петросян? Мда, как Вы выражаетесь,
Пишут, что помогает чистка флага EIFR=_BV(INTF0);
Спасибо, нашёл, вдруг кому пригодится:
..как только, вы вызовете функцию attachInterrupt прерывание возникает немедленно, даже если событие произошло час назад. Чтобы избежать этого, вы можете вручную сбросить флаг. Например:
vlad072, EIFR=x это не очень хороший способ сброса флага, т.к. если флага не было - то он установится. Лучше EIFR=EIFR
vlad072, EIFR=x это не очень хороший способ сброса флага, т.к. если флага не было - то он установится. Лучше EIFR=EIFR
Да, кстати, вот что не понятно. При возникновении прерывания соответствующие флаги EIFR устанавливаются в 1. Что бы их сбросить, нужно их опять же установить в 1. Это как? В единицу записываем единицу и получаем 0 ??
vlad072, именно. Ноль туда записать невозможно.
И ещё вопрос. Можно ли использовать аппаратные прерывания вообще без обработчика, просто отвлеживая в цикле соответствующие флаги?
В единицу записываем единицу и получаем 0 ??
И ещё вопрос. Можно ли использовать аппаратные прерывания вообще без обработчика, просто отвлеживая в цикле соответствующие флаги?
Да, если не записывать в регистр PCMSK то прерывание не будет вызвано.
На сколько я понял векторы на ардуино - ноги D2, D3 разрешает регистр EIMSK, а PCMSK использкется для PCINT портов, или я что то путаю?
vlad072, ну да eimsk. psmsk аналогично для групповых прерываний.
Получается и разрешать / запрещать прерывания не к чему, просто когда нам нужно читаем флаги и всё? Естественно если стоит задача просто "не пропустить" перепад уровня на ножке ардуины, а не "отработать немедленно".
Аппаратные прерывания на пинах 2, 3 ардуины использовал для контроля датчика удара. Сделал следующим образом:
01
//.......
02
void
setup
() {
03
DDRD &= ~0x0C; PORTD |= 0x0C; EICRA = 0x0A; EIFR = EIFR;
// D2,D3: input, pullup, falling, reset
04
//...........
05
}
06
void
loop
() {
07
if
( locked ) {
// флаг включённой охранки
08
switch
EIFR {
09
case
1: alarm |= 0x02;
break
;
// сильный удар (тревога)
10
case
2: alarm |= 0x01;
break
;
// слабый удар (предупреждение)
11
case
3: alarm |= 0x02;
12
} EIFR = EIFR;
13
//........
14
}
15
//...........
16
}
Всё "как бы" работает, но вся ардуина превратилась просто в одну "антенну". При касании рукой даже шины питания взводятся оба флага. Подтянул ПИНы к +5 аппаратно резистором (вплоть до 1 кОм) - не помогает. Придавил пины на землю кондёрами по 0.1uF - лучше, но всё равно проблема есть. Кто может предположить, что за чёрт??
наводки
наводки
так это понятно. Но почему то при "классическом" способе слежения за прерываниями c attachInterrupt функции обработки не вызываются от "каждого чиха". Видимо я что то намудрил с флагами не так. Вопрос - что?
Вполне себе вызываются.
Вполне себе вызываются.
В любом случае это должна быть "нифига себе" наводка, как минимум от машины Тесла а не от руки, чтобы довольно короткий провод, подключенный на +5В через резистор 1кОм, преодалев заряд конденсатора в 0.1мкФ даже на пикосекунду сдвинуть в лог. ноль... Чё то не клеится, как электронщик я не могу этого объяснить.
На кой вообще тогда механизм прерываний, если цифровой пин все мизерные наводки собирает?
требования по защите "от руки" весьма немного отличаются "от машины Тесла", так что когда как-то пришлось проходить сертификацию по этому делу, то в качестве тестера выступала пьезозажигалка.
Многие процессорные и плисочные девайсы не выносят ее разряда даже на расстоянии 5-20см, не говоря уж о прямом разряде на замлю платы, а тем более земля -тестовый контакт, но для систем с Touch Memory это просто проза жизни.
ГОСТ есть на стойкость к энергии разрядов, и если в вашей системе есть хоть один проводник для щупанья руками, вы его должны соблюдать в сертифицируемых девайсах.
vlad072, обычно эти явления из-за плохого питания, плохой разводки, земляных петель, из-за отсутствия земли там, где оно должна быть, и.т.п. Возьмите отдельную голую плату ардуино, запитайте её автономно от аккумулятора, залейте этот скетч. Есть эффект ложных срабатываний? Если нет, то подключите ваш бп. Появилось? Если нет, то подключайте что у вас там висит на контроллере. В какой-то момент станет ясно после чего это возникает.
dimax спасибо за конструктивные советы. Видимо дело не в прерываниях а в атмеге вцелом. Просто при "обычных" разовых опросах пинов типа digitalRead подвох практически не проявляется, а когда каждый единычный непроизвольный перепад уровня в любой момент времени неизбежно обнаружится (в случае с прерывниями) - вот они грабли. Пришёл к тому что при использовании прерывний ВСЕ входные пины надо землить через кондёры, ну и конечно питание обвязать по максимуму кондёрами.
Vlad072, от конденсатора на входе тоже есть побочные явления при очень крутых фронтах.
Неиспользуемые входы нужно перевести в output. У STM точно такие же проблемы кстати, так что это лишь высокая чувствительность МК к "игольчатым" помехам. При digitalRead шанс попасть такую помеху крайне мал, так что может показаться что все в порядке
А когда переводишь неиспользуемые порты на вывод лучше делать их High илм Low. И имеет ли смысл завожить их на землю или Vcc?
Конденсаторы конечно нужно выбирать разумно, в зависимости от назначения пина. Поставил на "дубовые кнопочные" и аналоговые входы по 0.47uF, на USART 0.01uF, на "кнопочные" PULLUP по 0.033uF. Неиспользуемых у меня нет ни единого.
А когда переводишь неиспользуемые порты на вывод лучше делать их High илм Low. И имеет ли смысл завожить их на землю или Vcc?
Неиспользуемые я бы всё таки поставил INPUT и завёл прямиком на землю.