// ======================================================
// Слово состояния программы
volatile unsigned int SYS_status;
#define SYS_KEYPRESS 0x0001 // бит нажатой кнопки
#define SYS_KEYRDY 0x0002 // бит готовности кнопки
// ======================================================
// входы/выходы контроллера для работы с кнопками
// и коммутатором
// ------------------------------------------------------
// PD3 (D3) - вход прерывания кнопок
//
// PD4 (D4) - выход 0
// PD5 (D5) - выход 1
// PD6 (D6) - выход 2
// PD7 (D7) - выход 3
// -------------------------------------------------
// ячейки обработки кнопок с подавлением дребезга
// -------------------------------------------------
volatile int KEY_value; // состояние кнопки
int KEY_delay = 100; // задержка на дребезг
#define KEY_1 0x08 // маска для кнопки
#define OUT_LED 0x80 // маска подсветки
#define OUT_1 0x10 // маска аналогового входа 1
#define TIM2_DIVIDER 0x07 // предделитель таймера 2 (1024)
#define TIM2_MASK 0x02 // маска прерывания таймера 2
// =================================================
// -------------------------------------------------------------------------
void setup() {
// запрещаем прерывания перед настройкой
cli();
// сбрасываем слово состояния программы
SYS_status = 0;
// устанавливаем режим "выход" линий 4-7 порта D
DDRD = (DDRD | 0xf0);
// +++++++++++++++++++++++++++++++++
// настройка режимов прерывания INT1
// +++++++++++++++++++++++++++++++++
// срабатывание по изменению уровня на входе INT1 (PD3)
EICRA = (0 << ISC11) | (1 << ISC10);
EIMSK |= (1 << INT1); // разрешаем прерывания INT1
// конец настройки прерывания INT1
// +++++++++++++++++++++++++++
// настройки режимов таймера 2
// +++++++++++++++++++++++++++
TCCR2A = 0; // установить регистры в 0
TCCR2B = 0; // таймер остановлен
// устанавливаем режим CTC (сравнение с регистром OCR2A)
TCCR2A |= (0 << WGM20) | (1 << WGM21);
// установка регистра совпадения таймера OCR2A
OCR2A = KEY_delay;
// включение прерываний по сравнению (CTC)
TIMSK2 = TIM2_MASK;
// конец настройки прерывания таймера 2
// +++++++++++++++++++++++++++
// включаем по умолчанию аналоговый вход 1
PORTD = (PIND | OUT_1);
// разрешаем прерывания после настройки
sei();
}
// -------------------------------------------------------------------------
void loop() {
// проверка на срабатывание кнопок
if ((SYS_status & SYS_KEYRDY) != 0)
{
// сбрасываем готовность кнопок
SYS_status &= ~SYS_KEYRDY;
if ((KEY_value & KEY_1) == 0)
// инвертируем состояние подсветки
PORTD = (PIND ^= OUT_LED);
}
}
// ===================================
// Программа обработки прерывания INT1
// ===================================
ISR(INT1_vect) {
KEY_value = PIND; // сохраняем состояние кнопки
TCNT2 = 0; // обнуляем счетчик таймера 2
TCCR2B = TIM2_DIVIDER; // запускаем таймер с делителем 1024
}
// ============================================
// Программа прерывания таймера 2 по сравнению
// ============================================
ISR(TIMER2_COMPA_vect) {
TCCR2B = 0; // останавливаем таймер
SYS_status |= SYS_KEYRDY; // фиксируем состояние кнопки
}