• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 16/05/2019

Découvrez les principaux périphériques d’un microcontrôleur autour d’un exemple

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Exemple d’un microcontrôleur et listing des périphériques utiles pour capteurs et actionneurs

Vous allez travailler avec un dispositif du fabricant Microchip. Le composant 18F45K20 est disponible sur une carte de développement, suffisante à notre propos.

PICKit 2 Programming Header
PICKit 2 Programming Header.

La fiche constructeur du PIC 18F45K20, comme de tout microcontrôleur, est votre guide pour le mettre en œuvre. Tout y est décrit et nous n’évoquons ici que les éléments principaux.

Le schéma symbolique du microcontrôleur est assez complexe. La figure suivante décrit l'agencement de registres et de fonctions. Les bus qui portent les signaux sont également détaillés avec leurs tailles respectives. Les ports d'entrée/sortie sont à droite.

18F45K20
18F45K20

Le microcontrôleur est une sorte d’automate, mû par des lignes d’instructions et qui organise la vie de différents périphériques, internes ou externes. La mémoire programme est symbolisée à gauche vers le haut de la figure. Il n'en sort principalement que des instructions. Nous n'entrons pas dans le détail du squelette du microcontrôleur, parce que ceci n'est pas nécessaire pour la compréhension ni l'usage des périphériques, mais vous comprenez à la vue de la figure ci-dessus, qu'il s'agit d'un système complexe. C'est à l'image des tâches qu'il peut remplir : il s'agit bien de l'intelligence du système embarqué.

Un périphérique est une fonction qui produit des signaux logiques, que d’autres périphériques vont utiliser. Par exemple, le port D d’entrée/sortie sur lequel des LED sont connectées. Vous remarquerez la présence de résistances, prévues pour limiter le courant comme il a déjà été dit. La valeur de la résistance dépend de l'éclairement qu'on souhaite donner à la LED.

:ninja: Petit détail encore : un "jumper" figure à la connexion avec la masse du circuit (sur la carte de développement). Ce jumper permet mécaniquement de déconnecter les LED sans avoir à les dessouder.

LEDs
LED

L’organe profond qui agit comme un maître d’œuvre est l’unité de décodage des instructions.  Ces instructions constituent le « programme à exécuter », stocké dans la mémoire programme. Ce décodeur comprend l'instruction en cours, et émet des signaux de contrôles à travers le système, qui conduisent à produire un résultat. Ce résultat dépend de l'instruction, comme par exemple stocker une valeur dans un registre. L'accumulation de ces petites actions mène à un grand programme. Heureusement, tout dépendra du langage utilisé pour décrire le programme. Notamment le langage C décrira des actions macroscopiques, compréhensibles par le concepteur mais malheureusement pas par l'unité de décodage des instructions. Il y a donc un traducteur qui associera des instructions de bas niveau à chaque macro-instruction venant du code C : c'est le compilateur de code.

Décodeur d'instructions
Décodeur d'instructions.
Synoptique simplifié du microcontrôleur
Synoptique simplifié du microcontrôleur.

L’ instruction est composée de 16 bits et sous-divisée en 4 catégories. Avec la figure suivante, intéressons-nous aux instructions liées au mot (byte en anglais) : ceci est contrôlé par 6 bits dans l'instruction, nommés OPCODE. Le mot sur lequel porte l’opération est désigné par son adresse dans la mémoire du microcontrôleur, FILE, sur 8 bits. Enfin, le résultat de l’opération peut être écrit à deux endroits désignés par le bit d.

Format d'une instruction traitant un mot (byte)
Format d'une instruction traitant un mot (byte).
Instruction d'incrémentation
Instruction d'incrémentation.

En gros, la partie opérative du microcontrôleur va exécuter plusieurs actions à l’intérieur du dispositif pour parvenir à ce résultat. Primo, le registre VAR est pointé et le contenu de ce registre est apporté à l’entrée f de l’unité arithmétique et logique. Secundo, la valeur est incrémentée par l’unité arithmétique et logique, et le résultat est écrit dans le registre W.

Abrégé de la séquence d'actions cachées par l'exécution de l'instruction INCFVAR
Abrégé de la séquence d'actions cachées par l'exécution de l'instruction INCFVAR.

Lien entre documentation et code pour la mise en œuvre d’un périphérique. Simulation avec MPlabX

 Le microcontrôleur embarque une variété plus ou moins grande de périphériques, liés ou pas à des broches (ou pins) d’entrée/sortie.

Les ports d’entrée/sortie sont des périphériques, pour lesquels la fiche constructeur donne un schéma électrique fonctionnel. Celui-ci est un peu complexe car il illustre tous les modes de fonctionnement possible du port. Il y en a beaucoup, mais dans un usage courant, seuls deux modes sont sollicités, suivant que le port serve à accéder à un signal (entrée) ou qu'il délivre un signal (sortie). Des signaux numériques contrôlent le schéma électrique du port.

Par exemple, le registre TRISD va définir si le port D agit en entrée (il est lu) ou en sortie (il faut écrire une valeur).

Schéma d'un port I/O
Schéma d'un port I/O.

La donnée à lire ou à écrire va se trouver dans un autre registre, comme PORT D ; enfin, il est possible de contrôler le verrouillage des données via le registre LATD.

Par l'instructionVAR equ 0x024, l’utilisateur identifie dans le code une étiquette nommée VAR, à l’adresse 024 en hexadécimal. L’étiquette sera utilisée tout le long du code pour manipuler une donnée particulière.

Mécanisme des étiquettes
Mécanisme des étiquettes.

L’étiquette pointe sur une case dans laquelle la donnée est écrite ou lue (figure ci-dessus à droite). Les instructions permettent d’identifier données et étiquettes, pour simplifier l’édition du code. L’instruction  CLRF TRISD  met à zéro chacun des bits de l’octet pointé par l'étiquette TRISD, et en conséquence tous les bits du port D seront configurés en sortie.

Dans cet exemple ci-dessous en langage C, la première instruction  TRISDbits.TRISD7=0;  agit sur le registre TRISD, pour changer la valeur du bit n° 7, de telle sorte que la broche n° 7 du port D soit configurée en sortie.

Macroinstruction pour configurer un bit d'un port I/O
Macro-instruction pour configurer un bit d'un port I/O.

La deuxième instruction fera de même pour le bit 0 de TRISD, avec la broche n° 0 de PORTD configurée alors en sortie. Une instruction peut dorénavant écrire sur le PORTD, par exemple un 1 logique sur le bit 7.

Macroinstruction pour délivrer une valeur en sortie d'un port I/O
Macro-instruction pour délivrer une valeur en sortie d'un port I/O.

Notion d’interruption matérielle et logicielle. Exemple d’un chenillard avec choix du motif par bouton poussoir. Simulation sous MPlabX

L'organigramme suivant active les broches d'un port I/O dès qu’un bouton a été activé. Après des initialisations sur lesquelles nous reviendrons, le programme doit placer certaines variables dans un certain état avant d'attendre qu'un bouton poussoir soit activé (appuyé). Ceci doit déclencher l'activation de la série de LED pendant UNE seconde.  Deux cas se présentent :

  • l'utilisateur a maintenu le bouton poussoir appuyé. Une temporisation est activée pour détecter en boucle si le bouton poussoir est toujours activé. Dans cette boucle, la série de LED reste dans son état pendant UNE seconde avant le test de l'état du bouton poussoir ;

  • si le bouton poussoir est relâché avant la fin de la temporisation, la série de LED est éteinte et le programme se positionne en attente de l'activation du bouton poussoir ;

  • si le bouton n'est pas relâché avant la fin de la temporisation, le programme le signale à l'utilisateur par un clignotement bref de la série de LED. En effet, le programme éteint la série de LED puis reprend le cours de corps principal du programme, à savoir qu'il teste l'état du bouton poussoir (il est appuyé !) et allume de nouveau la série de LED pour reprendre le cheminement des tests.

Organigramme pour contrôler l'éclairage successif d'une série de LEDs
Organigramme pour contrôler l'éclairage successif d'une série de LED. 

Le programme assembleur ci-dessous, que vous avez déjà vu, utilise l’instruction  Bit Test Skip if Clear  pour lire le bit n°0 du port B puis, si le bouton n’est pas activé, c’est-à-dire que la valeur du bit n° 0 du port B est à une valeur haute (vrai, c'est-dire 1 logique), alors l’instruction  goto  qui suit n’est pas ignorée, et la boucle recommence. Le programme fait du sur-place.

Test de la valeur d'un bit d'un port I/O
Test de la valeur d'un bit d'un port I/O.

Le microcontrôleur offre un mécanisme pour pallier cette situation : il s’agit du mécanisme d’interruption. Le bouton poussoir est transformé en source d’interruption : quand le bouton est activé, l’interruption devient active et signale cet évènement au programme principal, qui agit alors en conséquence. Le programme principal peut donc faire tout un tas de choses en ignorant le bouton poussoir, jusqu'à ce que le mécanisme d'interruption change le cours des choses :

Mécanisme d'interruption sur le niveau du bouton poussoir
Mécanisme d'interruption sur le niveau du bouton poussoir.
  • tant que l’interruption n’est pas activée, le programme principal se déroule normalement ;

  • quand l’interruption est activée, le programme principal est stoppé là où il est, et un code spécial, lié à l’interruption, est alors exécuté ; c'est une routine d’interruption ;

  • une fois que la routine a été déroulée,  le programme principal reprend normalement à l’instruction qui avait été suspendue. 

o_O Regardons comment l’interruption interagit avec le programme.

Un registre essentiel au bon déroulement d'une interruption (comme du reste d'ailleurs!) est le Program Counter. Celui-ci contient, à tout instant, l’adresse de l’instruction à exécuter derrière celle qui est en cours. Le champ d’adresses dépend du microcontrôleur. Des adresses particulières sont réservées.

En particulier, au RESET du microcontrôleur, le PCProgram Counter – prendra la valeur  h0000. Le code informatique doit donc avoir une instruction à cette adresse, c’est souvent un  goto. Le reste du code est implanté à la première adresse autorisée qui suit.

Program Counter et adresses d'implantation du code assembleur
Program Counter et adresses d'implantation du code assembleur.

Les routines d’interruption sont exécutées quand le Program Counter prend une adresse particulière appelée vecteur d’interruption. Il y en a au moins une possible, et davantage en fonction du microcontrôleur.

Vecteurs d'interruption
Vecteurs d'interruption.

Le bout de code en langage C suivant décrit qu’à l’adresse h0008 sera placée une instruction  goto :

// High priorityinterruptvector
#pragmacode InterruptVectorHigh= 0x08
void InterruptVectorHigh(void)
{
_asm
gotoInterruptServiceHigh //jump to interrupt routine code
_endasm
}

Il y a 10 registres spéciaux impliqués dans le mécanisme des interruptions. Les bits de ces registres sont imbriqués dans un système logique à la fois compliqué et simple. Il est compliqué parce qu’il y a une grande quantité de signaux en jeu, mais il est simple dans son organisation, comme nous le verrons dans un exemple par la suite.

Synoptique logique des registres impliqués dans le mécanisme d'interruption
Synoptique logique des registres impliqués dans le mécanisme d'interruption.

Le vecteur de haut niveau ne sera activé que si le bit GIEH/GIE est activé dans le registre INTCON.

Par exemple, le convertisseur analogique/numérique, à la fin d’une conversion, peut indiquer qu’une donnée est disponible par une interruption. Il faudra un nombre assez important de drapeaux (flag) et d’autorisations, comme l’AD Interrupt Enable.

Interruption par le convertisseur A/D
Interruption par le convertisseur A/D.

Exemple d'un code pour un chenillard de LEDs

Prenons l'exemple d’un chenillard avec le choix du motif par bouton poussoir. La simulation sera faite sous le logiciel propriétaire mais gratuit, MPlabX :

Code principal avec l'usage d'interruptions
Code principal avec l'usage d'interruptions.

Le port D du microcontrôleur active 8 LED, allumées successivement. Un octet – LED_display  est écrit dans le port D au rythme d’un timer, périphérique que nous détaillerons par la suite.

Il s’agit d’un chenillard. :magicien:

Un bit, appelé Direction, gère le sens de défilement du chenillard. Enfin, un potentiomètre fixe la vitesse de défilement du chenillard à travers une lecture par le convertisseur A/D.

Intéressons-nous en particulier au bouton poussoir connecté à la broche RB0, comme source d’interruption pour fixer la direction du chenillard :

  • le code principal définit le port D en sortie ;

  • alors que le bit 0 du port A (pour l’ADC) et du port B (pour le bouton poussoir) sont définis en entrée ;

  • le mécanisme d’interruption est mis en place en choisissant correctement les signaux relatifs à INT0. En particulier, le drapeau d’interruption INT0IF  (interrupt-flag) est mis à 0 avant que l’interruption ne soit autorisée par INT0IE (interrupt-enable).

  • l’autorisation de haut niveau de l’interruption est enfin donnée à travers  INTCONbits.INT0IE=1;

À partir de là, le programme ne fait que rafraîchir le port D. Aux routines interruptions de faire le reste.

Lors d’une interruption sur INT0 :

  • il y a d’abord vérification de l’origine de l’interruption ;

  • la remise à zéro du drapeau d’interruption ;

  • puis exécution de la routine avec le changement de direction du chenillard. 

Exemple de certificat de réussite
Exemple de certificat de réussite