Estoy tratando de usar interrupciones de cambio de pin para detectar botones presionados. Hasta ahora nunca he trabajado con este tipo de interrupciones y hay algunos problemas, así que quiero asegurarme de que este sea el uso correcto.
Si obtengo la hoja de datos correctamente, se deben hacer las siguientes cosas para usar una interrupción de cambio de pin:
- Establezca los PIN que desea controlar en el registro PCMSK
- Habilitar el registro de PIN para el control de interrupción de cambio de pin (PCICR)
- Habilitar interrupciones
- Utilice el vector de interrupción correspondiente
Proyecto: Moodlamp simple, colores controlados mediante 4 botones.
Configuración:
- Atmega168A-PU
- 4 mini interruptores pulsadores
- MOSFETS para controlar mi LED RGB de 3 vatios
Aquí está el código que estoy usando y no funciona como se esperaba:
#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: Los botones deben ser rebotados. Ya que estoy intentando este paso a paso y no debería importar el encendido del LED, lo ignoré aquí.
Pregunta: ¿La forma en que estoy intentando usar las interrupciones es correcta?
Problemas con mi configuración:
- Los botones 1-3 están totalmente ignorados.
- Button4 está activando un reinicio de la atmega
Cosas que verifiqué:
- Los botones no están conectados de ninguna manera al PIN de restablecimiento
- Los botones están correctamente conectados a GND si se presionan
- Los botones no están conectados a GND si no se presionan
-
Los botones
funcionan bien si los uso sin interrupciones, por ejemplo:
si (! (PINC & BUTTON4)) { PORTB ^ = AZUL; }
- Cristal externo de 16MHZ / cristal interno
- Cualquier error en el enrutamiento
- Estoy usando un capacitador de 100 nF entre PWR y GND en la atmósfera
- VCC (7), GND (8), GND (22), AVCC (20) están conectados (ya que no necesito AREF, no está conectado)