Radio Life - Программа управления одной кнопкой

УНЧ с коммутатором

Программа управления одной кнопкой (вариант 2)


// ====================================================== // Слово состояния программы volatile unsigned int SYS_status; #define SYS_KEYPRESS 0x0001 // бит нажатой кнопки #define SYS_KEYRDY 0x0002 // бит готовности кнопки #define SYS_LEDON 0x0004 // бит включенной подсветки #define SYS_IN1 0x0008 // флаг включения входа 1 // ====================================================== // входы/выходы контроллера для работы с кнопками // и коммутатором // ------------------------------------------------------ // PD3 (D3) - вход прерывания кнопок // // PD4 (D4) - выход 0 // PD5 (D5) - выход 1 // PD6 (D6) - выход 2 // PD7 (D7) - выход 3 // ------------------------------------------------- // ячейки обработки кнопок с подавлением дребезга // ------------------------------------------------- volatile int KEY_value; // состояние кнопки int KEY_delay = 250; // задержка на дребезг #define KEY_1 0x08 // маска для кнопки #define OUT_LED 0x04 // маска подсветки #define OUT_1 0x10 // маска аналогового входа 1 #define OUT_2 0x20 // маска аналогового входа 2 #define OUT_3 0x40 // маска аналогового входа 3 #define OUT_4 0x80 // маска аналогового входа 4 #define TIM2_DIVIDER 0x07 // предделитель таймера 2 (1024) #define TIM2_MASK 0x02 // маска прерывания таймера 2 volatile int LED_count; // счетчик таймера подсветки #define LED_MAXON 20 // время включения подсветки #define SET_TIME 8 // таймаут на включение режима установки // ================================================= // ------------------------------------------------------------------------- void setup() { // запрещаем прерывания перед настройкой cli(); // сбрасываем слово состояния программы SYS_status = 0; // устанавливаем режим "выход" линий 4-7 порта D DDRD = (DDRD | 0xf0); // устанавливаем режим "выход" линии 2 порта B (подсветка) DDRB = (DDRB | 0x04); // сбрасываем счетчик таймера подсветки LED_count = 0; // +++++++++++++++++++++++++++++++++ // настройка режимов прерывания 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 // +++++++++++++++++++++++++++++++++++++ // Настройка сторожевого таймера 0.5 sec // +++++++++++++++++++++++++++++++++++++ // необходимо для изменения делителя таймера WDTCSR = (1 << WDCE) | (1 << WDE); // установка делителя 0,5 сек. WDTCSR = (0 << WDP3) | (1 << WDP2) | (0 << WDP1) | (1 << WDP0); // разрешение прерываний таймера WDTCSR |= (1 << WDIE); // конец настройки прерывания сторожевого таймера // +++++++++++++++++++++++++++++++++++++ // включаем по умолчанию аналоговый вход 1 PORTD |= OUT_1; SYS_status |= SYS_IN1; // разрешаем прерывания после настройки sei(); } // ------------------------------------------------------------------------- void loop() { // проверка на срабатывание кнопки // ------------------------------- if ((SYS_status & SYS_KEYRDY) != 0) { // сбрасываем готовность кнопок SYS_status &= ~SYS_KEYRDY; // если кнопка нажата, включаем таймер подсветки if ((KEY_value & KEY_1) == 0) { // включаем подсветку PORTB |= OUT_LED; // устанавливаем бит включенной подсветки SYS_status |= SYS_LEDON; // устанавливаем бит нажатой клавиши SYS_status |= SYS_KEYPRESS; LED_count = 0; } else // сбрасываем бит нажатой клавиши SYS_status &= ~SYS_KEYPRESS; } // проверяем включена ли подсветка // ------------------------------- if ((SYS_status & SYS_LEDON) != 0) { if (LED_count >= LED_MAXON) { PORTB &= ~OUT_LED; SYS_status &= ~SYS_LEDON; } } // переключение входа при удержании кнопки SET_TIME/2 сек // ------------------------------------------------------ if (((SYS_status & SYS_KEYPRESS) != 0) && (LED_count == SET_TIME) && ((SYS_status & SYS_LEDON) != 0)) { // сначала гасим подсветку PORTB &= ~OUT_LED; SYS_status &= ~SYS_LEDON; // если включен Вход 1 if ((SYS_status & SYS_IN1) != 0) { // отключаем вход 1 PORTD &= ~OUT_1; // включаем вход 2 PORTD |= OUT_2; SYS_status &= ~SYS_IN1; } else { // отключаем вход 2 PORTD &= ~OUT_2; // включаем вход 1 PORTD |= OUT_1; SYS_status |= SYS_IN1; } } } // =================================== // Программа обработки прерывания 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; // фиксируем состояние кнопки } // ================================================== // Программа обработки прерывания сторожевого таймера // ================================================== ISR(WDT_vect) { LED_count++; }

Рис. 1. Схема коммутатора
(увеличенное изображение)