|
|
  |
Подавление дребезга контактов, Алгоритм подавления,реализация |
|
|
|
Apr 2 2007, 07:50
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Axxel @ Apr 2 2007, 10:28)  И еще вопрос: используя прерывания от аппаратного таймера для подавления дребезга, с какой частотой целесообразнее всего устраивать эти прерывания? Прерывания для опроса кнопок должны следовать с периодом превышающим дребезг клавиш. Частота следования от 3Гц до 100Гц. Меньше 3Гц неудобно для пользователя, слишком медленная реакция на клавиши. Выше 100Гц не имеет смысла, никакая супер-пупер машинистка-профессионалка не сможет в таком темпе печатать, это раз. А во-вторых, дребезг многих широкораспространенных тактовых и мембранных кнопок составляет как раз порядка 10мс. Цитата(Axxel @ Apr 2 2007, 10:28)  И каков риск что пользовательская функция-обработчик не успеет обработаться до возникновения следующего прерывания? А в чем состоит риск-то? Во вложенных прерываниях? Дык можно их не допускать. А если вложенные прерывания разрешены, то обходите повторный вызов функции и всех делов-то. Код __interrupt void TimerISR(void) { static unsigned Cntr=0; Cntr+=1; __enable_interrupt(); if (Cntr<2) key_scan_func(); // вызов функции сканирования клавиатуры, только если не было вложенного прерывания ... Cntr-=1; }
|
|
|
|
|
Apr 2 2007, 08:00
|

Частый гость
 
Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896

|
Цитата(Visor @ Apr 2 2007, 10:55)  Сигналы конечно в природе возможны всякие, но мы вроде обсуждаем сабж! Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков.
Сообщение отредактировал Axxel - Apr 2 2007, 08:01
--------------------
Если боишься - не говори. если сказал - не бойся. ©
|
|
|
|
|
Apr 2 2007, 08:07
|

Местный
  
Группа: Свой
Сообщений: 240
Регистрация: 23-03-07
Пользователь №: 26 428

|
Цитата(Axxel @ Apr 2 2007, 12:28)  И еще вопрос: используя прерывания от аппаратного таймера для подавления дребезга, с какой частотой целесообразнее всего устраивать эти прерывания? И каков риск что пользовательская функция-обработчик не успеет обработаться до возникновения следующего прерывания? А не надо использовать прерывания от таймера, опрашивайте состояние таймера в общем цикле, спешить некуда. Цитата(Axxel @ Apr 2 2007, 12:28)  Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков. Универсальность - враг оптимальности.
Сообщение отредактировал Visor - Apr 2 2007, 08:49
|
|
|
|
|
Apr 2 2007, 10:56
|

Частый гость
 
Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896

|
Универсальность - враг оптимальности. [/quote] Так каким же все-таки будет оптимальный код(алгоритм)?
--------------------
Если боишься - не говори. если сказал - не бойся. ©
|
|
|
|
|
Apr 2 2007, 12:12
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Axxel @ Apr 2 2007, 10:56)  ...Так каким же все-таки будет оптимальный код(алгоритм)?  СВОЙ! А это мой, заведомо хуже Сервис вставлен в прерывание 1 мс. Автоповтор. Ускорение автоповтора. Обработка комбинаций клавиш (генерируется альтернативный код) Предделитель для плохих кнопок. Успехов Код #define StartDelay 25 #define NextDelay 3
const char * const key_name[LastKbdEvent+1]= { "",name1,name2, name3, name4, name5, name6, name7 };
__no_init char kbd_status0; __no_init char kbd_status1; __no_init char kbd_status2; __no_init char kbd_status3; __no_init char kbd_status4;
__no_init char interrupt_counter; __no_init char found_events; __no_init char old_pressed_keys; __no_init char pressed_counter; __no_init char pressed_keys; char prescaler;
char DnPressed(void) { if (pressed_keys==kDn) return 1; else return 0; } char UpPressed(void) { if(pressed_keys==kUp) return 1; else return 0; } char NoPressed(void) { if (!pressed_keys) return 1; else return 0; }
void InitKbd(void) { kbd_status3=kbd_status2=kbd_status1=kbd_status0=0; found_events=0; }
void KbdService(void) // into timer interrupt 1 ms { if (prescaler<4) { prescaler++; return;} prescaler=0; switch (interrupt_counter) // to reduce time of function { case 0: interrupt_counter=1; //refresh statuses kbd_status3=kbd_status2; kbd_status2=kbd_status1; kbd_status1=kbd_status0; kbd_status0=Kbd; interrupt_counter=interrupt_counter; break;
case 1: interrupt_counter=2; //check pressed key every tic pressed_keys=kbd_status0&kbd_status1&kbd_status2; if (pressed_keys&(~kbd_status3)) if (bSound==SoundAlwaysOn) Beep(5,1); found_events|=pressed_keys&(~kbd_status3); // found edge if ((pressed_keys==kUp+kDn)&& // now this two keys ((~kbd_status3)&(kUp+kDn)))//and before it wasn't so {found_events|=kUpDn; // set new bit found_events&=~(kUp+kDn); break; } //reset usual bits if ((pressed_keys==kUp+kSt)&& // now this two keys ((~kbd_status3)&(kUp+kSt)))//and before it wasn't so {found_events|=kUpSt; // set new bit found_events&=~(kUp+kSt); break; }//reset usual bits if ((pressed_keys==kDn+kSt)&& // now this two keys ((~kbd_status3)&(kDn+kSt)))//and before it wasn't so {found_events|=kDnSt; // set new bit found_events&=~(kDn+kSt); break; } //reset usual bits break; case 2: interrupt_counter=3; //check if key the same as before if ((pressed_keys&kUp)||(pressed_keys&kDn)) //key for repeat { if (pressed_keys==old_pressed_keys) // same key? { if (pressed_counter) // yes, time over? {pressed_counter--;} //No else { pressed_counter=NextDelay; //Yes found_events=pressed_keys; } //reset } else // other key {pressed_counter=StartDelay; } }; old_pressed_keys=pressed_keys; break; case 3: interrupt_counter++; break; default: interrupt_counter=0; } }
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Apr 2 2007, 21:13
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 31-05-05
Пользователь №: 5 579

|
На Kazus.ru было несколько примеров на асемблере (давненько)-спрашывавшый был очень даволен результатом.
|
|
|
|
|
Apr 3 2007, 05:41
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 28-10-06
Из: Новосибирск
Пользователь №: 21 743

|
Я очень часто использую следующий принцип: Код unsigned char keyb; // глобальная переменная, состояние клавиатуры unsigned char kcnt; // счетчик времени события "кнопка нажата" ... // Опрос клавиатуры, вызывается из подпрограммы // обработки прерывания по таймеру (каждые 4 мс) // void rd_keyb(void) { unsigned char st; st = ~PINC; // читаем состояние кнопок if (st == 0) kcnt=0; else kcnt++; if (kcnt == 20) keyb=st; // таймаут антидребезга if (kcnt == 120) { keyb=st; kcnt -= 60; } // автоповтор }
|
|
|
|
|
Apr 3 2007, 08:57
|

Частый гость
 
Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896

|
Остановился пока на таком методе: unsigned char acc=0,state=0; interrupt Timer0() { acc=acc<<1; acc|=Pinx; if(acc==0){state=0;} if(acc==255){state=1;} } Всем респект!
--------------------
Если боишься - не говори. если сказал - не бойся. ©
|
|
|
|
|
Apr 3 2007, 10:34
|

Частый гость
 
Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896

|
Цитата(slog @ Apr 3 2007, 12:20)  Достаточно 20-30 раз в секунду опрашивать матрицу кнопок Дело в том что мне необходимо контролировать не клавиатуру, а несколько датчиков. Т.е каждый датчик нужно проверять на дребезг по отдельности,датчики могут сработать одновременно, и.т.д. Т.е необходим одновременный контроль. Конечно, в принципе я понимаю что хватит и двух устойчивых состояний для принятия нажатия, но... мало ли что может произойти. To =AK= О таком методе шла речь? (с битовым сдвигом,выше)
--------------------
Если боишься - не говори. если сказал - не бойся. ©
|
|
|
|
|
Apr 3 2007, 10:43
|

Частый гость
 
Группа: Новичок
Сообщений: 140
Регистрация: 31-01-07
Из: Челябинск
Пользователь №: 24 896

|
Цитата(=AK= @ Apr 3 2007, 13:40)  Ну так вы же его использовали в своем коде. Я то же самое делал на ассемблере. Вы же мне про него и сказали
--------------------
Если боишься - не говори. если сказал - не бойся. ©
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|