Почему он проверяет 10 мс на нажатие кнопки и 100 мс на ее отпускание.
Как говорится в сообщении в блоге, "Мгновенно реагируйте на ввод данных пользователем" и "Задержка в 100 мс весьма заметна".
Таким образом, основная причина, по-видимому, заключается в том, чтобы подчеркнуть, что make-debounce должен быть коротким, чтобы make фиксировался «немедленно» человеческим смыслом, и чтобы прерывание debounce было менее чувствительным ко времени.
Это также подтверждается абзацем в конце сообщения: "Как я уже писал в апрельском выпуске, большинство коммутаторов демонстрируют показатель отказов менее 10 мс. В сочетании с моим наблюдением, что ответ в 50 мс кажется мгновенным, разумно выберите период устранения отказов в диапазоне от 20 до 50 мс."
Другими словами, код в примере гораздо важнее, чем примерные значения, и то, какие правильные значения будут использоваться, зависит от используемых переключателей; вы должны сами решать их, исходя из особенностей вашего конкретного варианта использования.
Разве он не может просто проверить 10 мс на пресс-релиз?
Конечно, почему бы и нет? Как он написал, это должно работать, хотя он писал (как указано выше), что предпочитает более длительные периоды устранения дребезга (от 20 до 50 мс).
Является ли опрос этой функции каждые 5 мс из основного наиболее эффективным способом ее выполнения
Нет. Как писал автор, "Все эти алгоритмы предполагают наличие таймера или другого периодического вызова, вызывающего дебаунсер". Другими словами, это всего лишь один способ реализации программное устранение дребезга, а показанные примеры основаны на обычном прерывании по таймеру, вот и все.
Кроме того, в 5 мс нет ничего волшебного; как говорит автор: "Для быстрого отклика и относительно низких вычислительных затрат я предпочитаю частоту тиков в несколько миллисекунд. Идеально от одной до пяти миллисекунд".
или я должен проверить прерывание на выводе, и когда есть прерывание, изменить вывод на GPI и перейти к процедуре опроса, а после того, как мы выведем значение, переключить вывод обратно в режим прерывания?
Если вы реализуете это в коде, вы обнаружите, что довольно неприятно иметь прерывание, которое блокирует нормальное выполнение кода на 10–50 мс за раз. Ничего страшного, если проверка состояния входного контакта — это единственное, что делается, но если аппаратное обеспечение делает что-то еще, например, обновляет дисплей или мерцает некоторыми мигающими огнями, ваша процедура устранения дребезга в обработчике прерываний вызовет заметное дрожание/заикание. Другими словами, то, что вы предлагаете, не является практической реализацией.
То, как работают программные подпрограммы устранения дребезга на основе периодических прерываний по таймеру (показаны в исходном сообщении в блоге и в других местах), занимает очень короткое время, всего пару десятков циклов или около того, и не прерывает другой код ни на какое время. значительное количество времени. Это просто и практично.
Вы можете комбинировать периодическое прерывание по таймеру и прерывание по входному контакту (изменение состояния), но, поскольку накладные расходы многих программных средств устранения дребезга, основанных только на прерываниях по таймеру, ничтожны, как правило, не стоит пытаться комбинировать два — - код становится очень, очень сложным, а сложный код (особенно на встроенном устройстве) имеет тенденцию быть сложным/дорогим в обслуживании.
Единственный случай, который я могу придумать (но я всего лишь любитель, а не EE ни в коем случае!) Это если вы хотите минимизировать энергопотребление, например. работа от батареи и использование прерывания входного контакта для перевода устройства в режим частичной или полной мощности из спящего режима и т. п.
(На самом деле, если у вас также есть миллисекундный или субмиллисекундный счетчик (не обязательно основанный на прерывании, но, возможно, счетчик циклов или аналогичный), вы можете использовать прерывание входного вывода и счетчик циклов для обновления состояния входа на первом изменить, а затем десенсибилизировать его на определенное время после этого, сохраняя значение счетчика циклов при изменении состояния.Однако вам необходимо обрабатывать переполнение счетчика, чтобы избежать ситуации, когда давнее событие, кажется, произошло совсем недавно , из-за переполнения счетчика.)
Я нашел ответ Лундина довольно информативным и решил отредактировать свой ответ, чтобы показать свое собственное предложение по устранению дребезга программного обеспечения. Это может быть особенно интересно, если у вас очень ограниченная оперативная память, но много мультиплексированных кнопок, и вы хотите иметь возможность реагировать на нажатия и отпускания клавиш с минимальной задержкой.
Обратите внимание, что я не хочу подразумевать, что это «лучшее» в каком-либо смысле; Я только хочу, чтобы вы показали один подход, который я не часто встречал, но который может иметь некоторые полезные свойства в некоторых случаях использования. Здесь также количество циклов сканирования (в миллисекундах), в течение которых игнорируются входные изменения (10 для замыкания/выключения-включения, 10 для прерывания/включения-выключения), являются лишь примерными значениями; используйте осциллограф или метод проб и ошибок, чтобы найти наилучшие значения для вашего варианта использования. Если это подход, который вы считаете более подходящим для вашего варианта использования, чем другие бесчисленные альтернативы, то есть.
Идея проста: используйте один байт на кнопку для записи состояния, при этом младший значащий бит описывает состояние, а семь других битов являются счетчиком снижения чувствительности (длительности устранения дребезга). Всякий раз, когда происходит изменение состояния, следующее изменение рассматривается только через несколько циклов сканирования.
Преимущество этого заключается в немедленном реагировании на изменения. Он также допускает различные длительности make-debounce и break-debounce (в течение которых состояние контакта не проверяется).
Недостатком является то, что если ваши переключатели/входы имеют какие-либо сбои (ошибочные показания за пределами продолжительности устранения дребезга), они отображаются как четкие события включения/выключения.
Во-первых, вы определяете количество сканирований, при которых входы десенсибилизируются после перерыва и после замыкания. Они варьируются от 0 до 127 включительно. Точные значения, которые вы используете, полностью зависят от вашего варианта использования; это просто заполнители.
#define ON_ATLEAST 10 /* 0 to 127, inclusive */
#define OFF_ATLEAST 10 /* 0 to 127, inclusive */
Для каждой кнопки у вас есть один байт состояния, переменная state
ниже; инициализируется значением 0. Допустим, (PORT & BIT)
— это выражение, которое вы используете для проверки этого конкретного входного вывода, оценивая его как true (не ноль) для ON и false (ноль) для OFF. Во время каждого сканирования (в вашем прерывании таймера) вы делаете
if (state > 1)
state -= 2;
else
if ( (!(PORT & BIT)) != (!state) ) {
if (state)
state = OFF_ATLEAST*2 + 0;
else
state = ON_ATLEAST*2 + 1;
}
В любой момент вы можете проверить состояние кнопки, используя (state & 1)
. Это будет 0 для ВЫКЛ и 1 для ВКЛ. Кроме того, если (state > 1)
, то эта кнопка недавно была включена (если state & 1
) или выключена (если state & 0
) и поэтому не чувствительна к изменениям состояния входного контакта.
25.01.2018