TP01

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 12

TP1 : Initiation aux interruptions

1 Objectif
1. Manipuler les API destinées aux GPIO,
2. Gérer les interruptions,
3. Configurer le NVIC.

2 Principe
Une interruption matérielle (en anglais Interrupt ReQuest ou IRQ) est une interruption déclenchée par
un périphérique d'entrée-sortie d'un microprocesseur ou d'un microcontrôleur.

Les interruptions matérielles sont utilisées en informatique lorsqu’il est nécessaire de réagir en temps
réel à un événement asynchrone, ou bien, de manière plus générale, afin d’économiser le temps
d’exécution lié à une boucle de consultation (polling loop).

Les étapes d’une interruption sont résumées par la figure suivante :

1. Une interruption peut être activée d’une manière asynchrone au déroulement du programme
principal. Ici symbolisée par un éclair jaune sur la figure,
2. Après sauvegarde de contexte le processeur passe en mode exception et exécute la fonction
qui correspond à l’exception activée (une interruption est une exception). Le processeur
récupère l’adresse de la fonction « handler » à partir du « vector table » qui contient les
adresses des fonctions qui gèrent toutes les exceptions software et matérielles.
3. Une fois l’interruption est servie, il y a restauration de contexte,
4. Retour au programme principal.

Le processeur Cortex ARM contient un composant nommé « Nested Vectored Interrupt Controller
(NVIC) ». Il supporte jusqu’à 240 interruptions. Il offre 255 niveaux de priorités programmables de
0 à 255 avec 255 la priorité la plus faible. Les priorités sont hiérarchisées en deux groupes. Un
premier groupe de priorité de 0 à 15. De la même manière chacun de ces groupes contient un
sous-groupe de priorité de 0 à 15. Le NVIC est sensible aux niveaux de tensions et aux différents
fronts, montant ou descendant.

Le travail demandé dans ce TP permettra de tester une solution avec polling pour commander une
diode LED avec un bouton utilisateur puis avec une solution basée sur une interruption hardware.
Dans la troisième partie le NVIC sera programmé pour donner deux priorités différentes au bouton
utilisateur et au « system tick handler » responsable d’incrémenter le « system tick counter »
chaque 1 ms.
3 Création d’un projet
1. Suivre les mêmes étapes du TP initiation aux GPIO pour créer un projet,
2. Sélectionner sous le menu « Project » -> « Manage » -> « Run-Time Environment »,
sélectionner « LED API » et « Button API » et il est important de préciser la board « STM32F4-
Discovery » (voir figure suivante).

Cliquer sur « Resolve » et cocher « Classic » sous « STM32Cube Framework (API) » puis sur
« OK ».
3. Suivre les mêmes étapes du TP initiation aux GPIO pour ajouter les dossiers « sources » et
« headers », ajouter les fichiers « main.c » , « main.h », «stm32f4xx_it.c » et «stm32f4xx_it.h »
4. Cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug » afin de
configurer les options de la carte cible sur laquelle le programme sera exécuté. Cette fenêtre
fait apparaître deux options de test : par simulation (à gauche), ou par émulation (à droite), en
utilisant la carte STM32F407VG. Selectionner l’option émulation (à droite), cocher le bouton
« use » et sélectionner « ST-Link Debugger ».
Cliquer sur le bouton « Settings » et vérifier, sous l’onglet « Debug », que le port utilisé et de type
« SW », sinon le changer.

Cliquer sur l’onglet « Flash Download » de la même fenêtre, et vérifier que la taille de la mémoire Flash
de la cible est de 1 M on Chip.

Cliquer sur l’onglet C/C++ et ajouter le macro « HSE_VALUE=8000000 » qui indique la fréquence du
Crystal installé sur la carte à la fonction « SystemClock_Config(); » qui se trouve par défaut dans le
« Template » du « main.c »
Cliquer sur « OK » pour valider les options de configuration du Debugger choisies.

Re-cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug ». Cliquer sur « Settings »
puis « Trace » changer la fréquence « Core Clock » à 168MHz et cocher la case « Trace Enable » puis
sur « OK ».

A ce stade le code doit être compilable sans fautes.


4 Travail demandé
Partie 1 : Solution avec pooling

1. Au niveau de la ligne 109 du fichier « main.c » ajouter l’appel des fonction suivantes :
« Buttons_Initialize() » et « LED_Initialize() ». Ceci permettra ensuite l’utilisation des LEDs et
du Bouton utilisateur de la carte d’évaluation.
2. A l’aide d’une boucle infinie dans le fichier « main.c » tester la valeur du bouton utilisateur
puis inverser l’état de la LED0. Identifier dans le fichier « Buttons_F4Discovery.c » la fonction
qui retourne la valeur du bouton utilisateur.

Remarquer qu’avec cette solution le processeur est entièrement dédié à la lecture de l’état de la
pine relative au bouton utilisateur. Ceci est un gaspillage des cycles processeur et c’est pour cela
on se propose d’utiliser une solution avec interruption dans la partie 2.

Partie 2 : Solution avec interruption

1. Copier le contenu de la fonction « int32_t Buttons_Initialize (void); » pour créer dans le


fichier main une nouvelle fonction appelée « int32_t Buttons_Initialize_Int(void ); »
2. Dans le corps de la nouvelle fonction cliquer sur le bouton droit de la souris sur la macro qui
définit le mode de la pine PA0 relative au bouton utilisateur puis sur « Go to Definition ».

3. Choisir le bon paramètre pour configurer la pine PA0 en mode interruption sur front montant.
En changeant le mode «GPIO_MODE_INPUT » par « GPIO_MODE_IT_RISING » définis dans le
fichier « stm32F4ww_hal_gpio.h ».
4. Ouvrir le fichier « stm32F4xx_it.c » , lire attentivement le commentaire qui se trouve à la ligne
176. Puis aller sur le fichier indiqué par le commentaire et ajouter une fonction vide avec la
signature adéquate pour gérer l’interruption du bouton PA0. Noter bien que les interruptions
générées par les GPIO sont considérées comme des interruptions Externes et que toutes les
pines du même index sont connectées à la même ligne d’interruption.
5. Ouvrir l’onglet « {}function » trouver la fonction du driver HAL qui gère les interruptions des
GPIOs et faire appel à cette fonction dans le corps de celle créée au point 4.

6. Dans le fichier main.c redéfinir la fonction la fonction « void HAL_GPIO_EXTI_Callback(uint16_t


GPIO_Pin); ».
A l’intérieur de cette fonction utiliser « void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx,
uint16_t GPIO_Pin) » pour changer la valeur de la LED0.
7. Ouvrir l’onglet « {}functions » et trouver dans le driver HAL Cortex qui gère le NVIC la fonction
nécessaire pour activer l’interruption relative à la pine PA0 du bouton utilisateur.
8. Appeler cette fonction dans la fonction « int main(void) » après l’initialisation du bouton
utilisateur. Trouver le bon argument à cette fonction en faisant un clic droit sur le type de
l’argument puis « Go to definition ».
9. Dans la boucle « while(1) » de la fonction « int main(void)» utiliser la fonction « void
HAL_Delay(__IO uint32_t Delay) » pour faire clignoter la LED1 avec une période de 500ms.
Ceci permettra de vérifier que le programme fonctionne.

10. Complier et charger le programme dans la carte. Appuyer sur le bouton Reset (bouton noir).
Vérifier que la LED1 (Led orangée ) clignote et que le bouton utilisateur (bouton bleu)
permet de changer l’état de la LED0 (Led verte).
11. Ajouter une temporisation de 5ms dans la fonction « void HAL_GPIO_EXTI_Callback(uint16_t
GPIO_Pin); ». re-exécuter le programme. Appuyer sur le bouton et constater.
12. En effet, le programme arrête de tourner car les priorités de l’interruption du bouton
utilisateur et de l’interruption qui incrémente le compteur « system tick » (voir la fonction
« SysTick_Handler » à la ligne 170 du fichier « stm32F4xx_it.c ») n’ont pas été modifiées pour
donner la priorité à l’incrémentation du temps par rapport au bouton utilisateur.
Ajouter les deux lignes suivantes juste après l’activation de l’interruption du bouton
utilisateur :
HAL_NVIC_SetPriority(EXTI0_IRQn,15,15);
HAL_NVIC_SetPriority(SysTick_IRQn, 14 ,0);
En effet, ceci permet de donner une priorité supérieure à l’incrémentation du temps par
rapport à l’interruption du bouton.
13. Re-exécuter le programme et vérifier que le programme continue à tourner malgré l’appel de
la fonction « HAL_Delay() » dans la fonction call-back.

Partie 3: Filtre anti-rebonds

Les boutons poussoirs peuvent engendrer des rebondissements électriques à l’entrée de la pine (voir
figure suivante)

Pour éviter ce problème on va ajouter un filtre de temps pour ne considérer que les impulsions dont
la durée est supérieure à 20ms.

1. De la même façon que le point 1 de la partie 2 créer une fonction « int32_t


Buttons_Initialize_Int2(void); ». Cette fonction permet de configurer le bouton utilisateur
d’une manière à générer une interruption sur les deux fronts montant et descendant.
2. Ajouter deux variables globales :
volatile unsigned char Button_status=GPIO_PIN_RESET;
volatile unsigned int Button_Count=0;
La première permettra de lire l’état du bouton utilisateur et la deuxième de compter la durée
du bouton à l’état ‘1’ logique. Le mot clé « volatile » indique au compilateur que ces deux
variables peuvent être modifiées par des interruptions matérielles.
3. Sachant que la fonction « void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) » sera appelée au
front montant et descendant du bouton utilisateur, modifier son code pour récupérer l’état
du bouton et tester la largeur de l’impulsion.
4. Compiler le projet puis ouvrir une session de débogage. Dans le fichier « main.c » cliquer avec
le bouton droit de la souris sur la variable globale « Button_status », puis sur « Add
‘Button_status’= to … », puis « logic analyzer ».
5. Dans la fenêtre « Logic Analyzer » sélectionner la variable à visualiser « Button_status » puis
cliquer sur « setup ». Changer les paramètres « Display Range » entre 0 et 1. Le « Display
Type » doit être analogique. Cocher les « check box » comme indiqué dans la figure.

6. Exécuter le programme en appuyant sur la touche F5. Vérifier que la LED1 (Led orangée )
clignote et que le bouton utilisateur (bouton bleu) permet de changer l’état de la LED0 (Led
verte) si la durée de l’impulsion est supérieure à 20ms. La durée de l’impulsion peut être
observée sur le « logic Analyzer ».

Vous aimerez peut-être aussi