Я намагаюся використовувати переривання зміни штифтів, щоб виявити натиснуті кнопки. До цих пір я ніколи не працював з подібними перервами, і є деякі проблеми, тому я хочу переконатися, чи це правильне використання.
Якщо я отримав правильний опис даних, необхідно зробити наступне, щоб використовувати переривання зміни штифта:
- Встановіть, які PIN-коди потрібно керувати в регістрі PCMSK
- Увімкніть регістр PIN-кодів для управління перериванням зміни PIN-коду (PCICR)
- Увімкнути переривання
- Використовуйте відповідний вектор переривання
Проект: Простий Moodlamp, Кольори керовані за допомогою 4 кнопок.
Налаштування:
- Atmega168A-PU
- 4 міні-кнопкових вимикача
- MOSFETS для управління моїм світлодіодним світлодіодом RGB 3 Вт
Ось код, який я використовую, працює не так, як очікувалося:
#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 запускає скидання атмеги
Те, що я перевірив:
- Кнопки жодним чином не підключені до PIN-коду для скидання
- Кнопки належним чином підключені до GND, якщо їх натиснути
- Кнопки не підключаються до GND, якщо їх не натискати
Кнопки чудово працюють, якщо я використовую їх без перерви, наприклад:
if (! (PINC & BUTTON4)) {PORTB ^ = BLUE; }
- 16 МГц зовнішній кристал / внутрішній кристал
- Будь-які помилки в маршрутизації
- Я використовую 100nF конденсатор між PWR і GND на atmega
- VCC (7), GND (8), GND (22), AVCC (20) підключені (оскільки мені не потрібен AREF, його не підключено)