rezident 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба И еще вопрос: используя прерывания от аппаратного таймера для подавления дребезга, с какой частотой целесообразнее всего устраивать эти прерывания? Прерывания для опроса кнопок должны следовать с периодом превышающим дребезг клавиш. Частота следования от 3Гц до 100Гц. Меньше 3Гц неудобно для пользователя, слишком медленная реакция на клавиши. Выше 100Гц не имеет смысла, никакая супер-пупер машинистка-профессионалка не сможет в таком темпе печатать, это раз. А во-вторых, дребезг многих широкораспространенных тактовых и мембранных кнопок составляет как раз порядка 10мс. И каков риск что пользовательская функция-обработчик не успеет обработаться до возникновения следующего прерывания? А в чем состоит риск-то? Во вложенных прерываниях? Дык можно их не допускать. А если вложенные прерывания разрешены, то обходите повторный вызов функции и всех делов-то. __interrupt void TimerISR(void) { static unsigned Cntr=0; Cntr+=1; __enable_interrupt(); if (Cntr<2) key_scan_func(); // вызов функции сканирования клавиатуры, только если не было вложенного прерывания ... Cntr-=1; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Помехи например, ложные срабатывания от датчиков, ведь такое IMHO может быть Сигналы конечно в природе возможны всякие, но мы вроде обсуждаем сабж! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 (изменено) · Жалоба Сигналы конечно в природе возможны всякие, но мы вроде обсуждаем сабж! Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков. :) Изменено 2 апреля, 2007 пользователем Axxel Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 (изменено) · Жалоба И еще вопрос: используя прерывания от аппаратного таймера для подавления дребезга, с какой частотой целесообразнее всего устраивать эти прерывания? И каков риск что пользовательская функция-обработчик не успеет обработаться до возникновения следующего прерывания? А не надо использовать прерывания от таймера, опрашивайте состояние таймера в общем цикле, спешить некуда. Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков. Универсальность - враг оптимальности. Изменено 2 апреля, 2007 пользователем Visor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Универсальность - враг оптимальности. Так каким же все-таки будет оптимальный код(алгоритм)? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба ...Так каким же все-таки будет оптимальный код(алгоритм)? :) СВОЙ! А это мой, заведомо хуже :laugh: Сервис вставлен в прерывание 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; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Да,действительно не такая уж и тривиальная это задача... подавление дребезга :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Visor 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба Так каким же все-таки будет оптимальный код(алгоритм)? :) Выбор за вами. Я свой описал достаточно понятно, чтоб реализовать. Причём реализовать его можно очень просто, несколькими логическими инструкциями с байтами, для 8 кнопок сразу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vaivai 0 2 апреля, 2007 Опубликовано 2 апреля, 2007 · Жалоба На Kazus.ru было несколько примеров на асемблере (давненько)-спрашывавшый был очень даволен результатом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Birden 0 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба Я очень часто использую следующий принцип: 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; } // автоповтор } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба Остановился пока на таком методе: unsigned char acc=0,state=0; interrupt Timer0() { acc=acc<<1; acc|=Pinx; if(acc==0){state=0;} if(acc==255){state=1;} } Всем респект! :cheers: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slog 0 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба Ну вы и нагородили, на пустом месте. Достаточно 20-30 раз в секунду опрашивать матрицу кнопок и ВСЁ. Дребезг не влияет ни на что. Можно считать что его нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба Достаточно 20-30 раз в секунду опрашивать матрицу кнопок Дело в том что мне необходимо контролировать не клавиатуру, а несколько датчиков. Т.е каждый датчик нужно проверять на дребезг по отдельности,датчики могут сработать одновременно, и.т.д. Т.е необходим одновременный контроль. Конечно, в принципе я понимаю что хватит и двух устойчивых состояний для принятия нажатия, но... мало ли что может произойти. To =AK= О таком методе шла речь? (с битовым сдвигом,выше) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=AK= 18 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба To =AK= О таком методе шла речь? (с битовым сдвигом,выше) Ну так вы же его использовали в своем коде. Я то же самое делал на ассемблере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axxel 0 3 апреля, 2007 Опубликовано 3 апреля, 2007 · Жалоба Ну так вы же его использовали в своем коде. Я то же самое делал на ассемблере. Вы же мне про него и сказали :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться