Estou tentando usar interrupções de troca de pinos para detectar botões pressionados. Até agora, nunca trabalhei com esse tipo de interrupção e existem alguns problemas, por isso quero ter certeza se esse é o uso correto.
Se obtive a folha de dados correta, as seguintes ações devem ser feitas para usar uma interrupção de alteração de pinos:
- Defina quais PINs você deseja controlar no registro PCMSK
- Habilite o registro de PINs para controle de interrupção de alteração de pinos (PCICR)
- Ativar interrupções
- Use o vetor de interrupção correspondente
Projeto: Moodlamp simples, cores controladas através de 4 botões.
Configuração:
- Atmega168A-PU
- 4 mini botões
- MOSFETS para controlar meu LED RGB de 3 watts
Aqui está o código que estou usando, que não está funcionando conforme o esperado:
#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: Os botões devem ser devolvidos. Como estou tentando fazer isso passo a passo e não deve interessar em ligar o LED, eu o ignorei aqui.
Pergunta: A maneira como estou tentando usar as interrupções está correta?
Problemas com minha configuração:
- Os botões 1-3 são totalmente ignorados.
- Button4 está acionando uma redefinição do atmega
Coisas que eu verifiquei:
- Os botões não estão de forma alguma conectados ao PIN de redefinição
- Os botões estão conectados corretamente ao GND se pressionados
- Os botões não estão conectados ao GND se não forem pressionados
Os botões funcionam bem se eu os utilizar sem interrupção, por exemplo:
if (! (PINC & BOTÃO4)) {PORTB ^ = AZUL; }
- Cristal externo 16MHZ / cristal interno
- Quaisquer erros no roteamento
- Estou usando um capacitor de 100nF entre PWR e GND no atmega
- VCC (7), GND (8), GND (22), AVCC (20) estão conectados (já que não preciso do AREF, ele não está conectado)