Les Ports.docx

  • Uploaded by: Adil Abouelhassan
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Les Ports.docx as PDF for free.

More details

  • Words: 2,095
  • Pages: 6
Les ports Eskimon , le ven. 03 décembre 2010 (0 commentaire) arduino tuto Partons dans les entrailles du microcontrôleur en allant à la rencontre d’une mémoire un peu particulière : les registres. Dans notre cas nous allons parler des ports, un registre servant à gérer les entrées/sorties de la carte.

Sommaire 

Utiliser les ports

Utiliser les ports Dans cette partie nous allons voir une technique avancée de programmation de microcontrôleur. Bien qu’elle soit sans danger pour votre matériel, une mauvaise manipulation concernant la liaison série peut arriver et apporter des complications au niveau du chargement du programme (nous allons voir pourquoi). Soyez donc prudent et codez en connaissance de cause. Bien entendu, je vais tout vous expliquer pour que vous réussissiez sans problèmes !

Retour aux sources Vous vous souvenez, lorsque nous avons introduit la notion de "microcontrôleur" ? On a parlé de différentes choses qui se trouvaient à l’intérieur de ce composant et notamment des registres, en expliquant brièvement que ce sont des sortes de mémoires spécifiques… eh bien en voici un exemple complet : les ports . Ces derniers sont en effet des bits au sens le plus strict qui soit puisqu’ils traduisent directement l’état et le comportement des sorties. Ces bits servent donc à configurer vos entrées/sorties et à lire/écrire dessus. Ils sont accessibles directement et ont un effet immédiat sur l’électronique de votre microcontrôleur. En clair, c’est passer au travers de fonctions déjà toutes prêtes pour appliquer directement ce que vous voulez faire avec votre microcontrôleur. Cela revient à rentrer dans le détail et à coder façon "bas niveau". Par exemple, lorsque vous direz "mets ce bit à 1 (ou 0)" vous irez en fait activer (ou désactiver) un transistor à l’intérieur du microcontrôleur, ce qui aura pour effet de basculer la sortie à l’état haut ou bas. Lorsque vous utilisez les fonctions pinMode() ou digitalRead() ou digitalWrite(), sans le savoir vous utilisez en fait les registres en question. La seule différence est que certaines opérations de contrôle sont faites pour s’assurer que vous ne fassiez pas trop de bêtises. Des bêtises ? des vérifications ? je vais casser quelque chose ? Non rassurez-vous

.

Les avantages d’utiliser les ports

Lorsque l’on décide d’utiliser les ports plutôt que les fonctions d’abstractions digitalWrite(), on le fait souvent avec une bonne raison (et vous comprendrez pourquoi en lisant les inconvénients). Voici deux grandes raisons qui pourraient vous inciter, dans des cas précis, à vouloir utiliser les ports : 



Dans le cas où vous rédigez une application qui possède un côté critique au niveau du temps (par exemple la broche 3 et la broche 4 doivent basculer de manière synchrone sinon le message ne passe pas), l’utilisation des ports est faite pour vous ! En effet, comme dit plus haut contrairement à digitalWrite() , ici vous agissez directement sur le matériel, sans abstraction. Du coup ça va plus vite ! (là ou il pourrait s’écouler quelques précieuses micro-secondes entre deux digitalWrite() consécutifs) Si votre code rentre au chausse pied dans le microcontrôleur et que gagner quelques octets de mémoire programme vous arrangerait bien, là encore jouer avec les registres est une solution. En effet, chaque appel àdigitalWrite() représente plus d’instructions machines qu’un appel direct au port. Au bout d’un code assez conséquent, il peut donc s’avérer utile de passer par les ports pour sauver quelques octets à chaque fois (en particulier si les fonctions digitalWrite() sont très souvent utilisées à plein d’endroits différents).

Les risques et inconvénients à connaître

Vous avez décidé que finalement utiliser les ports c’était pas si mal, et en valait la peine ? Voyons pourquoi vous feriez-mieux d’y réfléchir une deuxième fois…  



Inconvénient n°1 : Votre code va devenir difficile à relire. En effet, utiliser les ports nécessite d’écrire des lignes du genre PORTD |= B00000100; là où un simple digitalWrite(2) aurait fait l’affaire. Inconvénient n°2 : Votre code devient moins portable. Les registres utilisés peuvent changer (de nom, d’adresse, etc…) entre les gammes de microcontrôleur. D’ordinaire, c’est la fonction digitalWrite() qui justement s’assure que tout est bien fait. En écrivant directement dans les registres, vous court-circuitez les vérifications et donc vous devez vous assurer vous-même de bien écrire pour activer les bonnes entrées/sorties (sous peine d’activer la mauvaise I/O ou même de ne pas compiler tout court ) Inconvénient n°3 : Vous allez vous arracher les cheveux ! Lorsqu’on joue avec les ports, on doit faire des opérations en binaire avec des masques. Il est très rapide de faire une erreur et de ne plus rien comprendre. La plus triste d’entre elles serait de bidouiller les broches utilisées par la liaison série et de se retrouver sans liaison série (ce qui d’ailleurs pourrait rendre difficile la reprogrammation de la carte…)

Mais, si vous ne manquez pas de rigueur, vous trouverez toutes les informations nécessaires relatives au microcontrôleur que vous utilisez. Donc le risque est amoindri et vous savez ce que vous faites. OK j’ai bien compris tout ça et c’est bien gentil, mais concrètement on fait quoi ? Concrètement, vous allez agir sur 3 données particulières qui s’appellent DDR, PORT ou encore PIN. Voyons maintenant à quoi elles servent et comment nous allons nous en servir…

Utilisation des ports

Vous êtes encore là ? Vous n’avez pas froid aux yeux, j’aime ça ! (ou simplement curieux ou inconscient, ça marche aussi

). Puisque vous êtes là, continuons, voyons voir les étapes

nécessaires à cette utilisation mystique des broches… Tout d’abord, sachez qu’il y a trois registres à manipuler pour réussir à se servir des broches. Un premier registre, DDR , servira "d’aiguillage". Ensuite deux autres serviront à lire ou écrire sur une broche, ce sont PORT etPIN . Dans une Arduino Uno, ces trois registres existent en trois exemplaires, le B, le C et le D. B sert pour les broches numériques 8 à 13, C pour les broches analogiques et D pour les broches 0 à 7. Le registre DDRx

Comme je viens de le dire, DDR sert d’aiguillage. C’est lui qui permet de définir l’utilisation d’une broche en entrée, ou en sortie, tout comme le faisait la fonction pinMode(). Un 0 signifie "entrée" et un 1 signifie "sortie". Chaque broche d’un même port étant commandée par ce registre. Au début de votre programme, vous avez la fonctionpinMode() pour définir l’utilisation des broches. Admettons que vous souhaitiez utiliser les broches 4, 5 et 6 en sortie et aussi 13 et 11 ainsi que les broches analogiques 2 à 4. Pour cela, vous auriez d’ordinaire écrit : void setup() { //définition des broches suivantes utilisées en sortie logique pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(11, OUTPUT); pinMode(13, OUTPUT); pinMode(A2, OUTPUT); pinMode(A3, OUTPUT); pinMode(A4, OUTPUT); }

Plutôt long et fastidieux non ? Avec les ports tout cela tiendra en 3 lignes, une par port. Pour cela, imaginez que les entrées/sorties soient représentées chacune par un bit dans un octet. Par exemple pour le registre D qui représente les entrées/sorties de 0 à 7, on pourrait avoir 00110010. Les numéros des broches sont ensuite les mêmes que ceux des bits, le poids faible sera la broche 0 et le poids fort la broche 7. Donc pour mettre les broches 4, 5 et 6 en sortie (donc les autres en entrée) on fera : PORTD = B01110100;

Le B devant la suite de 0 et 1 signifie que l’on donne un nombre binaire. On pourrait également donner un nombre hexadécimal en mettant un 0x suivi de deux caractères hexadécimaux. Dans la même lignée, nous pouvons donc déclarer l’utilisation de toutes les entrées/sorties précédentes :

DDRD = B01110100; // 0 (poids faible) vers 7 (poids fort) DDRC = B00011100; // A0 (poids faible) vers A5 (poids fort) DDRB = B00101000; // 8 (poids faible) vers 13 (poids fort)

Le registre D possède l’accès aux broches de la transmission série. Je vous recommande très fortement de toujours laisser ces derniers à 1 (pour le Tx) et 0 (pour le Rx), pour faire DDRD = xxxxxx10 si vous ne voulez pas avoir de mauvaises surprises… Le registre PORTx

C’est maintenant que l’on s’amuse

. En effet, c’est ici que l’utilisation des ports va prendre

tout son sens… Imaginons que vous vouliez basculer à l’état haut toutes les sorties 2, 3, 5 et 7 en même temps . Vous pourriez utiliser plusieurs fois digitalWrite(x, HIGH) mais il risque de se passer quelques microsecondes entre chaque action. Nous allons donc utiliser le registre PORT pour faire cette opération. Tout d’abord, on définit les broches en sortie (encore une fois, attention aux deux derniers bits pour la liaison série) : void setup() { DDRD = B11111110; // Tout le monde (de 1 à 7) en sortie ! }

Ensuite, au moment d’exécuter notre programme nous allons juste avoir à utiliser PORTD pour actionner les sorties. Par exemple en faisant : PORTD |= B10101100; //2, 3, 5 et 7 à l'état haut

Avez-vous remarqué ? J’ai utilisé l’opérateur OU (|) pour actionner uniquement les sorties qui m’intéressaient tout en ignorant les autres. Cela doit vous rappeler des opérations de masquage que l’on avait vu un peu plus tôt, dans un chapitre précédent. Maintenant, je vais au contraire utiliser l’opérateur antagoniste ET (&) pour mettre à l’état bas les sorties précédentes. PORTD &= B01010011; //2, 3, 5 et 7 à l'état bas

Je mets ainsi à zéro les broches qui m’intéressent en ignorant l’état des autres. C’est en tout point l’inverse du précédent ! Avec les ports (et les registres en général) les opérateurs de masquage ET et OU sont très importants à connaître et à maîtriser. Le registre PINx

Bon c’est chouette, vous savez modifier toutes les broches en une seule fois, mais savez-vous les lire en une seule fois ? Pour cela, il faut d’abord mettre quelques broches en entrée pour qu’elles puissent être lues. Je vous propose de reprendre celles de tout à l’heure (2, 3, 5 et 7) : void setup()

{ DDRD = B00000010; // Tout le monde (de 2 à 7) en entrée ! }

Ensuite, pour lire les données présentes sur ce port, il faut utiliser le dernier registre de cette leçon qui s’appelle PIN. Par exemple, pour stocker l’état des sorties dans un octet on fera : char lePort = PIND;

C’est cool mais moi je ne veux qu’une certaine broche dans ma variable, comme avec digitalRead() ! Et à votre avis ? on fait quoi ? Et bien oui, on masque ! Pour obtenir la broche 3 uniquement par exemple, on fera : char monEntree = PIND & B00001000; //sélectionne le bit 3 uniquement

Et c’est tout !

**************************=========================*****************************

Ports are groups of pins. In the arduino, pins 0-7 are controlled by port D and pins 8-13 are controlled by port B. Advantages of using ports: Faster than going per pin, takes up less code for a smaller program Disadvantages: Harder to use and debug I arbitrarily chose port D as my port. Some basic things to keep in mind for using ports Variables (X should be replaced by the correct port letter) DDRX -- Data Direction Register -determines which way data should flow for each pin on the port (0 is input, 1 is output) PORTX--Data register --holds what data is being output/input to the pins PINX --Input pins register The pins in the register are arranged from lower number = Least Significant Bit to Highest number - Most Significant Bit (so to get pins 0-3 to equal 0 and 4-7 to equal 1 it would be PORTD = B11110000)

Example Code int delayTime = 333; //It's better coding style to not have any hardcoded constants like in the previous example byte portD_HIGH = B11111000; byte portD_LOW = B00000000; void setup() { DDRD = DDRD | B11111100; //Sets up the pins for output //a look at what we just did //the | symbol is used as bitwise OR (if either bit is 1, result will be 1) //this goes through the register, ORing each bit with the binary to the right of the | //the B makes the compiler read the 11111100 as binary //So in summary it sets pins 2-7 to Output and leaves 1 and 2 (which sometimes //have special functions) alone } void loop() { PORTD = portD_HIGH; //sets pin ledPin High (so pin 13 is set to 1) delay(delayTime); //waits 333ms or ~1/3 sec PORTD = portD_LOW; //sets pin ledPin to Low (so pin 13 is now equal to 0) delay(delayTime); //waits another 333 ms } //end of the loop subroutine, so it will now go back to the beginning

Related Documents

Les
May 2020 44
Les
June 2020 42
Les Droits Et Les Devoirs
December 2019 54
Les Parents Et Les Enfants
December 2019 49
Les Jeunes Et Les Vacances
December 2019 52

More Documents from ""