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 obtuve la hoja de datos correcta, se deben hacer las siguientes cosas para usar una interrupción de cambio de pin:
- Establezca qué PIN desea controlar en el registro PCMSK
- Habilite el registro de PIN para el control de interrupción de cambio de pin (PCICR)
- Habilitar interrupciones
- Use el vector de interrupción correspondiente
Proyecto: Moodlamp simple, colores controlados a través de 4 botones.
Preparar:
- Atmega168A-PU
- 4 mini interruptores de botón
- MOSFETS para controlar mi LED RGB de 3 vatios
Aquí está el código que estoy usando que 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 eliminados. Como estoy tratando de hacerlo paso a paso y no debería importar encender el LED, lo ignoré aquí.
Pregunta: ¿Es correcta la forma en que intento usar las interrupciones?
Problemas con mi configuración:
- Los botones 1-3 se ignoran por completo.
- Button4 está activando un reinicio de atmega
Cosas que revisé:
- Los botones no están conectados de ninguna manera al PIN de reinicio
- Los botones están conectados correctamente a GND si se presionan
- Los botones no están conectados a GND si no se presionan
Los botones funcionan bien si los utilizo sin interrupción, por ejemplo:
if (! (PINC & BUTTON4)) {PORTB ^ = AZUL; }
- Cristal externo de 16MHZ / cristal interno
- Cualquier error en el enrutamiento
- Estoy usando un condensador de 100nF entre PWR y GND en el atmega
- VCC (7), GND (8), GND (22), AVCC (20) están conectados (ya que no necesito AREF, no está conectado)