Cette page vise à présenter une première utilisation des interruptions sur un microcontrôleur STM32. À la suite de cette page, un développeur logiciel doit être capable:

  • De trouver les informations nécessaires dans une datasheet pour l’utilisation des interruptions,
  • De programmer les différents registres pour l’utilisation d’une interruption,
  • De comprendre le fonctionnement pour différentes sources d’interruption.
Version des outils Les différentes étapes utilisent la version v1.12.0 du logiciel STM32CubeIDE. Certaines variations au niveau des captures d’écrans peuvent apparaître si vous utilisez des versions différentes. De même, la carte utilisée est la Nucleo-F446RE.

Détection d’un évènement

Précédemment, nous avons utilisé un bouton poussoir pour déclencher l’allumage d’une LED. La détection de l’état du bouton était alors faite de manière scrutative: le programme vérifiait régulièrement l’état du registre correspondant. Bien que fonctionnel, ce type de fonctionnement est peu efficace: le microcontrôleur exécute en boucle des opérations pour détecter le changement d’état. Ainsi, il ne peut exécuter aucune autre tâche utile pendant ce temps d’attente, en plus de continuer à consommer en réalisant les calculs.

Les interruptions sont un moyen de répondre à ces limitations. L’idée derrière ce mécanisme matériel est de permettre au processeur d’être prévenu lorsqu’un évènement a lieu. Différents évènement peuvent être configurés: changement d’état d’une broche, le débordement d’un compteur etc. Lorsque le processeur en est informé, il interrompt l’exécution en cours pour traiter l’évènement.

Dans cette première partie, nous allons voir comment ce mécanisme peut être utilisé pour détecter le changement d’état d’un bouton poussoir.

Question 1

Comme précédemment, configurez la broche du bouton poussoir (broche 13 du GPIOC) dans l’état suivant:

  • MODE: Input,
  • RÉSISTANCE DE RAPPEL: pull-up.
Question 2 Pour déclencher une interruption depuis un GPIO, il est nécessaire d’activer son utilisation dans le NVIC (Nested Vectored Interrupt Controller). Grâce au register ISER du NVIC, activez l’interruption correspondant à la ligne EXTI susceptible de recevoir un changement d’état du bouton-poussoir.
Aide supplémentaire (si nécessaire)

Chaque ligne EXTIx est susceptible de détecter un évènement sur la broche x d’un des ports. Ainsi, pour la ligne à activer pour le bouton poussoir est celle correspondants aux broches 13: EXTI15_10.

De base, le signal d’horloge pour certains modules du système est désactivé. Pour les interruptions depuis un GPIO, il est nécessaire de réactiver le signal d’horloge pour SYSCFG. Pour cela, il est nécessaire d’ajouter la ligne de code suivante:

  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
Question 3 Le registre EXTICR dans SYSCFG permet de choisir le port de déclenchement sur chaque ligne. Modifiez le registre EXTICR pour que la ligne EXTI13 utilise le port C du bouton poussoir.
Question 4 Pour être activée, une ligne d’interruption doit être non-masquée. Modifiez le registre IMR de EXTI en mettant le bit pour EXTI13 dans l’état correspondant.
Question 5 Une interruption peut être déclenchée pour différents types d’évènements, aussi bien sur un front montant qu’un front descendant. Pour cela, deux registres RTSR et FTSR sont mis à disposition, respectivement pour activer/désactiver un déclenchement sur front montant ou descendant. Configurez ces deux registres pour ne lancer une interruption que lorsque le bouton est pressé.

Toutes les étapes précédentes permettent d’activer et paramétrer l’activation d’une interruption sur la ligne EXTI13 depuis la broche 13 du GPIOC. L’étape suivante est de créer la fonction qui sera appelée lorsque l’évènement configuré sera détecté: c’est qu’on appelle le handler. Pour cela, des noms sont prédéfinis par l’environnement de programmation STM32 permettant de remplir automatiquement le vecteur d’interruptions du NVIC avec l’adresse de la fonction correspondante. Dans le cas de l’évènement EXTI15_10, la fonction est alors:

  void EXTI15_10_IRQHandler(void) {
    // Contenu
  }
Question 6 Vérifiez à présent que votre système fonctionne. En mode debogage, placez un point d’arrêt sur la fonction EXTI15_10_IRQHandler et lancez l’exécution du programme. Que se passe-t-il si vous appuyez sur le bouton-poussoir ?
Question 7 Lorsqu’une interruption a été traitée, il est nécessaire de la remettre à 0. Pour cela, utilisez le bit correspondant dans le registre PR de EXTI.
Question 8 Modifiez le contenu de la fonction pour inverser l’état de la LED à chaque fois que le bouton est pressé.
Question 9 Modifiez le paramétrage de l’interruption pour qu’elle ne s’active que lorsque le bouton est relâché.

Communication main / handler

On aimerait à présent concevoir un système où la fonction main fait clignoter la LED à un rythme variable. Ce rythme pourra ensuite être modifié selon le nombre de pressions effectuées sur le bouton poussoir: plus le bouton est pressé un grand nombre de fois, plus le clignotement accélère ou inversement. Pour cela, nous allons devoir faire des échanges d’informations entre les deux fonctions.

Question 10 Modifiez votre fonction main pour qu’elle fasse clignoter la LED selon la valeur d’une variable tempo.
Question 11 Modifiez votre routine d’interruption appelée par le bouton poussoir pour qu’elle diminue la variable tempo d’une valeur N à chaque exécution.
Aide supplémentaire (si nécessaire)

Les variables locales sont internes à chaque fonction. Les variables globales sont accessibles depuis n’importe quelle fonction.

Question 12 Modifiez votre routine d’interruption appelée par le bouton poussoir pour qu’elle diminue la variable tempo d’une valeur N jusqu’à 0. Si la valeur tempo est déjà à 0, alors la variable tempo doit être augmentée d’une valeur N jusqu’à une valeur maximale libre.
Aide supplémentaire (si nécessaire)

Pour savoir le sens utilisé (augmentation ou diminution de tempo), vous pouvez utiliser une nouvelle variable pour stocker l’information.

Source d’interruption logicielle

Généralement, les évènement déclenchant une interruption sont proviennent d’un composant matériel, souvent extérieur (e.g. par le biais d’une broche de GPIO). Cependant, il est aussi possible de déclencher une interruption du logiciel. Cela peut-être utile pour du débogage, synchroniser plusieurs applications, réutiliser des routines existantes etc. Dans le cas des cartes Nucleo-F446RE, les lignes d’interruptions EXTI peuvent être activées par un évènement extérieur (GPIO) ou alors depuis le logiciel en écrivant dans le registre SWIER d’EXTI.

Question 13 De la même manière que pour le bouton poussoir avec la ligne EXTI13, paramétrez une routine qui s’active lorsqu’une interruption arrive sur la ligne EXTI4. Générez ensuite cette exception depuis le main avec le registre SWIER d’EXTI.
Question 14 En utilisant le registre de priorité IPR du NVIC, modifiez la priorité des interruptions venant de EXTI4 et EXTI13 pour que la seconde puisse pré-emptée la première. En effectuant une exécution en mode debogage, validez ensuite le fonctionnement du système.