Sto cercando di utilizzare gli interrupt di cambio pin per rilevare i pulsanti premuti. Fino ad ora non ho mai lavorato con questo tipo di interruzioni e ci sono alcuni problemi, quindi voglio assicurarmi se questo è l'uso corretto.
Se il foglio dati è corretto, è necessario fare le seguenti cose per usare un interrupt di cambio pin:
- Imposta quali PIN vuoi controllare nel registro PCMSK
- Abilita il registro PIN per il controllo di interruzione cambio pin (PCICR)
- Abilita interrupt
- Utilizzare il vettore di interrupt corrispondente
Progetto: lampada semplice, colori controllati tramite 4 pulsanti.
Impostare:
- Atmega168A-PU
- 4 interruttori a pulsante mini
- MOSFET per controllare il mio LED RGB da 3 Watt
Ecco il codice che sto usando che non funziona come previsto:
#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);
}
}
Nota: i pulsanti devono essere rimossi. Dal momento che sto provando questo passo per passo e non dovrebbe essere necessario accendere il LED, l'ho ignorato qui.
Domanda: Il modo in cui sto cercando di utilizzare gli interrupt è corretto?
Problemi con la mia configurazione:
- I pulsanti 1-3 sono totalmente ignorati.
- Button4 sta innescando un reset di Atmega
Cose che ho controllato:
- I pulsanti non sono in alcun modo collegati al PIN di ripristino
- I pulsanti sono correttamente collegati a GND se premuti
- I pulsanti non sono collegati a GND se non vengono premuti
I pulsanti funzionano bene se li utilizzo senza interruzioni, ad esempio:
if (! (PINC & PULSANTE4)) {PORTB ^ = BLU; }
- 16MHZ cristallo esterno / cristallo interno
- Eventuali errori nel routing
- Sto usando un condensatore da 100nF tra PWR e GND su atmega
- VCC (7), GND (8), GND (22), AVCC (20) sono collegati (poiché non ho bisogno di AREF, non è collegato)