Я пытаюсь использовать прерывания смены контактов, чтобы обнаружить нажатые кнопки. До сих пор я никогда не работал с такими прерываниями, и есть некоторые проблемы, поэтому я хочу убедиться, что это правильное использование.
Если я правильно понял таблицу, для использования прерывания смены штифта необходимо сделать следующее:
- Установите, какие PIN-коды вы хотите контролировать в реестре PCMSK
- Включите регистр ПИН-кодов для управления прерыванием смены пинов (PCICR)
- Включить прерывания
- Используйте соответствующий вектор прерывания
Проект: Простой Moodlamp, Цвета управляются с помощью 4 кнопок.
Настроить:
- Atmega168A-PU
- 4 мини кнопочных переключателя
- МОП-транзисторы для управления моим 3-ваттным светодиодом RGB
Вот код, который я использую, который не работает должным образом:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BUTTON1 (1<<PC5)
#define BUTTON2 (1<<PC4)
#define BUTTON3 (1<<PC3)
#define BUTTON4 (1<<PC2)
#define GREEN (1<<PB1)
#define BLUE (1<<PB2)
#define RED (1<<PB3)
void init() {
// enable LED
DDRB |= GREEN;
DDRB |= BLUE;
DDRB |= RED;
// button pullups
PORTC |= BUTTON1;
PORTC |= BUTTON2;
PORTC |= BUTTON3;
PORTC |= BUTTON4;
// pin change interrupts for buttons
PCMSK1 |= PCINT13;
PCMSK1 |= PCINT12;
PCMSK1 |= PCINT11;
PCMSK1 |= PCINT10;
// enable pin change for buttons
PCICR |= PCIE2;
sei();
}
ISR(PCINT2_vect) {
PORTB = BLUE;
}
void ledTest() {
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
}
int main() {
init();
ledTest();
_delay_ms(500);
PORTB |= GREEN;
while(1) {
_delay_ms(100);
}
}
Примечание: кнопки должны быть отменены. Так как я пытаюсь сделать это шаг за шагом, и это не должно иметь значения для включения светодиода, я проигнорировал это здесь.
Вопрос: правильно ли я пытаюсь использовать прерывания?
Проблемы с моей настройкой:
- Кнопки 1-3 полностью игнорируются.
- Button4 запускает сброс Atmega
Вещи, которые я проверил:
- Кнопки никак не связаны с ПИН-кодом сброса
- Кнопки правильно подключены к GND при нажатии
- Кнопки не подключены к GND, если не нажаты
Кнопки работают хорошо, если я использую их без прерывания, например:
if (! (PINC & BUTTON4)) {PORTB ^ = СИНИЙ; }
- 16 МГц внешний кристалл / внутренний кристалл
- Любые ошибки в маршрутизации
- Я использую 100 нФ конденсатор между PWR и GND на Atmega
- VCC (7), GND (8), GND (22), AVCC (20) подключены (так как мне не нужен AREF, он не подключен)