Внутренние прерывания

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

на коленке != кривой симулятор.  сколько остается времени на хоби, столько и трачу. извените что не имею больше.

сорри перед другими участниками форума за флуд не по теме

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

На железе так не могло быть. И пуллап не при делах. У меня его нет, а никакие глюки не лезут.

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

снять видео чтоб вы поверили??

PS: так что медальку можете забрать себе и еще про Фому прицепить ;)

Green
Offline
Зарегистрирован: 01.10.2015

Проверил на железе.) Даже в таком виде у меня LED не загорается. Но. Загорается если в начало setup() добавить хотя бы одну команду настройки пина. Любого. Я настраивал 4-й на вывод. Вот это непонятно... 
 

const int btPin  = 2;                   //int0!
const int ledPin = 13;


void setup()
{
  pinMode(btPin, INPUT_PULLUP);         //INT0 pullup
  pinMode(ledPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(btPin), pinChange, CHANGE);
}


void loop()
{
}


void pinChange()
{
  digitalWrite(ledPin, true);
}

Но, если перед аттачем поставить сброс флага прерывания EIFR = 1<<INT0, то всё ОК - LED не загорается!
Загорается только при подаче нуля на 2-й пин, как и должно быть.
Вот и верь после этого людям!)

Green
Offline
Зарегистрирован: 01.10.2015

Получается, что флаг устанавливается если до включения подтяжки выполнить операцию с портом. Если же с другим портом или после подтяжки - тогда без разницы, флаг не устанавливается.
В любом случае, сброс флага ПЕРЕД аттачем решает все проблемы. Сам аттач на флаг влияния не оказывает.  У меня так.

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

Green, а если с внутренней подтяжкой, и посаженным на "+"  входом прерывания?

Green
Offline
Зарегистрирован: 01.10.2015

Без разницы - что на железный +, что на железный общий(. Заметил, что когда кнопка ко 2-му пину не подключена совсем (20 см провод), даже pinMode(4, OUTPUT) перед подтяжкой влияния не оказывает.) В общем, дурные эксперименты. Нужно сбрасывать флаг перед аттачем и ниочём не думать.)

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

Стало любопытно, сам попробывал. Полную ясность внесла осциллограмма

void setup()
{
pinMode(12, OUTPUT);
pinMode(ledPin, OUTPUT);
PORTB=255;
pinMode(btPin, INPUT_PULLUP);         //INT0 pullup
PORTB=0;
attachInterrupt(digitalPinToInterrupt(btPin), pinChange, CHANGE);
}

Сделал импульс с началом перед пуллапом, и концом после него. На картинке синим -импульс с 12 ноги, жёлтым сигнал на 2 ноге.

Как видно по картинке - из-за входной ёмкости МК  уровень на 2 пине просто не успевает вырости до нужной величины, поэтому следом идущий attachInterrupts ловит восходящий фронт. Стало быть после Pull_Up нужно ставить delay(), что б к началу следующей команды напряжение достигло нужной величины.

PS: и видимо из-за той же ёмкости напряжение на входе достигает в пике 6,5 вольт, что наверное тоже не полезно и может давать глюки. Вторую картинку вставлять не буду, там жёлтая линия очень плавно (~200µS) возвращается к уровню 5 вольт.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

alexbmd пишет:

я пишу с трех разных компов и двух телефонов.

Не надо так писать.

Пишите только с того компа, к которому подключена (или есть возможность вот прямо сейчас подключить) Ардуина.

 

PS. А писать на этот форум с телефона - вообще mauvais ton.

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

alexbmd пишет:

я пишу с трех разных компов и двух телефонов. 

Ну, потому я Вас медалью за вынос мозга и наградил.

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

dimax пишет:

alexbmd, 12 строка - внутренний Pull_Up не гарантирует, что вход прерывания не попытается принимать "радиосигнал с марса" ) Повторите эксперимент с жёстко соединённым входом к земле или питанию.

проверил. занчит пулап внутрений даже если через cli-sei всеравно раз срабатывает. пока флаг не сбросишь и именно после атача. тк до атача там просто нечего сбрасывать. непонимаю как у Грина флаг подымается до атача.

железные пулап/пулдаун не срабатывают как вы и говорили.

 

  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
    delay(4000);
  cli();
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
  sei();

сделал с задержкой как вы говорили всеравно выскакивает

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

alexbmd, значит не только отставание фронта виновато, есть ещё какая то неведомая аппаратная особенность 8-\

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

тфьу блин. все прозаичней. баг монитора.

если открываешь монитор то и флаг появляется. если не открываешь то нет :)

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

Я не успокоился и стал экспериментировать  дальше. Выяснились любопытные вещи -на  входе прерываний INT0/1 стоит некий аппаратный триггер. Сразу после старта МК он начинает следить за состоянием входов, и если что-то там произошло,  то он это запоминает, и  ставит флажок в EIFR, но тут самые чудеса -этот флажок не читается, но он там есть! Поэтому как только мы запрограммируем EICRA и EIMSK то тотчас срабатывает прерывание.

Теперь понятно почему с внешним pull_up не было ложного срабатывания - напряжение на входе на момент старта МК _уже_ было, поэтому триггер не записал событие. А когда мы подаём напругу после старта МК (не важно внутренней подтяжкой или внешней) -то событие запишется, и позже сработает, если будет разрешено прерывание.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Т.е. для недопущения "прерывания по включению" надо ненадолго придерживать старт МК и юзать внешнюю подтяжку?

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

sadman41,  ну или отчистить EIFR перед записью в EICRA/EIMSK.

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

dimax я что-то не понял, откуда на 2 ноге 6,5 вольт берутся?

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

asam пишет:

dimax я что-то не понял, откуда на 2 ноге 6,5 вольт берутся?

видимо заряд-разряд ёмкости

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

dimax так то оно так, но если не открывать монитор (пусть он даже будет настроен но не открывать) то флаг не взводиться. во всяком случае у меня. интересно девки пляшут.

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

dimax пишет:

Посомтрел из любопытства что делается в прерывании :


<__vector_1>:        
                


 

правильно я понимаю что перед заходом в ISR выполняется cli() а при выходе sei()/reti() ?

ISR(){ //условно тут cli()
..
} //условно тут sei()

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

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

DetSimen пишет:

 если они нужны

если они нужны внутри обработчика я так пониаю?

 

ну я больше не про включение спрашивал а про отключение.

т.к. я для перестраховки делал

ISR(){
cli(); //так делать не надо
flag = 1;
}

loop(){

if (flag){ sei();
..work..
}

}

вопрос _снимается_. как минимум внутри ISR незачем их отключать / включать повторно вручную. 

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

помещение sei() в loop это какая-то ересь, это убивает весь смысл прерываний. как мне кажется

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

для критикал кода это не ересь, и для неатомарных инструкций тоже нужен и cli() и sei() в лупе.

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

alexbmd пишет:

для критикал кода это не ересь, и для неатомарных инструкций тоже нужен и cli() и sei() в лупе.

Подобный бред я слышал от Вас три года назад. Вы тогда тоже лепили cli в луп и очень удивлялись, почему millis не работает. Неужели, Вы с тех пор так ничему и не научились?

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

Объясните это Нику Г http://www.gammon.com.au/interrupts

[можно не цитировать, отвечая следующим сообщением]

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

alexbmd пишет:

Объясните это Нику Г http://www.gammon.com.au/interrupts

Зачем мне ему объяснять? Он же не выносил мозг форуму, "почему for не работает?". Это Вы выносили. Не он виноват, что Вы вырвали фразу из контекста, которого не поняли, и стали применять там, где это неприменимо.

alexbmd пишет:

[можно не цитировать, отвечая следующим сообщением]

Не учите меня жить, пожалуйста.

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

вам виднее

1. если у вас плохое настроение не обязательно его срывать на мне
2. если вам не нравиться что на форуме задают вопросы вы знаете что делать

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

alexbmd пишет:
если вам не нравиться что на форуме задают вопросы

Отнюдь! Моя реакция была вовсе не на вопрос, а на утверждение из поста #174., в котором Вы решили поучить b707.

Да, мне не нравится, когда такие вещи утверждаются на форуме. И да, Вы правы, я знаю, что делать.

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

во первых я ни кого не учил. во вторых что прочитал то и рассказал. и я полностью согласен с прочитанным. во множестве дисскусий и статьях как у Ника так и у других знающих дядек используеться noInterrupts/Interrupts  в лупе.  В даташите avr тоже используется. не говоря уже про millis/serial и т.д.

зная как вы любите выдерать из контекста  - используется это не значит что каждый прогон лупа оно выключает /включает. А можно и каждый через if

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

Отнюдь. у вас реакция на вопросы всегда одна

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

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

Подобный бред я слышал от Вас три года назад. Вы тогда тоже лепили cli в луп и очень удивлялись, почему millis не работает. Неужели, Вы с тех пор так ничему и не научились?

о, это сильно.  Можно только позавидовать упорству... Обычно, если у человека что-то не идет, например нет способностей к программированию - максимум полгода и все, бросил. А тут три года без малейшего прогресса - а человек не сдается

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

b707 пишет:

помещение sei() в loop это какая-то ересь, это убивает весь смысл прерываний. как мне кажется

Помещение sei() в  лупе смысл прерываний никак не убиват. В большинстве случаев (99.999 %) это просто ни на что не влияет. Обычно, прерывания в loop  итак разрешены, и повторное разрешениние ничего не портит, но и смысла не имеет.

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

полностью согласен с предыдущим оратором.

а в случае банальной проверки не атомарной волативной переменной даже необходимо cli/sei а есть и другие ведь сценарии

Евгений -  я слышал от Вас три года назад. мне почемуто не было интересно смотреть ваш профиль. а вам смотрю нравитца копаться в грязном белье

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

умные дядьки пишут

    cli();
    PORTD = (PORTD & maskD) | valD;
    sei();

 

к ктото тут считает это ересью :)

sadman41
Offline
Зарегистрирован: 19.10.2016

Ересь - это делать atomic там, где этого не нужно. Тут же, у дядек, всё к месту.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

alexbmd пишет:

умные дядьки пишут

    cli();
    PORTD = (PORTD & maskD) | valD;
    sei();

 

к ктото тут считает это ересью :)

А алкашня пишет так: 

uint8_t  sreg = SREG;
cli();
PORTD = ......
SREG = sreg; 

 

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

DetSimen про это я и имел ввиду говоря выше про милис. суть одна. А также:

    In order to implement atomic access to multi-byte objects use cli() and sei(). 
alexbmd
Offline
Зарегистрирован: 15.01.2016

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

alexbmd пишет:

    In order to implement atomic access to multi-byte objects use cli() and sei(). 

Не слушай, матьтваю, таких советчиков.  А если, по каким-то причинам прерывания УЖЕ были до этого запрещены?  И ты их на выходе из своего блока ничтоже сумняшеся разрешаешь?  Чо будет, БАДАБУМ? 

Я ж тебе привел код, где при входе в свой блок, ты запоминаешь SREG (вместе с флагом IF, матьтваю), потом запрещаешь прерывания на время работы критического блока, а потом ВОССТАНАВЛИВАЕШЬ прерывания КАК БЫЛИ, вместе с флагом IF регистра флагов.   Чувствуешь разницу?  Всегда разрешаешь, или восстанавливаешь как были. А? 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если бы все проходили мимо, то ты бы до сих пор сидел с застывшим millis() в лупе. Да и форум был бы золотым, если бы почаще вопрошающие не мнили себя senior developer, у которого, например, канпилятор ошибается и поэтому ничего не работает. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

да, блин, понарожают сеньоров... 

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

alexbmd пишет:

Отнюдь. у вас реакция на вопросы всегда одна

Мы сейчас обсуждаем моё всегдашнее поведение или в данном конкретном случае? В данном случае реакция была не на вопрос, а на утверждение.p;

alexbmd пишет:

и я полностью согласен с прочитанным.

Да, это-то я вижу. только вот ещё вижу, что Вы не поняли прочитанного. Дело Ваше, когда, ещё через три года, у Вас опять for не будет работать, мы вернёмся к этому разговору.

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

DetSimen пишет:

Не слушай, матьтваю, таких советчиков.  А если, по каким-то причинам прерывания УЖЕ были до этого запрещены?  И ты их на выходе из своего блока ничтоже сумняшеся разрешаешь?  Чо будет, БАДАБУМ? 

по каким таким причинам ?

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

если такие вводные то да наверно единственный путь через SREG

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

и это Ник советовал если что :) и Дейв

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А своя голова нашто?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

всё. наданапицца. 

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

темболее тяпница :)

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

dimax пишет:

 У флаговых регистров AVR два основных принципа: - (1)он принимает только запись единицы, а на запись ноля не реагирует. (2) При записи в флаговый регистр единицы происходит инверсия содержимого. 

0 + 1 = 1

1 + 1 =0

вот первый сценарий (0+1) я попробовал (не давал он мне покоя) повторить. как только не пробовал. и орами (|=) и не орами (=) и срегами и магией, не говоря уже про нули и единицы. ничего не выходит. а это вообще возможно ?

пока только получалось завести фланг железно т.е. чтоб сработал EICRA. и дальше любая запись =EIFR |=1 =1 обнуляет. 

когда там ноль вручню ну никак не пишется туда. получается нам вообще не важно есть там флаг нету (я сейчас не про обработчик а про надежный/безопасный clear) если нам надо его обнулить тупо пишем (не важно как) туда единицу. он в любом случае обнулиться.

nik182
Offline
Зарегистрирован: 04.05.2015

Слушай. Какие сценарии, какие пробовал? Есть мануал на МК. В нем четко прописана процедура. Учи английский, открывай мануал и читай. Для 328 это пункт 12.2.3. Там написано что этот флаг снимается при выполнении прерывания, альтернативно при записи единицы в бит. Единицу можно записать разными способами. Запись нуля ничего не делает. Что можно альтернативного получить дергая процессор разными сценариями, кроме подтверждения информации из мануала?