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

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

  1. Разрешаем EXTI ISR по входам с клавиш, по обоим фронтам.
  2. Происходит ожидание изменения уровня сигнала на входах.
  3. Прерывание по EXTI, вызов EXTI ISR.
    В EXTI ISR останавливаем и запускаем заново таймер. Например, на 20 мс.
  4. Если ко времени вызова ISR таймера произойдёт новый вызов EXTI ISR, то таймер будет перезапущен и начнёт считать заново.
  5. Таймер досчитал, вызывается ISR таймера. Таймер останавливаем.
    Здесь состояние клавиатуры можно считать стабильным. Поэтому считываем её состояние и передаём на обработку, куда следует.
  6. Переходим к пункту 1.

Этот же метод вполне пригоден для определения таймаута по приёму UART на микроконтроллерах, у которых отсутствует отдельное прерывание по таймауту.

На CyberForum'е заметили, что при плохом контакте прерывания от клавиатуры могут идти слишком часто и микроконтроллер будет всё время висеть в прерываниях. Отсюда возникла небольшая доработка.

  1. Разрешаем EXTI ISR по входам с клавиш, по обоим фронтам.
  2. Нажимается ржавая кнопка.
  3. По первому вызову EXTI ISR:
  4. Запускается таймер;
  5. Отключается только вызов ISR по EXTI в NVIC, флаги прерываний продолжают сохраняться в регистре PR;
  6. В ISR таймера:
  7. Останавливаем таймер;
  8. проверяем наличие флага прерывания от EXTI:
    • Если флаг установлен, перезапускаем таймер;
    • Если флаг не установлен, то считываем состояние клавиатуры и передаём на обработку.
  9. Переходим к пункту 1.

Видео: Демонстрация подавления дребезга контактов

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