Savoir implémenter les interruptions externes INT0, INT1,…, INTn
Exemple 1: Diviseur de fréquence PWM par 2 (8 sorties synchrones)
Exemple 2: Synthèse de 8/16/32 sorties PWM synchrones
On va aborder à travers deux exemple les aspects pratiques des interruptions externes, en particulier les interruptions INT (INT0, INT1, etc.). La carte Arduino Mega dispose de 8 sources d’interruptions INT : INT0-INT7. Ces derniers sont câblés dans les deux port D et E pour la carte Arduiono Mega.
Nous avons abordé dans l’introduction aux interruption la notion du vecteur d’une interruption. En effet, chaque interruption est caractérisée par un vecteur, un numéro, indiquant sa priorité. L’interruption RESET dispose d’un vecteur égal à 1 (2 pour INT0, 3 pour INT1, etc.), elle la plus prioritaire.
Le vecteur permet également d’exécuter la routine ISR(). L’IDE Arduino dispose par défaut des variables prédéfinies pour spécifier un vecteur quelconque. Le nombres d’interruption (disponibilité d’un vecteur) va dépendre de la carte Arduino utilisée. En pratique, on consulte le tableau des sources d’interruptions pour connaitre le nombre et les nom s de sources d’interruptions. La syntaxe préfinie pour spécifier un vecteur est la suivante : NOM_vect.
Donc, il faut connaitre les variables prédéfinies (INT0_vect, INT1_vect, …) pour les différentes interruptions. Il se peut que vous ne savez pas le nom exact pour déclencher votre routine ISR. Par exemple, pour les périphériques ayant des noms composes. Dans ce cas, il faut utiliser la syntaxe originale pour déclencher ISR de la façon suivante : _VECTOR(numéro du vecteur).
Attention: _VECTOR(1) pour INT0, _VECTOR(2) pour INT1, etc.
Exemple 1: Diviseur de la fréquence par 2
L’objectif de l’exemple sera de diviseur la fréquence d’un signal PWM par 2 en utilisant l’interruption externe INT0. Ensuite, générer 8 sorties PWM synchrones ayant ½ la fréquence du signal PWM. On va utiliser le pin 2 de la carte Arduino pour générer le signal PWM de référence. Ce dernier sera ensuite câblé avec le pin 21 de la même carte. Sachant que l’interruptions INT0 est câblée avec le même pin, par conséquence, la routine de l’interruption sera exécutée à la présence d’un évènement dans le pin 21 de la carte Arduino. Dans cet exemple, on utilisera la détection par front montant. Dès la présente d’un front montant sur le pin, on inverse l’état du port A (sur 8 bits). Ayant comme conséquence la génération de 8 sorties PWM avec une fréquence égale à la moitié du signal PWM de référence (voir la vidéo pour plus de détails).
#define PWMout 2 // Signal PWM de référence
bool State=false;
void setup() { // Initialisation de la sortie PWM (signal carré, rapport cyclique 50%) analogWrite(PWMout, 128);
// Câblage du pin et configuration en entrée: INT0 => PD0 (pin 38 de la carte) DDRD =0x00; // Port D en entrée
// Activation de l'interruption globale (registre SREG) SREG|=0x80; //SREG|=0x80 // Activation //SREG&=0x7f // Désactivation //Ou bien //sei(): Set interrupt - Activation //cli(): clear interrup - Désactivation (masquer)
// Validation de l'interruption INT0 (Registre EIMSK) EIMSK|=0x01; // INT0 //EIMSK|=0x02; // INT1 //EIMSK|=0x04; // INT0 //... // Choix du mode de détection: Front montant dans INT0 EICRA|=0x03; //EICRA|=0x00; //niveau bas '0' dans INTn //EICRA|=0x01; //front montant ou descendant dans INTn //EICRA|=0x02; //Front descendant dans INTn //EICRA|=0x03; //Front montant dans INTn
// Initialisation du port A en sortie DDRA =0xff; PORTA=0x00; }
void loop() { // Au chaumage }
// Routine d'interruptions : Pour chaque front montant on inverse l'état // du port A (8 sorties synchrones)
Même code de l’exemple 1 avec une détection par front montant & descendant. La technique va nous permettre des signaux PWM synchrones ayant la même fréquence de celui du signal de référence. Dans cet exemple, le registre EICRA sera chargé avec le mot 0x01.
#define PWMout 2
bool State=false;
void setup() { // Initialisation de la sortie PWM (signal carré) analogWrite(PWMout, 128);
// Câblage du pin et configuration en entrée: INT0 => PD0 (pin 21 de la carte) DDRD =0x00; // Port D en entrée
// Activation de l'interruption globale (registre SREG) SREG|=0x80; // Ou bien sei();
// Validation de l'interruption INT0 (Registre EIMSK) EIMSK|=0x01;
// Choix du mode de détection: Front montant & descendant dans INT0 EICRA|=0x01;
// Initialisation du port A en sortie DDRA =0xff; PORTA=0x00; }
void loop() { // Au chaumage }
// Routine de l’interruption: Pour chaque front montant & descendant on inverse l'état // du port A (8 sorties synchrones)