Перейти к содержанию
    

программный антидребезг

Нужно реализация программного антидребезгу при сканировании клавиатуры

Для какого МК ?

В Google введите нечто вроде: "Микроконтроллер подавление дребезга" и поищите готовый исходник, или напишите сами.

Само по себе подавление дребезга мало кому нужно, обычно оно входит в какой-то проект. Или это студенческий курсовой ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

..фуу, первый успел пролезть в помошники.

 

Что конкретно надо???

В гугле смотрели??

?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно реализация программного антидребезгу при сканировании клавиатуры

Первое, что Вам нужно - разобраться в склонениях. После этого прислушаться к совету kovigor и попробовать вникнуть в то, что нагуглили. И если будет что-то не понятно - спрашивать на форуме. При этом не надо дублировать темы. Как-то так. =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Алгоритм программного антидребезга может выглядеть примерно так.

Если состояние кнопки изменилось -> начать отсчет времени антидребезга

Иначе:( Если состояние кнопки не менялось)

Если ведется отсчет времени и время истекло -> зафиксировать текущее состояние кнопки. Остановить таймер.

 

Отсчет времени можно вести по таймеру или по количеству опросов (особенно если они регулярные).

Более детальную реализацию думаю сами осилите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

обобщенный алгоритм опроса кнопки с подавлением дребезга контактов:

1. считать состояние кнопки, запомнить его

 

2. подождать 10-15 миллисекунд

 

 

3. считать снова состояние кнопки

 

4. сравнить это состояние с тем, что запомнено на 1 шаге

 

5. если состояния РАЗНЫЕ - закончить алгоритм, считая, что кнопка не нажата (либо считая, что состояние кнопки то же самое, что было при прошлом опросе кнопки)

 

6. если состояния одинаковые, то обработать это состояние (нажато или не нажато)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще более простой алгоритм: опрашивайте клавиатуру считывая состояние кнопок с интервалом 15 - 20 мс (или другое значение, превышающее время дребезга) и используйте считанные значения как истинные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще более простой алгоритм: опрашивайте клавиатуру считывая состояние кнопок с интервалом 15 - 20 мс (или другое значение, превышающее время дребезга) и используйте считанные значения как истинные.
недопустимо

 

доводим до абсурда: опрашиваем кнопку 1 раз в час - ровно в 00 минут и 00 секунд и 00 миллисекунд. а я нажимаю кнопку ровно за 3 миллисекунды до этого момента - в итоге опрос попадает как раз на время, пока кнопка дребезжит, и что при этом "опросится" - не известно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот кусок проекта с подавлениями и автоповторами разными. Будут вопросы - пишите.

Почему-то не аттачится ничего...

 

//
#include "keyboard.h"
#include "encoder.h"
#include "hardware.h"	/* зависящие от процессора функции работы с портами */

enum 
{
KBD_BEEP_LENGTH =			NTICKS(25),	// длительность озвучивания нажатия

KBD_STABIL_PRESS =			NTICKS(30),	// was 20 время для регистраци нажатия
KBD_STABIL_RELEASE =		NTICKS(30),	// was 20 время для регистраци отпускания

KBD_MAX_PRESS_DELAY_LONG =	NTICKS(600), // время для регистрации удержания кнопки с медленным автоповтором
KBD_PRESS_REPEAT_SLOW =		NTICKS(400),	// время между символами по медленному автоповтору

//KBD_MED_STAGE1 = NTICKS(200),			// моменты, на которых вырабатывается очередной символ клавиши с быстрым автоповтором
//KBD_MED_STAGE2 = NTICKS(300),
//KBD_MED_STAGE3 = NTICKS(400),
//KBD_MED_STAGE4 = NTICKS(500),
KBD_TIME_SWITCH_QUICK = NTICKS(200), // с этого времени начинается быстрый автоповтор
KBD_PRESS_REPEAT_QUICK1 =	NTICKS(50),	// время между символами по быстрому автоповтору
KBD_PRESS_REPEAT_QUICK2 =	NTICKS(5)	// время между символами по очень быстрому автоповтору
};

// сделаны по 8 бит - при 200 герц прерываний 600 мс всего 120 тиков.
static uint_fast16_t kbd_press;	/* время с момента нажатия */
static uint_fast16_t kbd_release;		/* время после отпускания - запрет нового нажатия */

static uint_fast8_t kbd_last;	/* последний скан-код (возврат при отпускании кнопки) */
static uint_fast8_t kbd_slowcount; /* количество сгенерированных символов с медленным автоповтором */

static uint_fast8_t kbd_beep;	/* время с момента нажатия */

/* получение скан-кода клавиши или 0 в случае отсутствия.
* если клавиша удержана, возвращается скан-код с добавленным битом 0x80
* ОТЛАЖИВАЕТСЯ
*/
static uint_fast8_t
kbd_scan_local(uint_fast8_t * key)
{
const uint_fast8_t chinp = hardware_ged_pressed_key();
const uint_fast8_t notstab = (kbd_press < (KBD_STABIL_PRESS + 1));

if (chinp != KEYBOARD_NOKEY)
{
	if (/*kbd_release != 0 && */ ! notstab && (kbd_last != chinp))		// клавиша сменилась в состоянии стабильного нажатия
	{
		// самое первое нажатие
		kbd_last = chinp;
		kbd_press = 1;
		kbd_release = 0;
		kbd_slowcount = 0;
		//dbg_putchar('t');
		return 0;
	}
	else if (kbd_release != 0 && ! notstab)
	{
		// Уже было застабилизировавшееся значение - не меняем ничего.
		// kbd_last уже содержит правильное значение
		// Нажатие должно исчезнуть когда-то наконец.
		//dbg_putchar('k');
	}
	else if (kbd_press == 0)
	{
		// самое первое нажатие
		kbd_last = chinp;
		kbd_press = 1;
		kbd_release = 0;
		kbd_slowcount = 0;
		//dbg_putchar('l');
		return 0;
	}	
	else if (notstab && (kbd_last != chinp))		// Ожидание стабилизации кода клавиши
	{	
		kbd_last = chinp;
		kbd_press = 1;
		kbd_release = 0;
		kbd_slowcount = 0;
		//dbg_putchar('m');
		return 0;
	}

	kbd_release = KBD_STABIL_RELEASE;

	const uint_fast8_t flags = qmdefs [kbd_last].flags;
	/* сравнение кодов клавиш, для которых допустим медленный автоповтор при длительном удержании */
	if ((flags & KIF_SLOW) != 0)	//(is_slow_repeat(kbd_last))
	{
		// клавиша может работать с медленным автоповтором
		switch (++ kbd_press)
		{
		case KBD_MAX_PRESS_DELAY_LONG + KBD_PRESS_REPEAT_SLOW:
			kbd_press = KBD_MAX_PRESS_DELAY_LONG;	// позволяем ещё раз сюда попасть.

		case KBD_MAX_PRESS_DELAY_LONG:
			* key = qmdefs [kbd_last].code;	
			kbd_release = 0;
			return 1;
		}
		return 0;
	}
	/* сравнение кодов клавиш, для которых допустим быстрый автоповтор при длительном удержании */
	else if ((flags & KIF_FAST) != 0)	//(is_fast_repeat(kbd_last))
	{
#if KBD_ENCODER
		// клавиша может работать с быстрым автоповтором
		// Перестройка клавишами вместо валкодера
		switch (++ kbd_press)
		{
		case KBD_TIME_SWITCH_QUICK:
			if (kbd_slowcount < 20)
			{
				++ kbd_slowcount;
				kbd_press = KBD_TIME_SWITCH_QUICK - KBD_PRESS_REPEAT_QUICK1;
			}
			else
				kbd_press = KBD_TIME_SWITCH_QUICK - KBD_PRESS_REPEAT_QUICK2;
			// формирование символа в автоповторе
			encoder_kbdctl(qmdefs [kbd_last].code, 1);
			//dbg_putchar('R');
			//dbg_putchar('0' + kbd_last);
			break;
		default:
			//dbg_putchar('U');
			break;
		}
		return 0;
#endif
	}
	else
	{
		// клавиша может работать с длинным нажатием
		if (kbd_press == KBD_MAX_PRESS_DELAY_LONG)
			return 0;	// lond_press symbol already returned
		if (kbd_press < KBD_MAX_PRESS_DELAY_LONG)
		{
			if (++ kbd_press == KBD_MAX_PRESS_DELAY_LONG)
			{	
				* key = qmdefs [kbd_last].holded; // lond_press symbol
				//
				return 1;
			}
		}
	}
	return 0;

}
else if (kbd_release != 0) // Нет нажатой клавишии - было нажатие
{
	if (notstab)
	{
		kbd_press = 0;		// слишком короткие нажатия игнорируем
		kbd_release = 0;
		//dbg_putchar('J');
		return 0;
	}
	//dbg_putchar('r');
	// keyboard keys released, time is not expire.
	if (-- kbd_release == 0)
	{
		// time is expire
		if ((qmdefs [kbd_last].flags & KIF_FAST) != 0)
		{
#if KBD_ENCODER
			// Перестройка клавишами вместо валкодера
			//if (kbd_press < KBD_MED_STAGE1)
			if (kbd_slowcount == 0)
			{
				encoder_kbdctl(qmdefs [kbd_last].code, 0);
				//dbg_putchar('Q');
				//dbg_putchar('0' + kbd_last);
			}
			//else
			//	dbg_putchar('F');

			kbd_press = 0;
			kbd_slowcount = 0;
			return 0;		// уже было срабатывание по быстрому автоповтору
#endif
		}
		else if (kbd_press < KBD_MAX_PRESS_DELAY_LONG)
		{
			* key = qmdefs [kbd_last].code;	
			kbd_press = 0;
			kbd_slowcount = 0;

			return 1;		// срабатывание по кратковременному нажатию на клавишу.
		}
		else
		{
			kbd_press = 0;
			kbd_slowcount = 0;
			return 0;		// уже было срабатывание по автоповтору или по длинному нажатию.
		}
	}
	return 0;

}
else // нет нажатой клавиши и небыло нажатичя перед этим
	return 0;
}

static volatile uint_fast8_t kbd_scancode = KBD_CODE_MAX;
static volatile uint_fast8_t kbd_repeat;
static volatile uint_fast8_t kbd_ready;

// вызывается с частотой TICKS_FREQUENCY герц
// после завершения полного цикла ADC по всем входам.
void
kbd_spool(void)
{
uint_fast8_t code;
if (kbd_scan_local(& code) != 0)
{
	kbd_beep = KBD_BEEP_LENGTH;
	board_keybeep_enable(1);	/* начать формирование звукового сигнала */
	//if (code != KBD_CODE_BW_AGC)
	//{
	//	dbg_puts_impl("UPS!\n");
	//	for (;;)
	//		;
	//}
	if (kbd_scancode == code)
		++ kbd_repeat;
	else
	{
		kbd_scancode = code;
		kbd_repeat = 1;
	}
}
else
{
	if (kbd_beep != 0 && -- kbd_beep == 0)
		board_keybeep_enable(0);
}
kbd_ready = 1;
}

uint_fast8_t 
kbd_is_tready(void)
{
#if CPUSTYLE_ATXMEGA
#warning TODO: remove this
return 1;
#endif

uint_fast8_t f;

//disableIRQ();
f = kbd_ready;
//enableIRQ();
return f;
}

/* получение скан-кода клавиши и количества её повторов.
*/
uint_fast8_t kbd_scan(uint_fast8_t * key)
{
disableIRQ();
uint_fast8_t repeat;
if ((repeat = kbd_repeat) != 0)
{
	* key = kbd_scancode;
	kbd_repeat = 0;
	kbd_scancode = KBD_CODE_MAX;
}
enableIRQ();
return repeat;
}

/* Проверка, нажата ли клавиша c указанным флагом
// KIF_ERASE или KIF_EXTMENU
*/
uint_fast8_t kbd_get_ishold(uint_fast8_t flag)
{
uint_fast8_t r;
disableIRQ();
r = (kbd_press != 0) && (qmdefs [kbd_last].flags & flag);
enableIRQ();
return r;
}

/* инициализация переменных работы с клавиатурой */
void kbd_initialize(void)
{
// todo: все присвоения нулями могут быть убраны.

////kbd_press = 0;
////kbd_release = 0;
////kbd_repeat = 0;
//kbd_scancode = KBD_CODE_MAX;


// таймер. Просто тут живёт.
////timer_0p1_s_repeat = 0;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имею три массива для обработки панели управления: массив нового состояния кнопок New, массив предыдущего состояния кнопок Old, массив обработанных кнопок Fix.

Опрашиваю кнопки с разумным интервалом, 64 раза в секунду, сохраняю в массиве New. Сравниваю со старым Old, полученным в прошлом опросе, и обработанными кнопками Fix. Если есть кнопка, состояние которой в New и Old одинаковое (устойчивое, не дребезжит), и отличается от Fix (еще не обработана), то выполняю обработку этой кнопки (посылаю по интерфейсу, в моем случае). После этого меняю состояние в массиве Fix. Дальше можно искать следующую кнопку с такими же свойствами. Ну, и в конце цикла не забываю перенести массив New в Old.

Таким образом, реагирую на любое нажатие или отпускание кнопок в любой комбинации. Для обнаружения изменившегося состояния кнопки мне нужно время (1/64 * 2 = 31 ms). Более частое дребезжание будет игнорировано.

P.S. Автоповтор, если нужно, делаю в программе, куда посылаю состояние кнопок. Пока кнопка нажата, можно с неким интервалом (первый больше) реагировать на кнопку. Когда придет информация, что кнопка отпущена, прекращаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

недопустимо

доводим до абсурда: опрашиваем кнопку 1 раз в час - ровно в 00 минут и 00 секунд и 00 миллисекунд. а я нажимаю кнопку ровно за 3 миллисекунды до этого момента - в итоге опрос попадает как раз на время, пока кнопка дребезжит, и что при этом "опросится" - не известно

Вполне допустимо. Попали на дребезг сейчас - значит получим правильный результат в следующий опрос. Главное чтобы интервал опроса был заведомо больше времени дребезга и меньше времени реакции человека. 50-70 мсек - оптимум, при 100 уже чувствуется задержка...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вполне допустимо.
сколько себя помню, все время стараются с дребезгом бороться. а решение-то, оказывается, элементарное! спасибо вам за совет, теперь мир изменится...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

элементарное

Дай и я сюда плюну, обнаружители обычно просто строятся, в регистр вдвигается 0,1 (не нажата/нажата),

далее есть критерий обнаружения начала события (нажатия), продолжения (удерживания) и конца события (отпускания клавиши), обычно это столько единичек из столькото отчетов, например для начала нажатия можно

взять 2 единички из 3х отсчетов, аналогично для удержания и отжатия.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удобный механизм подавления дребезга - вертикальные счетчики.

 

Почитать о них можно тут -

http://www.compuphase.com/electronics/debouncing.htm

http://www.dattalo.com/technical/software/pic/debounce.html

http://www.electro-tech-online.com/microco...debouncing.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...