|
|
  |
нажатие кнопки, в течение определенного интервала |
|
|
|
Aug 22 2010, 17:53
|
Участник

Группа: Участник
Сообщений: 72
Регистрация: 7-05-07
Из: Болгария
Пользователь №: 27 577

|
Прилагаю вариант реализации кот. почти повторяет алгоритм предложеным rezident. Различает три состояния: нормальное когда кнопка нажата до 1сек, длиное >1сек и <2сек, и сверхдлиное >2сек. Попутно озвучивает нажатие кнопок. CV 2.03.9, Proteus 7.6 SP0
Прикрепленные файлы
KbdLCD.rar ( 73.76 килобайт )
Кол-во скачиваний: 78
|
|
|
|
|
Aug 25 2010, 20:42
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(rezident @ Aug 25 2010, 22:43)  ... В одном их моих устройств было 14 кнопок, работающих независимо друг от друга с генерацией автоповтора для каждой из них с индивидуальными паузой и темпом повтора. Кстати, именно для этого случая единственный таймер лучше, чем куча перезапускаемых. Лучше чем? Требует меньше ОЗУ? Вряд ли, т.к. под каждую "засечку времени" потребуется переменная разрядностью = разрядности таймера. По коду меньше? Тоже вряд ли, т.к. вместо инкремента/декремента программных счётчиков (которые могут иметь разрядность меньше разрядности таймера) будет выполняться сравнение (через вычитание) двух чисел разрядностью = разрядности таймера. Чем-то ещё? Но судя по упоминанию топикстартером линукса, разрядности таймеров и счётчиков его не будут сильно беспокоить. Тем более, что свою обработку кнопок он собирается вставить в ядро.
|
|
|
|
|
Aug 26 2010, 08:51
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(xemul @ Aug 26 2010, 02:42)  Лучше чем? Лучше с точки зрения количества абстракций. Ведь, например, внутри одного прибора не ставят кучу RTC для отсчета времени на каждый узел индивидуально. Я этот этап уже проходил когда-то. Опыт - сын ошибок трудных В первых проектах я делал таймер, который просто инкрементировался на единичку в прерывании. Хватало. Потом где-то стало нужно ориентироваться не просто на абстрактные "тики", а с более определенными единицами времени. Пришлось считать в мс, "тики" подгонять именно под эту единицу времени и инкрементировать счетчик кратно минимальной единице квантования (1мс, 4мс, 10мс, 15мс и т.п.). Потом образовалась некая кучка проектов с примерно одинаковой функциональностью, но с разным количественным набором их. В одном проекте три локальных счетчика, в другом семь, в третьем один. Да забодало!  В каждом нужно отдельно переписывать таймерное прерывание, хотя функционально оно одинаковое. Так я и пришел к единому таймеру. Мне проще написать одну функцию запроса времени к единому таймеру один раз, чем переписывать ее в каждом проекте под требуемые особенности функциональности.
|
|
|
|
|
Aug 26 2010, 12:27
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(rezident @ Aug 26 2010, 12:51)  Лучше с точки зрения количества абстракций. Ведь, например, внутри одного прибора не ставят кучу RTC для отсчета времени на каждый узел индивидуально. Я этот этап уже проходил когда-то. Опыт - сын ошибок трудных В первых проектах я делал таймер, который просто инкрементировался на единичку в прерывании. Хватало. Потом где-то стало нужно ориентироваться не просто на абстрактные "тики", а с более определенными единицами времени. Пришлось считать в мс, "тики" подгонять именно под эту единицу времени и инкрементировать счетчик кратно минимальной единице квантования (1мс, 4мс, 10мс, 15мс и т.п.). Потом образовалась некая кучка проектов с примерно одинаковой функциональностью, но с разным количественным набором их. В одном проекте три локальных счетчика, в другом семь, в третьем один. Да забодало!  В каждом нужно отдельно переписывать таймерное прерывание, хотя функционально оно одинаковое. Так я и пришел к единому таймеру. Мне проще написать одну функцию запроса времени к единому таймеру один раз, чем переписывать ее в каждом проекте под требуемые особенности функциональности. Т.е. лучше тем, что стало привычным. Мне привычнее определить для проекта минимальный требуемый тик, из которого компилятор сделает все производные кванты (достаточно в дефайнах задать Fosc и собственно тик; а квантов-то обычно требуется 2-3-4). Для таймеров событий мне никогда не требуется абсолютное время (в масштабе коробочки), и эти таймеры я делаю минимально необходимой разрядности. Таймеры запускаются по возникновению события и декрементируются по прошествии требуемого кванта. Таймер события живёт полем в структуре, другим полем является состояние события. Если событие приключается от дребезжащего (или, н-р, медленно ползущего зашумлённого, или кнопки радиобрелока) входа, то состояние события фильтруется одной и той же функцией, которая вызывается с указателем на поле состояния события и с квантом, требуемым для этого входа. (я когда-то использовал механизм вертикальных счётчиков by Scott Dattolo, помянутый 777777, но ушёл от него к индивидуальному горизонтальному счётчику, живущему в поле состояния события. Вертикальные счётчики тем не менее удобны для фильтрации многих входов с одинаковой динамикой - н-р, для клавиатуры 4х4). В моих погремушках с учётом обычно используемых 8-битных контроллеров такой подход получается более экономичным и по ОЗУ, и по ПЗУ.
|
|
|
|
|
Aug 26 2010, 12:52
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(xemul @ Aug 26 2010, 18:27)  Т.е. лучше тем, что стало привычным. Дык, это не религия и я не проповедник, чтобы обращать в нее  Могу еще такой аргумент "за" привести. "Мой" таймер живет в таймерном прерывании один. А все временные отметки могут жить где угодно, хоть в main-е, хоть в любой другой функции. Ваши же старт-стопные таймеры вынуждены жить все вместе в каком-либо таймерном прерывании, либо вам требуется из прерывания вызывать функцию для инкремента поля структуры таймера. Вызов функции в прерывании это доп. накладные расходы. Это я считаю минусом. И немалым. Еще один минус в том, что вам нужно обеспечивать атомарность доступа к содержимому каждого старт-стопного таймера, а мне эту задачу нужно всего лишь для одного таймера решить.
|
|
|
|
|
Aug 26 2010, 14:21
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(rezident @ Aug 26 2010, 16:52)  Дык, это не религия и я не проповедник, чтобы обращать в нее  Я ж тоже не настаиваю - у меня куча более вредных привычек  . Цитата Могу еще такой аргумент "за" привести. "Мой" таймер живет в таймерном прерывании один. А все временные отметки могут жить где угодно, хоть в main-е, хоть в любой другой функции. Ваши же старт-стопные таймеры вынуждены жить все вместе в каком-либо таймерном прерывании, либо вам требуется из прерывания вызывать функцию для инкремента поля структуры таймера. Вызов функции в прерывании это доп. накладные расходы. Это я считаю минусом. И немалым. В прерывании железного таймера только взводится флаг инкремента таймера программного. Старт-стопные таймеры в прерываниях тем более обрабатывать не требуется (хотя и можно достаточно безболезненно - они обычно 1-байтовые). Цитата Еще один минус в том, что вам нужно обеспечивать атомарность доступа к содержимому каждого старт-стопного таймера, а мне эту задачу нужно всего лишь для одного таймера решить. Угу, с соответствующим оверхедом при каждом обращении к этому одному таймеру.
|
|
|
|
|
Aug 27 2010, 14:56
|

Местный
  
Группа: Свой
Сообщений: 307
Регистрация: 6-02-08
Из: Россия, Екатеринбург
Пользователь №: 34 798

|
Цитата(demiurg_spb @ Aug 25 2010, 23:39)  Достаточно одну кнопку удерживать в момент включения прибора... нее! а вдруг клиент попой сядет на девайс и запусит программирование - именно две надо чтобы нажато было - как разблокировка на сотовых!
--------------------
Разработчик
|
|
|
|
|
Aug 30 2010, 10:02
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Ну пусть сядет. При этом надо чтобы ещё в этот момент передёрнули питание. По таймауту и выйдет из загрузчика. Ничего "страшного" при этом не произойдёт. Цитата(Ivan Kuznetzov @ Aug 27 2010, 18:56)  а вдруг клиент попой сядет Попы толстые бывают - и сразу несколько кнопок могут охватить  Не стоит развивать в себе паранойу...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 8 2010, 13:21
|

Знающий
   
Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237

|
Цитата(rezident @ Aug 19 2010, 19:46)  А сама процедура, требуемая топикстартеру, представляет из себя конечный автомат с 4-мя состояниями. К сожалению, Ваша процедура не удовлетворяет условию, поставленному автором темы (по нажатию 3 с запускать одно действие, по нажатию 5 с - другое). У Вас трёхсекундное событие генерируется ненужным "бонусом" к пятисекундному. Тут всё проще - за временем надо следить, когда кнопка уже отпущена, ибо пока она нажата - ничего о времени её нажатия предсказать невозможно. Получается конечный автомат из 2 состояний, которым можно по ходу дела давить и дребезг контактов: 1. Кнопка отпущена. Если кнопка нажата - присваивание переменной Т текущего времени, переход в состояние 2. 2. Кнопка нажата. Если кнопка отжата - вычисление разницы D текущего времени и переменной Т. При D < 500 мс игнорирование нажатия, при 5 c > D > 3 c действие для трёхсекундного нажатия, при D > 5 c действие для пятисекундного нажатия. Переход в состояние 1.
--------------------
Сделано в Китае. Упаковано в России.
|
|
|
|
|
Sep 8 2010, 13:28
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(xemul @ Aug 26 2010, 18:21)  В прерывании железного таймера только взводится флаг инкремента таймера программного. Старт-стопные таймеры в прерываниях тем более обрабатывать не требуется (хотя и можно достаточно безболезненно - они обычно 1-байтовые). А не могли бы вы привести пример кода? Допустим, в прерывании взвели флаг, пусть он называется TimerTickEvent. Что и где с ним нужно делать, если у нас, к примеру, заведено одновременно 10 таймеров? Насколько я понимаю, декрементировать все [ненулевые] таймеры вплоть до нуля, а по нулю запускать обработчик? Что-то в этом есть... Хотя я использую метод, на котором настаивает уважаемый rezident
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Sep 8 2010, 19:19
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Demeny @ Sep 8 2010, 19:21)  К сожалению, Ваша процедура не удовлетворяет условию, поставленному автором темы (по нажатию 3 с запускать одно действие, по нажатию 5 с - другое). У Вас трёхсекундное событие генерируется ненужным "бонусом" к пятисекундному. Ну и что? Пауза 3с всегда короче 5с и возникает раньше второго события. Время штука непрерывная и необратимая. Цитата(Demeny @ Sep 8 2010, 19:21)  Тут всё проще - за временем надо следить, когда кнопка уже отпущена, ибо пока она нажата - ничего о времени её нажатия предсказать невозможно. Вот именно! Событие нужно получить не только за определенный промежуток времени, но и немедленно через этот же промежуток. Зачем нужно 5с событие, которое произошло полчаса назад, когда на кнопку, например, сели попой и заметили это только сейчас? В случае устройства с автономным питанием, которое должно отключаться после 5с удержания кнопки, за полчаса оно может просто "высосать" весь аккумулятор, ожидая когда кнопку отпустят  Впрочем топикстартер, думаю, сам разберется какой алгоритм ему больше подходит.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|