Dans cet article, nous allons introduire la notion d’interruption hardware. Leur utilisation est primordiale dans le monde des microcontrôleurs. Les interruptions hardware sont implémentées dans toutes les familles de microcontrôleurs.
Les interruptions sont une manière de signaler au microcontrôleur que quelque chose s’est passé. La grande question qu’on peut se poser, c’est : pourquoi ne pas utiliser une des entrées-sorties digitales ? La réponse est très simple: On ne peut pas…
Quand on utilise une entrée digitale, on doit généralement la lire en utilisant une instruction puis agir sur la valeur lue via une équation logique adéquate. Le programme doit vérifier en permanence l’état de cette entrée et risque de passer la majorité de son temps à le faire. Suivant la complexité et la durée de votre code, il est possible que vous ratiez un changement d’état de votre pin.
En utilisant une interruption hardware, votre code, comme le dit le nom, est littéralement interrompu et le microcontrôleur est forcé d’exécuter une partie de code dédicacé à cette interruption. De cette manière, vous ne louperez plus aucun changement d’état de votre pin.
Suivant le type de carte que vous utilisez, il faut bien vérifier les spécifications de votre carte afin de déterminer où se trouvent les pins dédicacées à la gestion des interruptions.
Sur l’Arduino Uno classique, deux sources d’interruptions sont disponibles. Elles sont situées sur les pins 2 et 3. Pour notre exemple, nous allons placer une diode et sa résistance de limitation de courant sur la pin 4. Un bouton pressoir en série avec une résistance de 10k est placé entre le +5 volts et la masse. Le point commun entre la résistance et le bouton pressoir est connecté à la pin 2.

Réalisez le montage tel que décrit dans le paragraphe ci-dessus. Il vous reste à uploader le code ci-dessous dans la carte Arduino. Le code lit le niveau de la pin 2, fait une comparaison logique et exécute une routine consommant du temps. Une fois cette routine executée, on boucle.
En exécutant ce code, on remarque que la LED a un comportement erratique dû au fait de la longueur de la routine consommatrice de temps et le moment où le bouton est pressé. Parfois la LED change d’état immédiatement, parfois rien ne se passé et on doit maintenir le bouton appuyé pendent un certain temps avant que le changement d’état ne soit validé.
|
int boutonIn = 2; // Entrée pin 2 int ledOut = 4; // Sortie vers la LED int etat = LOW; // Etat enregistré void setup() { // definition des pins : boutonIn en entrée et ledOut en sortie pinMode(boutonIn, INPUT); pinMode(ledOut, OUTPUT); } void loop() { etat = digitalRead(boutonIn); //on lit l’état du bouton digitalWrite(ledOut, state); //on inscrit le résultat sur la LED //On simule une tache complexe consommatrice en temps. for (int i = 0; i < 100; i++) { delay(10); // on attend… } } |
|||
On utilise toujours le même circuit mais vous l’avez deviné, nous allons modifier le code afin d’utiliser les interruptions hardware qui sont à notre disposition. Quand vous avez uploadé le nouveau code, vous remarquerez que quelque soit le moment où vous appuyez sur le bouton, la LED réagit instantanément même si le microcontrôleur est en train d’exécuter le code d’attente dans le programme principal.
|
int BoutonIn = 0; // Interrupt 0 est sur la pin 0 int ledOut = 4; // Sortie vers la LED volatile int etat = LOW; // Etat enregistré void setup() { // La pin 4 est configure en sortie pinMode(ledOut, OUTPUT); //on déclenche une interruption pour chaque variation sur la pin 0 attachInterrupt(boutonIn, Change_etat, CHANGE); } void loop() { //On simule une tache complexe consommatrice en temps. for (int i = 0; i < 100; i++) { delay(10); // on attend… } } void Change_etat() { etat = !etat; digitalWrite(ledOut, etat); } |
|||
Le mot-clé volatile a été ajouté à la variable etat Afin que le compilateur utilise une case mémoire en RAM plutot que d’utiliser un registre pour stocker l’info. Ceci est fait pour éviter que ce même registre ne soit modifié par la routine principale lors de son déroulement normal entre deux interruptions.
La fonction attachInterrupt(param1, param2, param3) nécessite trois paramètres :
• param1 = Quelle interruption doit-on écouter. Attention, c’est le numéro de l’interruption et pas le numéro de la pin.
• param2 = Quelle fonction doit-être appelée par l’interruption, elle ne peut avoir de paramètres et ne retourne pas de réponse.
• param3 = Quel est le type de déclenchement de l’interruption.
Il y a quatre types de déclenchements possible :
• LOW = L’entrée est au niveau bas
• RISING = L’entrée passe d’un niveau bas à un niveau haut
• FALLING = L’entrée passe d’un niveau haut à un niveau bas
• CHANGE = L’entrée a changé de niveau. Elle est passé d’un niveau bas vers un niveau haut ou inversément.
La carte Arduino peut aussi être configure pour ignorer temporairement toute interruption. C’est ce qu’il faut faire si on a une partie de code qui doit impérativement être effectuée sans interruption pour des raisons de timing par exemple. Dans ce cas, il faut utiliser la fonction noInterrupts(). Une fois votre code effectué, vous pouvez, à nouveau, autoriser les interruption en appelant la fonction interrupts(). Si vous voulez completement retirer une interruption, vous pouvez encore utiliser detachInterrupt(numéro_interruption).