J'essaie d'utiliser des interruptions de changement de broche pour détecter les boutons enfoncés. Jusqu'à présent, je n'ai jamais travaillé avec ce type d'interruptions et il y a quelques problèmes, donc je veux m'assurer que c'est la bonne utilisation.
Si j'ai bien compris la fiche technique, les choses suivantes doivent être faites pour utiliser une interruption de changement de broche:
- Définissez les codes PIN que vous souhaitez contrôler dans le registre PCMSK
- Activer le registre PIN pour le contrôle d'interruption de changement de broche (PCICR)
- Activer les interruptions
- Utilisez le vecteur d'interruption correspondant
Projet: Simple Moodlamp, couleurs contrôlées via 4 boutons.
Installer:
- Atmega168A-PU
- 4 mini interrupteurs à bouton-poussoir
- MOSFETS pour contrôler ma LED RGB 3 Watt
Voici le code que j'utilise qui ne fonctionne pas comme prévu:
#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);
}
}
Remarque: les boutons doivent être anti-rebond. Étant donné que j'essaie de procéder pas à pas et que cela ne devrait pas être important pour allumer la LED, je l'ai ignoré ici.
Question: La manière dont j'essaie d'utiliser les interruptions est-elle correcte?
Problèmes avec ma configuration:
- Les boutons 1-3 sont totalement ignorés.
- Button4 déclenche une réinitialisation de l'atmega
Choses que j'ai vérifiées:
- Les boutons ne sont en aucun cas connectés au PIN de réinitialisation
- Les boutons sont correctement connectés à GND s'ils sont enfoncés
- Les boutons ne sont pas connectés à GND s'ils ne sont pas enfoncés
Les boutons fonctionnent bien si je les utilise sans interruption, par exemple:
si (! (PINC & BUTTON4)) {PORTB ^ = BLUE; }
- Cristal externe 16MHZ / cristal interne
- Toute erreur dans le routage
- J'utilise un condensateur 100nF entre PWR et GND sur l'atmega
- VCC (7), GND (8), GND (22), AVCC (20) sont connectés (car je n'ai pas besoin d'AREF, ce n'est pas connecté)