Catégories: Circuits microcontrôleurs
Nombre de fois vus: 41940
Commentaires sur l'article: 5

Méthodes de lecture et de gestion des ports d'E / S Arduino

 

Pour interagir avec le monde extérieur, vous devez configurer les sorties du microcontrôleur pour recevoir ou transmettre un signal. Par conséquent, chaque broche fonctionnera en mode d'entrée et de sortie. Il y a deux façons de le faire sur chaque carte Arduino que vous aimez, exactement comment vous apprenez de cet article.

Méthodes de lecture et de gestion des ports d'E / S Arduino

Méthode 1 - Le langage standard pour l'IDE Arduino

Tout le monde le sait Arduino Il est programmé en C ++ avec quelques adaptations et simplifications pour les débutants. Cela s'appelle le câblage. Initialement, tous les ports Arduino sont définis comme des entrées, et il n'est pas nécessaire de le spécifier dans le code.

Les ports sont généralement écrits dans la fonction d'initialisation variable:

void setup ()
{
// code
}

La commande pinMode est utilisée pour cela, elle a une syntaxe assez simple, d'abord le numéro de port est indiqué, puis son rôle est séparé par des virgules.

pinMode (nomer_porta, naznachenie)

Avec cette commande, le circuit interne du microcontrôleur est configuré d'une manière spécifique.

Il existe trois modes dans lesquels le port peut fonctionner: INPUT - entrée, dans ce mode se produit lecture des données des capteurs, état des boutons, signal analogique et numérique. Le port est situé dans le soi-disant état de haute impédance, en termes simples - l'entrée a une résistance élevée. Cette valeur est définie, par exemple, 13 broches de la carte, si nécessaire, comme suit:

pinMode (13, ENTRÉE);

SORTIE - sortie, selon la commande prescrite dans le code, le port prend une valeur de un ou zéro. La sortie devient une sorte de source d'alimentation contrôlée et produit un courant maximum (dans notre cas, 20 mA et 40 mA au maximum) connecté à la charge. Pour affecter un port en tant que sortie à Arduino, vous devez entrer:

pinMode (13, SORTIE);

INPUT_PULLUP - le port fonctionne comme une entrée, mais le soi-disant s'y connecte. Résistance de pull-up de 20 kΩ.

Le circuit interne conditionnel du port dans cet état est illustré ci-dessous. Une caractéristique de cette entrée est que le signal d'entrée est perçu comme inversé («l'unité» à l'entrée est perçue par le microcontrôleur comme «zéro»). Dans ce mode, vous ne pouvez pas utiliser de résistances de rappel externes lorsque vous travaillez avec des boutons.

pinMode (13, INPUT_PULLUP);

Résistance pull-up d'entrée

Les données sont reçues des ports et leur sont transmises par les commandes:

  • digitalWrite (broche, valeur) - convertit la broche de sortie en logique 1 ou 0, respectivement, une tension de 5 V apparaît ou disparaît à la sortie, par exemple digitalWrite (13, HIGH) - fournit 5 volts (unité logique) à 13 broches et digitalWrite (13, faible ) - traduit 13 broches dans un état de zéro logique (0 volt);

  • digitalRead (pin) - lit la valeur de l'entrée, par exemple digitalRead (10), lit le signal de 10 broches;

  • analogRead (pin) - lit un signal analogique à partir d'un port analogique, vous obtenez une valeur dans la plage de 0 à 1023 (dans un ADC 10 bits), un exemple est analogRead (3).


Méthode 2 - Gérer les ports via les registres Atmega et accélérer le code

Un tel contrôle est bien sûr simple, mais dans ce cas, il y a deux inconvénients - une plus grande consommation de mémoire et de mauvaises performances lorsque vous travaillez avec des ports. Mais rappelez-vous ce qu'est Arduino, quelle que soit la carte optionnelle (uno, micro, nano)? Tout d'abord, cette microcontrôleur famille AVR ATMEGA, récemment utilisé MK atmega328.

Dans l'IDE Arduino, vous pouvez programmer dans la langue maternelle de cette famille de C AVR, comme si vous travailliez avec un microcontrôleur séparé. Mais tout d'abord. Pour gérer les ports Arduino de cette façon, vous devez d'abord examiner attentivement l'illustration suivante.

Ports du microcontrôleur Atmega168

Peut-être que quelqu'un examinera plus clairement les ports sous cette forme (les mêmes sur la figure, mais dans une conception différente):

Ports du microcontrôleur Atmega328

Ici vous voyez la correspondance des conclusions d'Arduino et les noms des ports d'Atmega. Nous avons donc 3 ports:

  • PORTB;

  • PORTC;

  • PORTD.

Sur la base des images montrées, j'ai compilé un tableau de correspondance entre les ports d'Arduino et Atmega, il vous sera utile à l'avenir.

Table de concordance des ports Arduino et Atmega

Atmega dispose de trois registres 8 bits qui contrôlent l'état des ports, par exemple, le port B déterminera leur objectif en établissant des analogies avec les outils de câblage standard décrits au début de cet article:

  • PORTB - Gérer l'état de sortie. Si la broche est en mode "Sortie", alors 1 et 0 déterminent la présence des mêmes signaux à la sortie. Si la broche est en mode "Input", alors 1 connecte une résistance de pull-up (identique à INPUT_PULLUP discutée ci-dessus), si 0 est un état de haute impédance (analogique de INPUT);

  • PINB est un registre de lecture. En conséquence, il contient des informations sur l'état actuel des broches du port (unité logique ou zéro).

  • DDRB - registre de direction de port. Avec lui, vous indiquez au microcontrôleur si le port est une entrée ou une sortie, avec «1» une sortie et «0» une entrée.

Au lieu de la lettre «B», il peut y en avoir d'autres selon les noms des ports, par exemple, PORTD ou PORTC, d'autres commandes fonctionnent de manière similaire.

Nous clignotons la LED, remplaçons la fonction digitalWrite () standard. Tout d'abord, rappelons à quoi ressemble l'exemple d'origine de la bibliothèque Arduino IDE.

Code clignotant LED Arduino

C'est le code du fameux «clignotement», qui montre le clignotement de la LED intégrée à la carte.

Gestion des broches

Les commentaires expliquent le code. La logique de ce travail est la suivante.

La commande PORTB B00100000 met PB5 dans l'état d'une unité logique, regardez, et ces images et le tableau qui se trouvent ci-dessous et voyez que PB5 correspond à 13 broches d'Arduina.

La lettre "B" devant les chiffres indique que nous écrivons les valeurs sous forme binaire. La numérotation en binaire va de droite à gauche, c'est-à-dire ici, l'unité se trouve dans le sixième bit à partir du bord droit du bit, ce qui informe le microcontrôleur de l'interaction avec l'état du sixième bit du registre du port B (PB5). Le tableau ci-dessous montre la structure du port D, elle est similaire et est donnée à titre d'exemple.

Structure du port D

Vous pouvez définir la valeur non pas en binaire, mais sous forme hexadécimale, par exemple, pour cela, nous ouvrons la calculatrice Windows et en mode "VIEW", sélectionnez l'option "Programmer".

Calculatrice Windows

Entrez le numéro souhaité:

Mode calculatrice programmeur

Et cliquez sur HEX:

Traduction de nombres sur une calculatrice

Dans ce cas, nous transférons tout cela vers l'IDE Arduino, mais au lieu du préfixe "B", ce sera "0x".

Transfert de numéro dans Arduino IDE

Mais avec cette entrée, il y a un problème. Si vous avez quelque chose connecté à d'autres broches, entrez une commande comme B00010000 - vous réinitialiserez toutes les broches sauf 13 (PB5). Vous pouvez saisir des données pour chaque broche individuellement. Cela ressemblera à ceci:

Saisie de données dans chaque broche

Un tel record peut sembler incompréhensible, essayons de le comprendre.

Analyser un enregistrement

Il s'agit d'une opération d'addition logique, | = signifie ajouter quelque chose au contenu du port.

Opération d'addition logique

Cela signifie que vous devez ajouter un mot de 8 bits dans le registre avec une unité décalée de 5 bits - par conséquent, si 11000010 s'avère être 110 110 010. Dans cet exemple, on peut voir que seul PB5 a changé, les bits restants de ce registre sont restés inchangés, ainsi que L'état des broches du microcontrôleur est resté inchangé.

Mais avec un ajout logique, un problème se pose - vous ne pouvez pas transformer l'unité en zéro, car:

0+0=1

1+0=1

0+1=1

La multiplication et l'inversion logiques viendront à notre secours:

Multiplication logique et inversion

& = signifie multiplier le contenu du port par un nombre spécifique.

 

Multiplier le contenu du port par un nombre

Et c'est le nombre par lequel nous multiplions. Le signe «~» indique une inversion. Dans notre cas, l'unité inversée est nulle. Autrement dit, nous multiplions le contenu du port par zéro, décalé de 5 bits. Par exemple, c'était 10110001, il est devenu 10100001. Les bits restants sont restés inchangés.

Multipliez le contenu du port par zéro décalé de 5 bits

La même chose peut être faite en utilisant l'opération d'inversion (^):

La lecture à partir des ports, l'analogue de digitalRead () est effectuée à l'aide du registre PIN, dans la pratique, cela ressemble à ceci:

Lire depuis les ports

Ici, nous vérifions si l'expression entre parenthèses est égale à l'état réel des ports, c'est-à-dire de même si nous avons écrit if (digitalRead (12) == 1).


Conclusion

Pourquoi y a-t-il de telles difficultés avec la gestion des ports si vous pouvez utiliser des fonctions pratiques standard? Tout dépend de la vitesse et de la taille du code. Lorsque vous utilisez la deuxième méthode, discutée dans l'article, la taille du code est considérablement réduite et la vitesse augmente de plusieurs ordres de grandeur. Le digitalWrite () standard a été effectué en 1800 μs, et l'enregistrement directement sur le port en 0,2 μs, et digitalRead () en 1900 μs, et est également devenu en 0,2 μs. Cette méthode de contrôle a été trouvée sur les espaces ouverts du réseau et se retrouve souvent dans le code. projets terminés.

Voir aussi sur e.imadeself.com:

  • Connecter et programmer Arduino pour les débutants
  • Comment connecter un encodeur incrémental à Arduino
  • Microcontrôleurs PIC pour débutants
  • Télécommande du microcontrôleur: télécommande IR, Arduino, ESP8266, 433 ...
  • Mesurer la température et l'humidité sur Arduino - une sélection de façons

  •  
     
    Commentaires:

    # 1 a écrit: Kipovets | [citation]

     
     

    "Mais avec un ajout logique, un problème se pose - vous ne pouvez pas transformer l'unité en zéro, car:

    0 + 0 = 1 "(c)

    Petit oubli: 0 + 0 = 0.

     
    Commentaires:

    # 2 a écrit: chugou | [citation]

     
     

    Kipovets, il voulait probablement dire:

    1 + 1 = 1

     
    Commentaires:

    # 3 a écrit: | [citation]

     
     

    Kipovets,
    Typo banale! Vous voyez à quel point il est bon que des spécialistes soient assis sur notre portail! Vous ne devez créer que du contenu adapté!

     
    Commentaires:

    # 4 a écrit: Serg | [citation]

     
     

    Dans la dernière partie, il est dit PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Mais 5 broches du port B, c'est 13 broches d'arduino. Ou je me trompe?!

     
    Commentaires:

    # 5 a écrit: p-a-h-a | [citation]

     
     

    Si (PINB == B00010000) {} n'est passimilaire à si nous avons écrit if (digitalRead (12) == 1)
    plutôt analogique
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... et donc 8 broches de port

    Ici, vous avez besoin de ceci:
    si (
    ! (~ PORTB & (1 << PB4))) {} //retourne0 ou 1
    soit comme ça:
    si (PORTB & (1 << PB4)) {} // renvoie l'unité décalée = 16, DEC
    soit comme ça:
    si (
    bit_is_set (PORTB, 4)) {}// renvoie l'unité décalée = 16, DEC