В МК я до сих пор начинающий, хотя и собрал несколько устройств Инкубатор, управление ДХО остальное в основном учебное или незначащая мелочь. Сейчас хочу создать центр управления аквариумом и появился такой вопрос.
Раньше мне хватало 3 кнопок с комбинациями короткого, длинного и одновременного нажатия.
Принцип простой - таймер на 100Гц в таймере обновляется структура состояния кнопки (для меня в норме 3 задетектированых нажатия и 2 задетиктированных отпускания или 50мс на короткое нажатие тогда засчитывается клик).
А уже в основном цикле атомарно читается эта структура и выполняется инструкция(или анализируется набор структур для одновременного нажатия). Если инструкция долгая, некоторые клики пропускаются, но я считаю, что так лучше иначе могут быть неприятные эффекты, когда пойдут клики из буфера. (особенно если было зависание и пользователь начал тыкать любые кнопки).
Обработка счётчиков и состояния довольно длинная - около 70 строк ассемблерного кода от avr-gcc: Спойлер
Сильно инструкции не разбирал, но допустим максимум 200тактов на выполнение всех инструкций. Но из-за условных переходов работает половина(а то и меньше). Допустим 100 тактов на обработку ОДНОЙ кнопки в ХУДШЕМ случае.
Для трёх кнопок, это не было проблемой.
Но теперь, если у меня будет 16 кнопок, то в прерывании задержусь на 1600тактов, плюс, допустим, 400 тактов на всякую другую фигню.
В итоге получаю 2K тактов, это много или мало? Стоит ли того чтобы переписать отлаженную библиотеку и вынести больше обработки в основной цикл?
Допустим для atmega328 на 20MHz? Вроде должно получиться 100us.
Заранее благодарен!
P.S. Пока на другие прерывания ничего сильно ответственного вешать не планирую. P.P.S. Если можно подскажите на сколько в норме можно занимать прерывание в тактах или в миллисекундах в условиях когда в других прерываниях нет ничего важного и в условиях когда что-то есть. Желательно с конкретными примерами - например если используется UART на скорости 19200, то не больше столько-то.
В итоге получаю 2K тактов, это много или мало? Стоит ли того чтобы переписать отлаженную библиотеку и вынести больше обработки в основной цикл?
В идеале, прерывание должно успеть завершится до сработки следующего прерывания. Если программа работает, так как задумано, то поправлять начнете когда перестанет работать.
Вы знаете, что такое дребезг контактов? И сколько прерываний подряд будет идти на одно нажатие кнопки? С циклом в 2к инструкций на каждое прерывание это будет "весело и непринужденно", не говоря уж о полной занятости МК и отваливанию всех остальных интерфейсов.
P.P.P.S. Прикинул по алгоритму, когда клавиша не нажата обработка тела займёт 8тактов ну на возврат 4 такта. Итого, с учётом вызова, около 400 тактов на всю обработку кнопок. Уже не так страшно
В итоге получаю 2K тактов, это много или мало? Стоит ли того чтобы переписать отлаженную библиотеку и вынести больше обработки в основной цикл?
В идеале, прерывание должно успеть завершится до сработки следующего прерывания. Если программа работает, так как задумано, то поправлять начнете когда перестанет работать.
codenamehawk писал(а):
не говоря уж о полной занятости МК и отваливанию всех остальных интерфейсов
Кому верить?
u37 писал(а):
Вы знаете, что такое дребезг контактов? И сколько прерываний подряд будет идти на одно нажатие кнопки?
Может вы не поняли?
Таймер на 100Гц. В прерывании этого таймера изменяются состояния сразу всех кнопок.
В основном цикле уже атоманое копирование структуры состояний и неспешное выполнение команд.
От дребезга позволяет избавиться как раз таймер, задетиктировано нажатие счётчик увеличился, а если нет то уменьшился. Дошел до 3(30 миллисекунд), теперь может включается счётчик сколько кнопка была отпущена. Если по таймеру кнопка отпущена 2 раза подряд(20 миллисекунд), то клик считается засчитан, делается пометка в структуре, а уже эту пометку анализирует основной цикл вне прерываний.
У вас опрос кнопок вместо обработки прерывания от них? Что, тоже вариант. Если еще и вынесете обработчик из прерывания в фоновый процесс, будет еще лучше. Не гоже делать долгие процедуры в слое прерываний.
Если еще и вынесете обработчик из прерывания в фоновый процесс, будет еще лучше.
Вот в этом и вопрос, очень удобно обработать, счётчики нажатий и отпусканий, а также выставить флаги короткого и длинного нажатия в прерывании от таймера.
Ведь если я начну всё это обрабатывать в основном цикле, то на атомарный доступ тоже будут расходоваться такты.
Но по большему нужно опрашивать только изменение состояния, могу и в 8бит для одной кнопки уложиться. Но явно всё придётся переписать практически с 0.
Какой тип кнопки из клавиатуры? Необходимость использования анти-дребезг алгоритм с механическими кнопками нарушит ваши вычисления (100 Hz). "Жду" мех. кнопка не менее 20 ms, может быть 10..30 ms. При частоте сканирования 100 Hz, анализ по первому измерению будет неуспешным. Была кнопка с "уникальным" временем дребезга в 70 ms!.
При частоте сканирования 100 Гц "дребезг" невозможен, в чём и есть его прелесть. К слову - давно так делаю, получается мягко и пушисто. Главное вынести тяжелый обработчик из прерывания. Либо процедуру делать легкой и выдавать уже не нажатия/отжатия кнопок, а распознанные события по кнопкам (короткое нажатие, долгое и т.д.). В последнее время так и делаю.
Кнопки с дребезгом в 70 мс являются технически неисправными или несовместимыми с жизнью с программным решением. Их надо обрабатывать специальным образом и этот спецобраз в-принципе не совместим с обычными кнопками, т.к. тооооормооооZ.
Добавлено after 4 minutes 2 seconds: На вопрос "сколько можно сидеть в прерывании" вам ответит ваша аппаратура. Например, сколько можно сидеть, если принимается байт из UART? (или блок из UART, или из другого ARTа ))
Да, это просто вопрос из практики. Ето была нормально работающая кнопка.
В прерывания бы проанализировал состояние кнопок, изменил флаги как можно быстрее, а выполнение действия: в основной программе. Лично нет смысла перегружать MK из-за каких-то кнопок чрез прерывания и таймер. Где-то, для другой задачи, вам прерывание/я и таймер.
Последний раз редактировалось veso74 Пн дек 15, 2025 16:59:50, всего редактировалось 1 раз.
Какой тип кнопки из клавиатуры? Необходимость использования анти-дребезг алгоритм с механическими кнопками нарушит ваши вычисления (100 Hz). "Жду" мех. кнопка не менее 20 ms, может быть 10..30 ms. При частоте сканирования 100 Hz, анализ по первому измерению будет неуспешным. Была кнопка с "уникальным" временем дребезга в 70 ms!.
Пока поглядываю на такую клавиатуру: Спойлер
Даташита естественно нет, только схема обычной матричной клавы.
Я дефайнами могу поправить интервал таймера опроса. Могу другими дефайнами дожидаться устойчивого нажания не 3, а 8 опросов, а устойчивого отпускания не 2, а 7 опросов, заодно увеличить сколько опросов должно длиться долгое нажатие.
Это легко можно подогнать к реальному устройству. Но до него ещё далеко. Но вопрос не в этом. Вопрос в том кака долго я могу находиться в прерывании.
Это зависит от нагрузки MK в устройстве. Если МК ничего больше не делать, то обработка можно происходить по таймеру до следующего вызова. Но ... такие устройства уже встречаются редко.
Вариант моей реализации из прошлом, просто как идея: MK ничего не делает (не сканирует, не анализирует ...) пока не получит "нажат клавиш" с клавиатуры и PCF.
Да, это просто вопрос из практики. Ето была нормально работающая кнопка.
В прерывания бы проанализировал состояние кнопок, изменил флаги как можно быстрее, а выполнение действия: в основной программе. Лично нет смысла перегружать MK из-за каких-то кнопок чрез прерывания и таймер. Где-то, для другой задачи, вам понадобится таймер и таймер.
Я так и делаю. Никаких действий в прерывании нет. Но:
Но полный код для выставления счетчиков и флагов довольно большой, хотя много условий равенства, так что часто выполняется сильно быстрее. Например за 20 тактов на ненажатую кнопку с учётом всех вызовов.
Можно опрос сделать в прерывании не по таймеру, по нажатию хоть чего-то. Но всё равно это будет прерывание, и его тоже нельзя ДОЛГО задерживать. Но вот сколько это долго?
Можно даже пренести опрос в основной цикл, но опять же нужен АТОМАРНЫЙ доступ и опять нужно знать на какое время можно отключить прерывания.
Вариант моей реализации из прошлом, просто как идея: MK ничего не делает (не сканирует, не анализирует ...) пока не получит "нажат клавиш" с клавиатуры и PCF.
Спасибо!
Я уже думал о подключении через интерфейсы, по этому поводу у меня возник другой вопрос: viewtopic.php?f=61&t=200066
В общем ясно, что не ясно. Но лучше код переписать и протестировать после эмулятора на имеющихся живых 3 кнопочных девайсах. Может даже лучше получится. Это будет уже 4 итерация библиотеки, наверное и на гитхаб можно будет залить.
Пока спасибо, буду приделывать и оптимизировать. А так хоть в справочник по ассемблерным командам заглянул, тоже полезно. Хотя по нашим временам дешевле купить более быстрый МК, чем тратить время на оптимизацию которой не видно. Но это хобби, так что можно, увлекательно...
Если ещё есть что сказать - говорите. Но я вроде уяснил главное - надо смотреть на другие прерывания и считать сколько они могут подождать.
(Почти) не использую многозадачность кнопок (быстрое/медленное нажатие и отпускание, а также одновременное нажатие нескольких кнопок). Даже не рассматривал эту идею - нет необходимости.
В напр. 95% случаев пр. код для МК - как управляющим компонентом: задержка не так важна.
Но коллеги часто используют микроконтроллер и как исполнительный компонент (напр. + динамическая индикация, ШИМ ...). Алгоритмы "без пауз" и максимально быстрые процессы - предпочтительнее -> придется подсчитывать машинные циклы и оптимизировать алгоритмы.
Последний раз редактировалось veso74 Пн дек 15, 2025 18:33:04, всего редактировалось 1 раз.
Вообще-то, для этого все процессы в МК делают буфферизованными, что позволяет процессору спокойно заниматься обработкой. Даже больше, программу надо писать от настроек аппаратуры, и только дописывать подпорки на процессоре на то, не смог реализовать в железе. Но не таком МК (сарказм).
Вообще-то, для этого все процессы в МК делают буфферизованными
Я уже писал, что для клавиатуры это зло. А так да, в общем случае без буфера никак. Мало ли будет долгая команда, а тут пользователь начнет остервененно тыкать. Потом всё понатыканное в буфер будет неожиданно выполняться. Уж лучше тут пропустить ввод, зато мгновенный отклик, на последнюю команду.
(Почти) не использую многозадачность кнопок (быстрое/медленное нажатие и отпускание, а также одновременное нажатие нескольких кнопок).
У мня быстрое долгое сейчас в этом обработчике.
А одновременное нажатие уже в основном цикле просмтором флагов нескольких кнопок.
Добавлено after 4 hours 19 minutes 49 seconds: Если ещё кто читает. Этот таймер не очень важный, в основном опрос кнопок и так по мелочи. А что если я разрешу в этом прерывании другие прерывания.
Насколько это применимая идея? Или такого следует избегать всеми возможными способами? И к тому же опять всплывает проблема атомарного доступа. Попробую всё же сначала переписать, а там смотреть.
Да ведь это несложно сделать в конечном автомате. Кнопка или концевик - штука очень медленная, достаточно опрашивать 1 раз в миллисекунду (понятно, что если концевик можно "проскочить", то придется задействовать прерывание, но во всех остальных случаях это не нужно). Каждой кнопке заводим структуру: предыдущее состояние, нонешнее состояние, время последней смены состояния. Если еще счетчик нажатий ввести, можно и несколько нажатий подряд детектировать (а по прошествии определенного времени сбрасывать в нуль). Заодно и "антидребезг" программный. У меня обычно новая смена состояния допускается не раньше, чем через 50-80мс после предыдущей. Вот такой простой код.
_________________ Windows must die! And the users of this crap should either become smarter or become janitors.
Смотря как те кнопки обрабатывать и как программу организовать... Мне и стандартного варианта из 4-5 кнопок для домочасиков достаточно было... Правда проект или на ассемблере или для адуринки...
Ну так оно и ежу понятно, что прерывания для обработки кнопок, нажимаемых "кожаным мешком", не нужны. Ну вот взять, скажем, механическую клавиатуру. С какой скоростью самые "скорострельные" набирают? У меня когда-то было 400 с чем-то символов в минуту, но это - только когда фигачишь документацию. А код - редко бывает, что можно "на автомате" какой-нибудь здоровый switch с такой скоростью набирать. Обычно куда медленней.
_________________ Windows must die! And the users of this crap should either become smarter or become janitors.
С новыми микроконтроллерами с множеством пинам и матричная клавиатура не нужна - каждая кнопка может иметь свой собственный пин . Можете играть на пианино вдвоем и кнопки останутся не нажаты, если МК STM32 с напр. 64..100..144 пина . А и как произошло с китайскими STM: 64-pins стоить столько же, сколько 48-pins ...
Можете играть на пианино вдвоем и кнопки останутся не нажаты
Это только в 144-ногом 112 GPIO, а в 100-ногом их всего лишь 80, на пианинные клавиши не хватит. Да и пианино - тоже медленный инструмент, вполне можно мультиплексировать каждую миллисекунду. Правда, если "целыми портами" использовать, то задача упрощается: достаточно сравнивать предыдущее значение IDR с нынешним.
А вот как китаезы умудряются так сильно демпинговать - непонятно. STM32F103C6T6 я покупал по 30р за штучку — получается самое дешевое решение с CAN на борту (увы, USB в нем не умеет одновременно с CAN работать, но это не всегда и нужно). А для многих задач даже C4 хватит: к примеру, код USB занимает около 4к флеша + 128-256 байт ОЗУ.
_________________ Windows must die! And the users of this crap should either become smarter or become janitors.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения