Задача для начинающих: коварная ошибка
- Войдите на сайт для отправки комментариев
Давненько я не публиковал учебных задач для начинающих. Вот, держите свежачок.
Эта программа ждёт нажатия на кнопку, подключённую между пином D2 и землёй (дребезг аппаратно подавлен!) и, поймав таковое нажатие, выводит в Serial время этого события.
Код:
static volatile bool buttonState = false; void processButton(void) { buttonState = true; } // // Возвращаем текущее значение buttonState // а саму её делаем false, чтобы не обработать // тоже самое нажатие дважды // static bool isPressed(void) { const bool result = buttonState; buttonState = false; return result; } void setup(void){ Serial.begin(57600); Serial.println("Fun begins!"); pinMode(2, INPUT_PULLUP); attachInterrupt(0, processButton, FALLING); } // // Если клавиша была нажата, печатаем время, // когда мы об этом узнали. // void loop(void) { if (isPressed()) { Serial.print("Button is pressed: "); Serial.println(millis()); } }
Результат:
Fun begins! Button is pressed: 2385 Button is pressed: 2785 Button is pressed: 3184 Button is pressed: 3479 Button is pressed: 3829 Button is pressed: 4177 Button is pressed: 4579 Button is pressed: 4929
Вроде бы, всё нормально, но есть одно «но». Иногда (нечасто) она почему-то пропускает нажатия кнопки. Пропустит и дальше работает как ни в чём не бывало. Попробуйте запустить хоть на железе, хоть в протеусе и пощёлкайте – заметите.
В чём дело? Нет, плата, конечно, китайская и Си нечестный, это понятно. Только ошибка здесь не в плате, а в голове программиста. Найдите и привыкайте видеть такие вещи сразу, при первом взгляде на программу.
Примечание: если будете собирать для пробы в протеусе, то проблем нет, а если в железе, то не забудьте подавить дребезг. Для данной задачи достаточно зашунтировать выводы кнопки конденсатором, скажем в 4,7µF и между кнопкой и пином воткнуть резистор на пару килоом – если кнопка не вдрызг убитая, то никакого дребезга не будет.
Пример был бы нагляднее (ИМХО), если бы время, когда событие может быть пропущено, имело бы большую долю в цикле.
Может ISR Falling поменять на Down? Ибо не всегда будет именно Falling, например при удержании кнопки или "неуспевания" зарядки конденсатора.
Пример был бы нагляднее (ИМХО), если бы время, когда событие может быть пропущено, имело бы большую долю в цикле.
А при чём тут цикл? Пришло прерывание, переменная buttonState стала true и будет таковой оставаться пока до неё isPressed не доберётся. Цикл (в смысле loop) здесь как раз и нужен очень короткий, чтобы невозможно было два раза нажать кнопку за время между обращениями к isPressed. Или я не так понял замечание?
Может ISR Falling поменять на Down? Ибо не всегда будет именно Falling, например при удержании кнопки или "неуспевания" зарядки конденсатора.
Удержание не при делах - мы считаем количество нажатий и плюём на удержание. Так что FALLING - самое то. А время зарядки конденсатора - постоянная времени там менее 10мс - не думаю, что можно успеть дважды нажать кнопку за такое время.
А при чём тут цикл?...
Или я не так понял замечание?
;)) не так понял.
Сейчас так:
Вероятность "осечки" 9%.
Я имел ввиду, что можно было как-то ярче выделить ошибку, чтобы "осечки" были чаще... Но я не придумал - как. Так что мое замечание - чисто демагогическое.
--------------
Так напишу, штоп не портить празднег: между строчкой N и N+1 нужно было бы вставить какой-нибудь осмысленный(якобы) мусор. Тогда осечки были бы чаще.
Странный у тебя ассемблер... ret 4 --- когда это у оператора возврата был параметр? Или может я чо не знаю...
А по поводу тактов в нахождении в процедуре обработчика, вот тут надо подумать. Флаг окончания обработки в регистре флагов от прерываний когда сбрасывается, при входе или при выходе (reti) ??? (я забыл, но по идее должен при выходе из обработчика сбросится на аппаратном уровне, в 328р это 100%) По идее если его (флаг) сбросить в начале обработчика вектора прерывания - будет возможность работы прерывания в прерывании, что, конечно же не жалательно. Так что 9% на "необработку" по причине "занятости" вполне себе может быть.
13, 14 - не обеспечивается атоммарность доступа
13, 14 - не обеспечивается атоммарность доступа
Ну и зачем это было???
Не знаю как Женя, я планировал еще долго издеваться над умниками, а ты мне такую малину прогадил!!!
Мда, мля..., тема привлекла внимание исключительно новичков :(((
Неужели у нас все новички такие, что кроме "дайте готовый код, а книжки я потом изучу" им ни хрена больше не нужно? Ну, не могут же все такими быть - откуда-то же потом вырастают и нормальные люди :(
Не только новички, не только здесь. Любого начальника возьми: "Дыра заткнута? Перебрасываем ресурсы на другое направление".
Странный у тебя ассемблер... ret 4 --- когда это у оператора возврата был параметр? Или может я чо не знаю...
А по поводу тактов в нахождении в процедуре обработчика, вот тут надо подумать. Флаг окончания обработки в регистре флагов от прерываний когда сбрасывается, при входе или при выходе (reti) ??? (я забыл, но по идее должен при выходе из обработчика сбросится на аппаратном уровне, в 328р это 100%) По идее если его (флаг) сбросить в начале обработчика вектора прерывания - будет возможность работы прерывания в прерывании, что, конечно же не жалательно. Так что 9% на "необработку" по причине "занятости" вполне себе может быть.
Вот весь этот поток сознания вспоминай всякий раз, как только тебе захочется сунуть нос в темы, сложнее песочницы.
;))))
Хде?????!!!!!
Думаю, не все, всё-таки. А старожилы ... да, зря сразу всё раскололи - подумать людям не дали :(
Думаю, не все, всё-таки. А старожилы ... да, зря сразу всё раскололи - подумать людям не дали :(
ну я ж написал, что задачку упростить надо было, между... что уж теперь скрывать, 13 и 14 нужно было тебе какой-нить, якобы полезный, счет добавить. Тогда неатомарность сразу бы вылезла.
Не увидят наши дебилы неатомарность, если она в соседних строках, она и в изделии - (9% - помнишь?) будет редко давать глюки, которые наши кулибины спишут на - "платы - гафно китайское!"! ;))
Думаю, не все, всё-таки. А старожилы ... да, зря сразу всё раскололи - подумать людям не дали :(
та чё там думать...прыгать надо, день ВДВ на носу
А как нада?
ишё адин навичёк :-)))
Дак век живи - и дураком помрешь. Который не дальше песочницы. ¦(
Ну, за новичков! (тм)
Я б третью строку со слова inline бы начал и пофиг все не атомарности.
Вот весь этот поток сознания вспоминай всякий раз, как только тебе захочется сунуть нос в темы, сложнее песочницы.
И слава яйцам, шо я ещё раз убедился в "говняности" дурдуинокода и его компилятора. Как так "иногда" процессор может "потерять" значение переменной. Тем более, что на асме это бы заняло всё вместе не более 10 команд и никогда ничего не потерялось.
Вот весь этот поток сознания вспоминай всякий раз, как только тебе захочется сунуть нос в темы, сложнее песочницы.
И слава яйцам, шо я ещё раз убедился в "говняности" дурдуинокода и его компилятора. Как так "иногда" процессор может "потерять" значение переменной. Тем более, что на асме это бы заняло всё вместе не более 10 команд и никогда ничего не потерялось.
Хы хочешь выглядеть еще глупее и еще смешнее? У тебя получается, возможно это талант.
Вот весь этот поток сознания вспоминай всякий раз, как только тебе захочется сунуть нос в темы, сложнее песочницы.
И слава яйцам, шо я ещё раз убедился в "говняности" дурдуинокода и его компилятора. Как так "иногда" процессор может "потерять" значение переменной. Тем более, что на асме это бы заняло всё вместе не более 10 команд и никогда ничего не потерялось.
Значения теряют программисты. Компилятор ни при чем.
Можно отдельную тему создать: "найди ошибку в коде". Для интересных и неочевидных моментов.
Можно. Создай.
Пока ОН не запретил :)
Я б третью строку со слова inline бы начал и пофиг все не атомарности.
ну, пофиг, так пофиг, только нажатия всё равно бы терялись :)))
Кстати, не удивлюсь, если она и так inline (компилятор любит такие шутки).
Для интересных и неочевидных моментов.
Ну, здесь-то момент достаточно очевидный.
wdrakula, а что я говорил!? :)))
Маститые ассембляторы уже начали отмечаться. Скоро должны подойти представители секты СТМ32 и затянуть песню про то, что все проблемы от ногодрыга авровского. Ну, и там еще лямбды нет, как я заметил.
PS. Про эмбеддоров с вертикальным счётчиком забыл. С ним по дефолту все ок будет.
Много раз слышал заявления типа: "говно ваш С, то ли дело асм" и всегда (100% - ни одного исключения!) такие заявления исходили от людей толком не знающих ни Си, ни ассемблера, и, по гамбургскому счёту, не умеющих программировать.
Кстати, не удивлюсь, если она и так inline (компилятор любит такие шутки).
Конечно так и есть. Я же привел код, на исключением всего добра по сериалу и прерываниям, что я убрал, это и есть весь код программы. Само прерывание - отдельно. Это особенность реализации attachInterrupt().
Ну, и там еще лямбды нет, как я заметил.
Чё, правда нет? Как же я мог так облажаться-то? Позор на мою лысину!
Приношу покаянные извинения и исправляюсь:
Скоро должны подойти представители секты СТМ32 и затянуть песню про то, что все проблемы от ногодрыга авровского.
Ну я люблю СТМ32 и ЕСП. Считаю на их фоне АВР - пустой тратой времени... хотя хобби, по-любому - трата времени ;)).
Но можно я про "проблемы ногодрыга" не буду?
Ну, и там еще лямбды нет, как я заметил.
Чё, правда нет? Как же я мог так облажаться-то? Позор на мою лысину!
Приношу покаянные извинения и исправляюсь:
Супер! Хотя вынужден поправить: "The fun begins!"
Много раз слышал заявления типа: "говно ваш С, то ли дело асм" и всегда (100% - ни одного исключения!) такие заявления исходили от людей толком не знающих ни Си, ни ассемблера, и, по гамбургскому счёту, не умеющих программировать.
Я историю этого знаю. Если интересно?
Вкратце это пошло от ПИКов. 20 (может больше, память уже подводит) лет назад компилятор для ПИК был очень слабым и без приличного оптимизатора. Простейшие алгоримы в ПИК не лезли и "тру ембеддеры" вынужденно пользовались ассемблером, который был приличный, с нормальными макросами, "шахматами и пионистками". ;)). Хотя "тру тру" писали в кодах. ;)))))
Но можно я про "проблемы ногодрыга" не буду?
Можно. Я же не зверь какой, чтобы запрещать.
Кстати, вот удивительное дело - два бородатых мужика, работавших на серьёзную организацию, решили что на ассемблере писать утомительно и выковали Си. А сейчас любой водитель кобылы с безаппеляционной уверенностью заявляет, что на ассемблере писать в сто крат легче, чем на нечестном. Ну и далее докУментом машет, рассказывая о том, что он 20 лет руки на клавиатуре держал и кнопка 0 у него пробита до самого пола.
Очень интересная задача! Жалко сразу результат выдали.... ((
Очень интересная задача! Жалко сразу результат выдали.... ((
Ну результат выдали , теперь вопрос "как этих пропусков нажатия избежать ?"
В данном примере, могу предположить - Возможно глупое предположение, но если запретить прерывание перед использованием if в loop и после него разрешить прерывания?
Но я как ученик лишь могу высказаться....
если запретить прерывание перед использованием if в loop и после него разрешить прерывания?
Очень грубо! У Вас программа будет половину времени с закрытми прерываниями работать, если не больше. А они может ещё кому нужны.
Согласно приведенной программы - несколько микросекунд, пока if выполняется. Но вас понял. Надо еще подумать....
Без лямбд.
Да, ну вас всех, блин. Вот все "новички" cj,hfkbcm и навалились :( Чё людЯм подумать-то не даёте? Да и щё и без лямбд :(
В следующий раз выложу задачу для гуру :-)
У меня такая мысль была самой первой, но я предположил, что такое невозможно. Получается такое возможно?....
Да, ну вас всех, блин. Вот все "новички" cj,hfkbcm и навалились :( Чё людЯм подумать-то не даёте? Да и щё и без лямбд :(
В следующий раз выложу задачу для гуру :-)
Не, надо честно - надо две задачи. Одна для гуру, другая для начинающих. Гуру в решение задачи начинающих "лезть" нельзя, а начинающим попробовать свои силы в задаче гуру можно. Вот так справедливее будет. Не? )
Без лямбд.
Ну зачем _все_ прерывания запрещать? Достаточно INT0 запретить.
)) Лишние телодвижения.
Да, ну вас всех, блин. Вот все "новички" cj,hfkbcm и навалились :( Чё людЯм подумать-то не даёте? Да и щё и без лямбд :(
В следующий раз выложу задачу для гуру :-)
"А чё тут думать", после того как Komandir указал на атомарность в 13, 14!)