Aller au contenu

Micro contrôleurs AVR/Les PORTs

Leçons de niveau 14
Une page de Wikiversité, la communauté pédagogique libre.
Début de la boite de navigation du chapitre
Les PORTs
Icône de la faculté
Chapitre no 3
Leçon : Micro contrôleurs AVR
Chap. préc. :Le langage C pour AVR
Chap. suiv. :Le Timer 0
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Micro contrôleurs AVR : Les PORTs
Micro contrôleurs AVR/Les PORTs
 », n'a pu être restituée correctement ci-dessus.

Le nombre de PORTs disponibles sur les AVR dépend de la série. À part la série TINY qui sont des composants de petites tailles, les AVRs de la série Mega comportent au moins les PORTs B, C et D.

Le PORT pour entrer et sortir des informations

[modifier | modifier le wikicode]

On rappelle que l'opérateur d'affectation = du C est asymétrique. Écrire

var1 = var2; // met la valeur de var2 dans var1

est complètement différent de

var2 = var1; // met la valeur de var1 dans var2

Profitons-en pour rappeler que dans le premier cas, seule la valeur de var1 change (pas celle de var2).

Le registre DDRB

[modifier | modifier le wikicode]

Ce registre est d’un fonctionnement très simple et est lié au fonctionnement du PORTB.

Chaque bit de DDRB positionné à 0 configure la broche correspondante en entrée. Chaque bit à 1 configure la pin en sortie.

Au reset de l'AVR®, toutes les pins sont mises en entrée, afin de ne pas envoyer des signaux non désirés sur les pins. Les bits de DDRB seront donc mis à 0 lors de chaque reset.

Notez que l'entrée est faite à l'aide de PINB et non de PORTB :

PORTB = val;

mais

val = PINB;

Les entrées des PORTx peuvent être connectées à une résistance de rappel au +5 V de manière interne, cette sélection s’effectuant par une écriture dans le registre PORTx (écriture d'un '1' avec bit correspondant en entrée pour pullup et écriture d'un '0' pour désactiver le pullup). Cela veut dire que les pull-up peuvent être choisis individuellement dans un PORT, contrairement aux PIC 16F !

Les registres PORTC et DDRC

[modifier | modifier le wikicode]

Ces registres fonctionnent exactement de la même manière que PORTB et DDRB, mais concernent bien entendu les seules 7 pins PC6 ... PC0. Les seuls 7 bits utilisés sont les bits de poids faibles.

Voyons maintenant les particularités du PORTC.

Les 7 bits de DDRC sont désignés par DDC0 ... DDC6. Mais si vous ne voulez pas vous encombrer la mémoire, utilisez PC0 ... PC6, cela fonctionnera de la même façon !

Des LEDs et des boutons poussoirs sur des PORTs

[modifier | modifier le wikicode]

Le but de cette section est d'étudier quelques connexions électriques à partir des PORTs d'un microcontrôleur. Nous nous contenterons des Diode électroluminescente et des boutons poussoirs.

Le PORT et sa modélisation électrique

[modifier | modifier le wikicode]

Le modèle électrique est très simple : on le modélise comme d'habitude à l'aide de Thevenin.

Il est raisonnable de prendre un Imax de 40 mA pour un ATMega8.

Modèle de Thévenin d'un PORT en sortie
Panneau d’avertissement

Contrairement à ce qu'indique la figure on prendra toujours un Rth de 50 Ohms.

Connecter et dimensionner des LEDs

[modifier | modifier le wikicode]

Une LED (ou Diode électroluminescente) est une diode et par conséquent se modélise de la même manière :

Modèle électrique des LEDs

Retenez les valeurs typiques notées dans la figure pour Ud=1,8 V et rd=0 Ohm.

Il y a deux façons typiques pour connecter des LEDs :

Connexions de LEDs à un microcontrôleur

À gauche c’est le microcontrôleur qui est à l'origine du courant. À droite c’est lui qui reçoit le courant passant par la LED et provenant d'une alimentation. Évidemment, il faut un un logique sur le bit PA1 pour allumer la LED de gauche et un zéro logique sur le bit PA2 pour allumer la LED de droite.

Nous allons essayer de dimentionner R1 dans les montages ci-dessus.

1°) Une led rouge (Kingbright λ = 627 nm 15mcd à 10 mA VD = 1,95 V) est montée comme à gauche sur le bit b0 du PORTB d'un ATMega8. À l'aide du modèle de Thévenin du PORT, on vous demande d'évaluer la résistance R1 à mettre pour avoir un courant ne dépassant pas 5 mA.

2°) Une led verte (Kingbright λ=565 nm 12mcd à 10 mA VD = 2,09 V) est montée comme sur le schéma de gauche (sur le bit b2 du PORTB). Calculer R1 sans prendre l'approximation de Rth pour avoir un courant qui ne dépasse pas les 4 mA.

3°) On désire commander deux leds rouge en série. Faire le schéma et dimensionner correctement la résistance.

Connecter des boutons poussoirs

[modifier | modifier le wikicode]

Il est naturellement possible de connecter des boutons poussoirs à un PORT et de demander au micro-contrôleur de dire si le bouton est appuyé ou relâché. (Sur un robot mobile on peut utiliser ce principe pour détecter des objets)

Connexions de boutons poussoirs à un micro-controleur

Regardez attentivement le dessin de gauche et en particulier la connexion sur le bit PB4. On sait parfaitement ce qu’il se passe si le bouton est appuyé : on est relié à Vcc on aura donc un un logique en lecture. Mais qu'en est-il si on lâche le bouton poussoir ? Tout dépend de la technologie du PORT. La technologie TTL fournirait un un logique donc aucune différence suivant que le bouton est appuyé ou pas !


Il faut donc utiliser une résistance supplémentaire que l’on appelle résistance pullup (ou Résistance de tirage en français). Soit elle existe à l'intérieur du PORT, soit il faut l'ajouter à l'extérieur du PORT.

La gestion des résistances internes de tirage dépend fortement du processeur. Sur le PIC c’est un seul bit pour tous les PORTs. Ici, pour les AVR, il suffit de passer le PORTx en entrée à l'aide du registre DDRx associé d'écrite un '1' logique dans PORTx là où vous voulez la résistance pull-up.

Exemple d'un Microcontrôleur avec des boutons poussoirs et des leds

On connecte deux interrupteurs comme indiqué dans la figure sans utiliser de résistance pull-up interne (puisqu'elle est externe). Les deux LEDs de l'exercice 1 sont elles aussi connectées.

1°) On désire écrire un programme C qui ne fait rien si on n'appuie sur aucun bouton poussoir, fait clignoter la LED rouge si l’on appuie sur un bouton, fait clignoter la led verte si on appuie sur l'autre bouton, et les deux LEDs si l’on appuie sur les deux boutons.

1-a) Donner les 4 valeurs possibles de la variable interrupteurs avec l'instruction

interrupteurs = PINB & 0x60;

1-b) Compléter alors le morceau de code ci-dessous pour en faire un programme :

#undef F_CPU
#define F_CPU 25000000UL
#include "util/delay.h"

leds = 0x00;// variable de gestion des LEDs
// boucle d'attente ATTENTION PB6=1 et PB5=0 au repos
while(interrupteurs == 0x20)
     interrupteurs = PINB & 0x60;
switch(interrupteurs) {
  case 0x60 : PORTB = leds^0x10;break; 
  case 0x00: PORTB = leds^0x80;break;
  case 0x20 : PORTB = leds^0x90;break; // les deux
}
_delay_ms(1000);

2°) Peut-on modifier facilement le programme pour que les deux LEDs fonctionnent à deux fréquences différentes ?

On désire réaliser un dé comme indiqué sur le schéma ci-dessous.

Pour simplifier la lecture du schéma : D1 est relié à PD1, D2 à PD2, D3 à PD3, D4 à PD4, D5 à PD5, D6 à PD6 et enfin D7 à PD7.

1°) Calculer les sept valeurs prédéfinies pour allumer correctement le dé et les ranger dans un tableau si la première case du tableau éteint tout.

Quel est l’affichage du dé correspondant à :

unsigned char tableau[7]={0x00,0x10,0x44,0x54,0xAA,0xBA,0xEE};

2°) Écrire un programme complet qui affiche les 6 valeurs du dé avec un délai d'attente de 3s utilisant la fonction "_delay_ms()" de la librairie libc.

3°) On désire maintenant générer de manière aléatoire le score affiché sur le dé. Pour cela on vous propose d’utiliser la fonction ci-dessous.

unsigned char pseudoAleat(int Lim) {
  unsigned char Result;
  static unsigned int Y=1;
  Y = (Y * 32719 + 3) % 32749;
  Result = ((Y % Lim)+1);//+1 : eviter 0
  return Result;
}

3-a) Calculer la première valeur de cette fonction si Lim=6.

3-b) Écrire le programme général qui génère les valeurs du dé de manière aléatoire dès l'appui du bouton poussoir (attente de 0,3s pour éviter les rebonds).

4°) Proposer un schéma pour réaliser deux dés en utilisant un seul PORT de sortie sur 8 bits. Écrire le programme correspondant.

Interfacer un clavier

[modifier | modifier le wikicode]

Sur un PC, le clavier est complètement décodé. C'est-à-dire que lorsqu'une touche est appuyée, sa position sur le clavier est envoyée sur la liaison PS2. Le fait d'envoyer la position et non le code ASCII permet de gérer les claviers en divers langues.

Clavier 12 touches

Pour de petites applications, on utilise un clavier à 12 touches. Il est composé de simples contacts et le décodage est réalisé par le système informatique. Avec seulement 8 touches, un PORT de 8 bits en entrée suffit. Si le clavier possède plus de 8 touches, il faut:

  • soit utiliser d'avantage d'entrées,
  • soit multiplexer les entrées en deux étapes.

En utilisant 4 fils pour les lignes et 4 fils pour les colonnes, on peut différencier par croisement 16 touches. On utilise donc 8 fils reliés à 8 bits d'un PORT pour 16 touches. Pour nos 12 touches on peut câbler comme indiqué ci-dessus. Il s'agit ensuite de procéder en deux phases, une pour la détection de la colonne et une autre pour la détection de ligne.

Question 1 : détermination du numéro de colonne
[modifier | modifier le wikicode]
#define NOTAKEY 127
// colonne 1 à gauche
char lecture_colonne(){
  char ch;
  DDRB=0xF0; // 1111 0000
  PORTB = 0x00; // B4, B5,B6 et B7  mis à 0 !!! surtout pas 0x0F =>pullup !!!
  ch = PINB & 0x0E; // on ne garde que les bits intéressants B1, B2 et B3
  switch (ch) {
  case 14 : return 0;//aucune touche
  case 6 : return 1;//a gauche
  case 10 : return 2;// au milieu
  case 12 : return 3;//a droite
// si autre cas, deux touches ou autre
  default : return NOTAKEY;
  }
}

Commenter en testant les bonnes valeurs du case.

Question 2 : détermination du numéro de ligne
[modifier | modifier le wikicode]

Programmer les directions avec DDRB (PB7-PB4 en entrée et PB3-PB1 en sortie).

Quel est le code correspondant : sous-programme char lecture_ligne()

Question 3 : détermination du caractère
[modifier | modifier le wikicode]

À partir des deux informations précédentes transformer le numéro de colonne et le numéro de ligne en caractère correspondant sur le clavier : '1' ou '2' ou ... ou '0' ou '#'

Interfacer des éléments de puissance pour faire tourner des moteurs

[modifier | modifier le wikicode]

Quand le courant à sortir dépasse 15 mA (par bit), il faut trouver une solution amplifiée. C'est ce que nous allons examiner dans cette section.

Utilisation de transistors BJT

[modifier | modifier le wikicode]

Pour commander des sorties puissantes il faut ajouter des transistors (BJT Bipolar Junction Transistor). Les sorties puissantes peuvent être :

  • des relais
  • des bobines
  • des LEDs
  • des moteurs
Interfacer des LEds

On veut commander une LED qui nécessite 16 mA. Le transistor choisi a un b de 100.

1°) Calculer IB ?

2°) En déduire R1 (si l’on prend une marge de 30% ou si l’on prend 1 mA par défaut)

3°) En déduire RC pour un VCEsat=0,2 V (pour une alimentation Vcc=5 V) ?

4°) Une résistance RC de 1/4W suffit-elle ?

Interfacer des sorties puissantes avec des FET

[modifier | modifier le wikicode]

On peut utiliser des transistors à effet de champ à la place des BJT. Nous examinons le cas des MOSFET. Un paramètre important à vérifier est la tension de grille nécessaire à la commutation. En effet pour les micro-contrôleur alimenté en 3,3 V cette tension peut s'avérer un peu forte pour des MOSFET de puissance.

Il existe des familles spécialement faites pour être commandées directement par des PORTs. Voir ZVN4206A (600 mA) et ZVN4306A (1,1A) de chez Zetex.

Avec isolation galvanique

[modifier | modifier le wikicode]

Il faut utiliser des opto-coupleurs. Ils permettent aussi une isolation galvanique ce qui est important si la tension d'alimentation est très différente de celle du micro-contrôleur. Cette isolation garantit qu'aucun courant de l'élément de puissance finira dans le micro-contrôleur, ce qui le détruirait.

Commander des bobines moteurs et relais avec BJT

[modifier | modifier le wikicode]

Il existe des transistors de puissance adaptés. Par exemple le transistor BD139 propose un gain b compris entre 25 et 250. On peut l’utiliser avec un courant IC=1,5 A (3A en pointe). Son faible gain nécessite un courant IB assez important, allant au-delà des possibilités des ports traditionnels (typiquement 10 mA). Par exemple pour commuter 1A, il faut un IB=40mA dans le pire des cas. Il faut donc un transistor supplémentaire.

Montage Darlington

Ce montage appelé Darlington existe en boîtier unique : par exemple le BCX38C peut commuter des courants jusqu'à 800 mA.

On considère le montage Darlington ci-contre. Le transistor 2N2222 est bloqué, il circule 40 mA dans IB

1°) Si R2 est choisi à 330 Ohms, quelle puissance passe dans R2 ?

2°) Si le transistor 2N2222 est saturé (VCEsat=0,2 V) quelle puissance passe dans R2 ?

3°) Lorsque le BD139 est saturé, il circule Il circule IC=1A et l’on a VCEsat=0,70 V. Quelle puissance est dissipée dans le BD139 ?

Commander plusieurs moteurs avec un circuit unique

[modifier | modifier le wikicode]

Il existe des circuits capables de commander 7 moteurs comme le ULN2003 qui a à peu près les mêmes caractéristiques que le BCX83C (mais sept fois). Ils sont appelés Darlington driver IC. Le ULN2803 possède 16 broches et peut commander 8 moteurs avec la possibilité d’utiliser deux sorties identiques pour commander un seul moteur.

Le circuit ULN2003 est capable de délivrer 500 mA sous 50 V.

Exemple concret

[modifier | modifier le wikicode]

Voici l'électronique de commande des moteurs du robot mobile ASURO présenté dans un autre chapitre de ce projet. A noter que l’on utilise ici des transistors discrets et non pas un circuit de puissance intégré.

Les deux commandes de moteurs du robot mobile ASURO

On remarquera une commande d'un moteur avec un pont en H qui permet de faire fonctionner le moteur dans les deux sens.

Un exercice sur ce schéma a été ajouté dans le chapitre AVR et robotique : ASURO de ce cours. Cet exercice nécessite cependant une bonne connaissance du timer 1 expliqué dans le chapitre ultérieur.