Axxel 0 28 марта, 2007 Опубликовано 28 марта, 2007 (изменено) · Жалоба Привет всем! Написал небольшой кусочек кода для подавления дребезга контактов, IMHO данный код должен "фильтровать" ложные срабатывания менее заданного периода. Но почему-то не покидает ощущение того, что в коде могут оказаться грабли :) Какие еще есть правильные методы, либо можно это сделать проще или красивее? Пример для одного бита порта ввода: #define BOUNCE_CANCELLATION_PERIOD 20 unsigned char BITcounter=0; //счетчик состояний бита bit BITstate=0; //используемое (устойчивое) состояние бита (более 20 мсек) bit BITmemory=0; // промежуточная переменная, запоминающаяя предыдущее состояние бита bit toggled=0; //флаг,указывающий на изменение состояния бита interrupt Timer0() //возникает 1 раз в мсек { if(BITmemory^BITn){if(toggled){BITcounter=0;} toggled=1;} if(toggled ){BITcounter++;} if(BITcounter==BOUNCE_CANCELLATION_PERIOD){BITstate=BITn;BITcounter=0;toggled=0; } BITmemory=BITn; //чтение с порта } Вот, примерно так... Изменено 28 марта, 2007 пользователем Axxel Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Oleg_IT 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба Давно и хорошо работающий код. Обслуживает несколько клавиш. unsigned long int debounced_state = 0,debounced_stateOld = 0; unsigned long int A = 0x0; unsigned long int B = 0x0; unsigned long int C = 0x0; void debounce(unsigned long int new_sample) { unsigned long int delta; delta = new_sample ^ debounced_state; //Find all of the changes /* clock_A ^= clock_B; //Increment the counters clock_B = ~clock_B;*/ A = A^(B&C); B = B^C; C = ~C; A &= delta; //Reset the counters if no changes B &= delta; //were detected. C &= delta; //Preserve the state of those bits that are being filtered and simultaneously //clear the states of those bits that are already filtered. debounced_state &= (A|B|C); //Re-write the bits that are already filtered. debounced_state |= (~(A|B|C) & new_sample); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vade_nsk 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба а я просто опрашиваю клавиатуру с интервалом большим, чем максимальное время дребезга. Скажем в первом примере вместо прерывания каждую 1 мс делать опрос раз в 20-50мс. Человек такую задержку не чувствует Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IEC 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба Контролировать один раз нажатие клавиши (совет NVade) глупо, т.к. любой дребезг вызовет событие нажатия. По хорошему необходимо контролировать время первого удержания клавиши (состояния порта) и через контрольный тайм-аут, если состояние ни разу не изменилось, принимать решение о нажатии клавиши. После этого необходимо переходить на другой этап и контролировать время отпускания. Через определенный тайм-аут принимать решение об завершении работы с клавишей. И уже после всего этого можно переходить к повторному ожиданию нажатия клавиши. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба По хорошему необходимо контролировать время первого удержания клавиши (состояния порта) и через контрольный тайм-аут, если состояние ни разу не изменилось, принимать решение о нажатии клавиши. После этого необходимо переходить на другой этап и контролировать время отпускания. Через определенный тайм-аут принимать решение об завершении работы с клавишей. И уже после всего этого можно переходить к повторному ожиданию нажатия клавиши. Да, примерно так и сделано, т.е к примеру если BOUNCE_CANCELLLATION_PERIOD равен 20 то в течение за все 20 прерываний от таймера значение бита должно быть равно одному и тому же значению, только в этом случае состояние запоминается. Вопрос: нормально ли для этого алгоритма использование прерывания от таймера? Может есть способы без прерываний? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergCom07 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба Думаю лучший вариант реализуется при помощи прерываний от линий IO кнопок. В этом случае изменение состояния линии не пропустишь, а по таймеру только проверять время, прошедшее с момента последнего изменения состояния и через скажем 20 мс фиксировать логическое состояние кнопки (нажата/нет). Вопрос только в количестве кнопок и аппаратных прерываний, но у последних AVR их много. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба На самом деле достаточно ловить первый фронт изменения состояния и через таймаут проверить сохранилось ли состояние. И не надо ждать когда сигнал перестанет дребезжать, и только потом включать выдержку времени, это бессмысленно. Подумайте. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DeXteR 0 29 марта, 2007 Опубликовано 29 марта, 2007 · Жалоба На самом деле достаточно ловить первый фронт изменения состояния и через таймаут проверить сохранилось ли состояние. И не надо ждать когда сигнал перестанет дребезжать, и только потом включать выдержку времени, это бессмысленно. Подумайте. :) Если неждать то кто даст гарантию что после принятия решения о нажатой кнопке не происходит дребезга А с дребезгом при отжатии как быть ?? По моему мнению самый верный способ - запускать програмный таимер по нажатию Делать +1 если нажата и -1 если отжата Ограничить нулем и числом А снизу и сверху И принимать решение о точ что нажата кнопка когда таимер достигнет А Заодно можно и блительное нажатие обрабатывать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 29 марта, 2007 Опубликовано 29 марта, 2007 · Жалоба На всех форумах одни и те же вопросы задаются :) http://www.telesys.ru/wwwboards/mcontrol/1...es/202772.shtml Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 30 марта, 2007 Опубликовано 30 марта, 2007 · Жалоба У меня примерно так: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 31 марта, 2007 Опубликовано 31 марта, 2007 · Жалоба Если неждать то кто даст гарантию что после принятия решения о нажатой кнопке не происходит дребезга А с дребезгом при отжатии как быть ?? Либо я не ясно выразился, либо одно из двух. :) Ловим фронт изменения входа (не важно какой), запоминаем новое состояние, ждем время достаточное чтоб дребезг успокоился, проверяем вновь состояние входа, если совпало, его и принимаем за текущее. Обрабытывается таким образом и вкл и выкл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба А если произойдет такое? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба А если произойдет такое? Объясните пожалуйста, как такое возможно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=AK= 12 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Я проще делаю. В 8-битный сдвиговый регистр каждые 10 мс вдвигаю текущее состояние кнопки. Если в сдвиговом регистре все '1', то кнопка нажата, выходной сигнал устанавливаю в '1'. Если все '0', то кнопка отжата, выходной сигнал устанавливаю в '0'. Все другие комбинации игнорируются и не меняют состояние вых. сигнала. При опроcе каждые 10 мс и 8-ми битах время получается 80 мс, это отлично работает со всеми обычными кнопками, в т.ч. с мембранными клавами. Для массивных контактов, которые могут дребезжать с малой частотой (контактор какой-нибудь, например), время опроса можно увеличить до 20..30 мс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Объясните пожалуйста, как такое возможно? Помехи например, ложные срабатывания от датчиков, ведь такое IMHO может быть Я проще делаю. В 8-битный сдвиговый регистр каждые 10 мс вдвигаю текущее состояние кнопки. Если в сдвиговом регистре все '1', то кнопка нажата, выходной сигнал устанавливаю в '1'. Если все '0', то кнопка отжата, выходной сигнал устанавливаю в '0'. Все другие комбинации игнорируются и не меняют состояние вых. сигнала. При опроcе каждые 10 мс и 8-ми битах время получается 80 мс, это отлично работает со всеми обычными кнопками, в т.ч. с мембранными клавами. Для массивных контактов, которые могут дребезжать с малой частотой (контактор какой-нибудь, например), время опроса можно увеличить до 20..30 мс. Можно кусочек кода? И еще вопрос: используя прерывания от аппаратного таймера для подавления дребезга, с какой частотой целесообразнее всего устраивать эти прерывания? И каков риск что пользовательская функция-обработчик не успеет обработаться до возникновения следующего прерывания? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться