Полный хак: Подключаем 16 кнопок на 3 прерывания

Представьте: у вас есть клавиатура 4×4, и вы хотите обрабатывать нажатия без опроса в loop().

volatile bool keyPressed = false;
volatile uint8_t lastState = 0;

void setup() {
// Настраиваем пины 0-7 (PORTD) как входы с подтяжкой
DDRD = 0b00000000; // Все как входы
PORTD = 0b11111111; // Включаем внутренние pull-up резисторы

// Настраиваем прерывания для PORTD
PCICR |= (1 << PCIE0);   // Включаем прерывания для PCINT0 (PORTD)
PCMSK0 = 0xFF;           // Разрешаем прерывания на ВСЕХ пинах PORTD
sei();                   // Глобально разрешаем прерывания

}

// Обработчик прерывания (сработает при ЛЮБОМ изменении на пинах 0-7)
ISR(PCINT0_vect) {
uint8_t currentState = PIND; // Читаем ВСЕ 8 пинов за 1 такт

// Проверяем, какие пины изменились
uint8_t changedPins = currentState ^ lastState;

if (changedPins & (1 << 0)) {
    // Пин 0 изменился!
    if (currentState & (1 << 0)) {
        // Пин 0 стал HIGH (кнопка отпущена)
    } else {
        // Пин 0 стал LOW (кнопка нажата)
    }
}

if (changedPins & (1 << 3)) {
    // Пин 3 изменился — делаем что-то срочное!
}

lastState = currentState;  // Запоминаем для следующего раза

}

void loop() {
// Ваш код выполняется, пока прерывания работают в фоне!
// Можно спокойно управлять дисплеем, не опрашивая кнопки.
}

 Важные хакерские нюансы:

  1. Антидребезг: В прерываниях НЕЛЬЗЯ использовать delay(). Вместо этого ставьте флаг и обрабатывайте кнопку в loop() через millis().
  2. Разделяем пины по портам: Если вы используете PCINT0 для кнопок, не вешайте на этот порт ШИМ или UART — прерывания будут срабатывать постоянно.
  3. Скорость реакции: Pin Change прерывания срабатывают через 0.1 микросекунды после изменения сигнала. Это в 50 раз быстрее, чем digitalRead() в loop().

Вам также может понравиться

About the Author: ардуинчиков

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *