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

Подавление дребезга контактов

И еще вопрос: используя прерывания от аппаратного таймера для подавления

дребезга, с какой частотой целесообразнее всего устраивать эти прерывания?

Прерывания для опроса кнопок должны следовать с периодом превышающим дребезг клавиш. Частота следования от 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;
}

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


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

Помехи например, ложные срабатывания от датчиков, ведь такое IMHO может быть

Сигналы конечно в природе возможны всякие, но мы вроде обсуждаем сабж!

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


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

Сигналы конечно в природе возможны всякие, но мы вроде обсуждаем сабж!

 

Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков. :)

Изменено пользователем Axxel

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


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

И еще вопрос: используя прерывания от аппаратного таймера для подавления

дребезга, с какой частотой целесообразнее всего устраивать эти прерывания?

И каков риск что пользовательская функция-обработчик не успеет обработаться

до возникновения следующего прерывания?

А не надо использовать прерывания от таймера, опрашивайте состояние таймера в общем цикле, спешить некуда.

Но ведь неплохо бы фильтровать и ложные срабатывания от немеханических датчиков.

Универсальность - враг оптимальности.

Изменено пользователем Visor

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


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

Универсальность - враг оптимальности.

 

 

Так каким же все-таки будет оптимальный код(алгоритм)? :)

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


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

...Так каким же все-таки будет оптимальный код(алгоритм)? :)

СВОЙ! :biggrin:

А это мой, заведомо хуже :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;
    }
}

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


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

Да,действительно не такая уж и тривиальная это задача... подавление дребезга :)

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


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

Так каким же все-таки будет оптимальный код(алгоритм)? :)

Выбор за вами. Я свой описал достаточно понятно, чтоб реализовать. Причём реализовать его можно очень просто, несколькими логическими инструкциями с байтами, для 8 кнопок сразу.

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


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

На Kazus.ru было несколько примеров на асемблере (давненько)-спрашывавшый был очень даволен результатом.

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


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

Я очень часто использую следующий принцип:

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; }   // автоповтор
}

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


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

Остановился пока на таком методе:

 

unsigned char acc=0,state=0;

 

interrupt Timer0()

{

acc=acc<<1;

acc|=Pinx;

if(acc==0){state=0;}

if(acc==255){state=1;}

}

 

Всем респект! :cheers:

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


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

Ну вы и нагородили, на пустом месте. Достаточно 20-30 раз в секунду опрашивать матрицу кнопок и ВСЁ. Дребезг не влияет ни на что. Можно считать что его нет.

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


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

Достаточно 20-30 раз в секунду опрашивать матрицу кнопок

 

 

Дело в том что мне необходимо контролировать не клавиатуру, а несколько датчиков.

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

одновременно, и.т.д. Т.е необходим одновременный контроль.

 

Конечно, в принципе я понимаю что хватит и двух устойчивых состояний для

принятия нажатия, но... мало ли что может произойти.

 

 

 

 

 

To =AK=

О таком методе шла речь?

(с битовым сдвигом,выше)

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


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

To =AK=

О таком методе шла речь?

(с битовым сдвигом,выше)

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

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


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

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

 

 

Вы же мне про него и сказали :)

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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