|
|
|
|
Для составления графа сначала требуется понять, в каких состояниях может находиться автомат. Сосчитать эти состояния и присвоить им номера (или условные названия). Потом изобразить на листке бумаги, а лучше в чертежной программе типа Visio, все эти состояния в виде кружков с цифирками (или названиями) внутри. Затем продумать - из какого состояния в какие другие состояния возможны переходы. Изобразить эти переходы стрелками. Вот скелет уже вырисовался. Далее разобраться - при каких условиях эти переходы должны происходить. Нанести эти условия на граф. И напоследок уяснить - какие действия должны происходить при каждом переходе из состояния в состояния. Также нанести их на граф. Сложно? Вообще-то да, с непривычки дьявольски сложно. Это творчество. Зато в процессе составления графа выясняется множество скрытых "подводных камней" и неявно заданных условий. Имея перед глазами грамотно составленный граф, составлять алгоритм уже значительно легче. Все состояния, переходы, условия и действия уже видны. А писать код по составленному алгоритму - это, как я уже говорил, ремесло. Достаточно раз приобрести навык - и всё, дальше работа довольно однообразная. |
|
|
От себя могу сказать только, что рисовать граф или нет, составлять блок-схему или нет - это очень индивидуально, всё зависит от образа мышления конкретного человека. Сам никогда не составлял ни того ни другого при написании реальных программ, а занимаюсь этим с 89-го года (не контроллеров) и на разных языках. И для себя не вижу необходимости в их составлении. Но возможно кому-то это даёт возможность представить работу программы, в этом случае конечно составление графа или блок-схемы может оказать помощь. Если же человек может пользоваться языком "без словаря", то, думаю, заставлять его читать по слогам нет необходимости. У каждого свой подход и от этого никуда не деться. |
|
|
Я вот еще насчет дребезга контактов. Не совсем понимаю. Поэтому прошу помочь разобраться. Мой ход мысли такой. Что такое дребезг? Попытаюсь дать определение. В момент нажатия кнопки какое-то время присутствует периодически возникающий и исчезающий контакт. Через время порядка 50 мс контакт становится постоянным. Так?... В чем опасность? Мне думается, что опасность в том, что система может воспринять дребезг, как многократное нажатие кнопки, но только в том случае, если скорость программной обработки этого нажатия достаточна для того, чтобы осуществить нежелательные процедуры. Например, однократное нажатие на клавишу клавиатуры приводит к появлению нескольких повторяющихся символов. Если это так, то да, нужна какая-то защита от дребезга. Но рассмотрим данный случай (нашу задачу). У нас (точнее в моей программе ) опрос состояния кнопок происходит очень быстро. Период опроса составляет несколько микросекунд. При нажатии кнопки (пусть с дребезгом) рано или позно опрос фиксирует наличие нуля. После этого начинает выполняться сценарий, соответствующий нажатию этой кнопки. Сценарий длится около 1.5 секунд! Во время работы программы по этому сценарию опроса кнопок не происходит. Техническое задание гласит, что "бегущий огонь" должен добежать до конца! Использовать промежуточный опрос или прерывание по нажатию бессмысленно! И лишь по окончанию сценария происходит повторный опрос кнопок. Но теперь, одно из двух. Либо дребезг уже прекратился по определению самого понятия дребезга, которое я попытался сформулировать вначале, либо кнопка уже отпущена! Вот и спрашивается, в чем здесь мое заблуждение? Где ошибка в рассуждениях? Теперь рассмотрим другую ситуацию. Одну кнопку мы уже держим и удерживаем, а другую нажимаем. По условию задачи (хоть это и не прописано в задании явно, отдельным пунктом) должен закончиться предыдущий сценарий (бегущий огонь должен добежать до конца), и только после этого должны загореться два средних светодиода. Время дребезга 50 мс по сравнению с временем опроса кнопок 1.5 сек (а ведь именно такое время опроса при удерживании одной кнопки) очень малО, и маловероятно, что дребезг здесь тоже может повредить. Хотя существует вероятность, равная 50мсек/1.5 сек = 1/30, что момент нажатия совпадет с моментом опроса кнопок, и вот тут, да, дребезг может вызвать нежелательное явление, заключающееся в том, что сценарий пойдет по пути обработки двух нажатых кнопок. А в этом сценарии в моей программе опрос кнопок тоже быстрый (несколько микросекунд). Поэтому во втором или любом из последущих опросов мы можем нарваться на дребезг вновь нажатой кнопки, который еще продолжается, и сценарий опять уйдет в длительную ветку обработки одной нажатой кнопки. И это будет настоящий нежелательный сбой. Но это решается в моей программе достаточно просто. Достаточно сделать период опроса кнопок при одновременном нажатии двух кнопок больше 100 мсек (ввести программную задержку) и вроде как проблемма решается. Так или не так? Проясните, если можно. Я ж говорил, ну недопонимаю я что-то с этим дребезгом. Когда нужна защита, когда нет? А тут еще этот анализ дребезга надо как-то в граф встраивать. О' ужас! Или наплевать на все логические рассуждения, и делать защиту всегда, не задумываясь? А при написании программ на Си, например, тоже нужно графы рисовать? Боюсь, что эти графы с князьями отобьют у меня всю охоту. |
|
|
Так вот насчет дребезга я точно так же думаю, что в большинстве проблема на пустом месте создается. Мне кажется, что это от дискретной логики пошло - например, кнопка подключена ко входу счетчика - вот там надо принимать аппаратные меры - чтобы инкремент происходил строго по числу четких нажатий кнопки. Что же касается МК, то обычной паузы хватает. А если нам не нужны многократные повторения команды - можно просто ставить флаг - нажато-отпущено. С уважением, Николай. |
|
|
В этом устройстве нам не столько дребезг мешает, сколько возможные помехи. Ещё раз повторяю - устройство не должно реагировать на нажатие кнопки длительностью менее 100 мс из исходного состояния!!! Иначе любая помеха по входу будет приводить к ложному запуску. Вот для отстройки от помех и служат антидребезговые паузы. Запуск должен происходить не по факту нажатия на кнопку, а по факту удержания кнопки более 100 мс. Рисовать ли граф, составлять ли алгоритм - каждый решает для себя сам. Я считаю, что потраченные на это время и усилия впоследствии окупятся. И чем сложнее устройство - тем больше выигрыш от их составления. И это не только моё мнение. Посмотрите любую книгу или статью о проектировании микроконтроллерных устройств. |
|
|
picmaniac: В этом устройстве нам не столько дребезг мешает, сколько возможные помехи. Ещё раз повторяю - устройство не должно реагировать на нажатие кнопки длительностью менее 100 мс из исходного состояния!!! Если так, тогда все понятно. Задание есть задание. Будем делать строго по заданию. Но, абстрагируясь от данного задания, хочу все-таки понять, почему подобную защиту называют антидребезговой? Почему не назвать ее антипомеховой. И еще. Помеха - наводимая? Т. е. при приближении руки к кнопке фон индустриальной частоты через емкость может проникнуть в цепь управления? Еще. Надо ли делать подобную защиту и в других входных высокоомных цепях МК? Ведь туда тоже может навестись помеха. Я понимаю, что все эти дела - на совести разработчика, но все-таки, как положено? Т.е. опять же встает этот дурацкий сакраментальный вопрос, где нужна защита от дребезга (наводок), а где нет? Просто в голове сидит клином схема классической антидребезговой защиты на RS триггере и двух кнопках, обмусоленная везде, где только можно. Ведь эта защита не только не спасает от помех, но и провоцирует ложное срабатывание триггера от любой наводки? Николай Брагин: А если нам не нужны многократные повторения команды - можно просто ставить флаг - нажато-отпущено. А это как? |
|
|
Назвать можем как угодно. Что дребезг, что помехи - нам без разницы. Дребезг - это в общем-то тоже своеобразная "помеха". Один или несколько импульсов (в данном случае отрицательных, т.к. подтяжка к шине питания) на входе за промежуток менее 100 мс мы считаем помехой. От неё и предстоит отстраиваться. Источник помехи не имеет значения для программиста - будь это дребезг, наводки или происки инопланетян. |
|
|
Классически часть Вашей программы (и про дребезг) решается так: В нормальной микроконтроллерной системе всегда предусматривается внутреннее прерывание по таймеру. Период этого прерывания выбирается из максимально допустимого времени реагирования системы на внешние сигналы. Например один из возможных вариантов для ваших кнопок: Прерывание, всегда, например раз в 20ms. Вне этого прерывания контроллер спит, или ковыряет в носу или еще чем его займете... В этом одном прерывании делается все. Прервались чтение состояния ............... В этом прерывании опрашиваются биты кнопок, если есть нажатия, то +1(один раз в прерывание!) к соответствующему индивидуальному байтовому счетчику времени для каждой кнопки. Если нажатие пропало , -то сброс соотв. счетчика. Затем, если какой-либо счетчик достиг исходно заданного вами значения времени, то включаем выход. ................... В зависимости от того, что включили, уст биты состояния, которые будут читаться при следующем входе в прерывание. Вернулись из прерывания. Думаю, сама идея понятна. Опрос кнопок производится многократно и решение о нажатии принимается, например, по 16 пробам. Ясно, что ресурсы на эту задачу минимальны и контроллер почти всегда свободен... Конкретно программа зависит от вида контроллера. |
|
|
picmaniac: 1. Подано питание. Инициализация, настройка портов. 2. Выходы обнулить как можно раньше. 3. Светодиоды погасить. 4. Проверить кнопки. 5. Если ни одна кнопка не нажата - погасить светодиоды, обнулить выходы и вернуться к п.4. 6. Если нажаты обе кнопки - зажечь 2 средних светодиода и переход к п.4. 7. Если нажата только одна кнопка - запомнить состояние кнопок. 8. Выдержать паузу 100 мс. 9. Проверить кнопки повторно. 10. Если состояние кнопок не соответствует запомненному - переход к п.4 11. Если нажата только кнопка L - установить 1 на OutL и вызвать подпрограмму бегущего огня влево (во время выполнения которой кнопки не опрашиваются). 12. Если нажата только кнопка R - установить 1 на OutR и вызвать подпрограмму бегущего огня вправо (во время выполнения которой кнопки не опрашиваются). 13. Возврат из подпрограммы бегущего огня. 14. Переход к п.10. (чтобы лог.0 не появился на выходе при нажатой кнопке) Это не окончательный вариант. Прошу покритиковать.
Осмелюсь. Допустим, что в процессе работы мы вышли на п.7. Далее выходим на п.9, где выясняется, что по цепи другой кнопки прошла помеха (ну, кратковременное появление 0). Согласно п.10 мы возвращаемся на п.4. Между п.9 и п.4 (при возврате) программной задержки практически нет. Следовательно, если мы засекли помеху в п. 9, то засечем ее и в п.4. И согласно п.6 мы сразу зажигаем два средних светодиода. После нескольких циклов п.6 - п.4 выясняется, что по другой кнопке все-таки прошла помеха и мы опять выходим на п.7, и далее, допустим все идет, как по маслу. Но сбой-то в результате появления помехи на другой кнопке был! Противоречит ли это нашему заданию, или допускается? Еще. Что такое нажатие двух кнопок одновременно? Наверное реально это невозможно? Всегда одна кнопка будет отставать от другой. И тогда вредное явление, описанное выше, оказывается не вредным, а полезным?! Более того, при нажатии двух кнопок одновременно, я думаю будет опасность "ложняков" не только в результате появления помехи, но и в результате настоящего дребезга. Как примирить все эти моменты? Я думаю, что все-таки надо сделать так: .................... п.N. Запись состояния всех кнопок в регистр. п.N+1. Задержка 100мс п.N+2. Считать состояние всех кнопок в W п.N+3. Вычесть W из регистра п.N+4. Проверить флаг Z . Если 0, возврат на п.N. . Если 1, то программа идет далее А далее нам не надо уже заботиться ни о дребезге, ни о помехах. Делаем проверки, как хотим. Даже так, как я предложил в своей программе. Единственное, что время между зажиганием последнего с/д и первого с/д в процессе бегущего огня при нажатой кнопке, увеличиться на 100мс (250+100мс), что будет противоречить заданию. Необходимо сократить последнюю паузу, или бог с ней?
|
|
|
picmaniac: Что дребезг, что помехи - нам без разницы. Дребезг - это в общем-то тоже своеобразная "помеха". Один или несколько импульсов (в данном случае отрицательных, т.к. подтяжка к шине питания) на входе за промежуток менее 100 мс мы считаем помехой. От неё и предстоит отстраиваться. Дико извиняюсь, но ясности это не прибавило, а наоборот убавило. В чем тогда ошибка в моих рассуждениях от (сегодня, 01:30)? С этим дребезгом (помехами) в голове такая же "каша", как и была до обсуждения.
|
|
|
|
|