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

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

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

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

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

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

Демонстрация этого варианта:

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

Posted in STM32 on Sep 16, 2016