Utilisation des PORTS

Bonjour les Amis,
Suite à une aide dont j’ai bénéficié dans un autre sujet, je me suis mis à l’étude des interventions directes sur les ports d’E/S d’Arduino, l’utilisation des masques logiques étant pour moi un outil courant et dont j’apprécie l’efficacité.
Ayant cerné la structure classique des registres couplés de directions et de données pour un port, c’est assez standard sur les µP, je me suis mis tout de suite à rédiger du code pour expérimenter la chose.
Pas de problème pour définir le sens des données. Je me suis rapidement codé une BARREGRAPHE, une lumière qui se déplace vers la droite ou vers la gauche en utilisant DDRA, PORTA etc.
J’ai ensuite désiré utiliser un port en lecture pour effectuer la saisie de tous ses bits simultanément.
L’idée de mon programme est simple :
DDRD en huit sorties.
DDRB que des entrées.
Dans la boucle de base, je fais une lecture du registre PORTB et j’écris ce contenu dans PORTD. Je devrais avoir la recopie des entrées 8 à 13 dans les sorties 0 à 5.
Ben NON, et je n’arrive pas à savoir pour quelle raison. J’ai testé plusieurs formes d’écriture, rien à faire. Si j’impose l’usage des résistances de forçage de « 1 » en interne, j’ai bien des niveaux « 1 » sur le port D. Mais si je force à la masse les entrées de B, il n’y a pas recopie sur D ?
ZAVEZ UNE IDÉE ?
Voici l’un de mes codages, mais j’ai déjà testé une tripoté de variantes dans l’écriture.

/* Programme de test des instructions travaillant sur les PORTS */
// Définition des variables pour ce programme.
byte X; // (Déclarer en int ne change pas le problème)

void setup() {
  DDRD = B11111111;   // Impose huit sorties sur 0 à 7.
  // Possibilité de donner 255 mais moins lisible que B11111111.
  DDRB = B00000000;}  // Impose que des entrées.
void loop() {
//  PORTB = B10101100; // Instruction pour tester la sortie et l’éclairage des LED.
  X = PORTB; // Lire les bits de 8 à 13.
  // J'ai testé également digitalRead(PORTB) sans succès.
  PORTD = X; // Recopier sur 0 à 7 l'état lu sur B.
  }

Autre question relative au même sujet :
Je ne vois vraiment pas à quoi peut servir PIN, ni comment l’utiliser.
J’ai pensé que c’était une autre forme pour modePIN() mais la documentation précise que cette instruction ne fonctionne qu’en lecture. Vous pouvez m’éclairer sur ce point s’il vous plait, éventuellement me scribouller une ou deux lignes de codage pour illustrer le propos ?
Merci d’avance les Amis et Aduinez-bien.

Bonjour,

alors la réponse va répondre à tes deux questions en même temps :slight_smile: :

  • pour «écrire» l'état de sortie d'une broche on utilise les registres PORTx
  • mais pour lire l'état d'une broche en entrée, on utilise PINx

Tous les microcontrôleurs ne sont pas comme ça (certains utilisent le même registre pour la lecture et l'écriture), mais les AVR sont ainsi faits.

L’idée de mon programme est simple :
DDRD en huit sorties.
DDRB que des entrées.

C'est une bonne idée, sauf que la réalité n'est pas aussi idyllique.

Les ports disponibles diffèrent selon les modèles de micro-controleur et quand un port existe les 8 bits sont rarement tous disponibles.
Exemple dans un 328p le quartz de l'oscillateur est raccordé sur un port ce qui lui fait 2 I/O en moins.
Le reset est aussi raccordé sur autre port donc une I/O en moins
Avec un 328p il n'y a que le portD qui puisse être intégralement disponible A CONDITION de sacrifier Rx et TX, donc plus d'USB.

UNE SEULE ISSUE ---> LIRE LA DATASHEET

J'ai pigé ... du moins je crois. :slight_smile:
PORTx permet d'écrire d'un seul coup 8 bits dans un port.
PINx permet de lire les huit bits d'un coup.
Si sur un port conditionné en entrées j'écris des "1", alors les résistances de forçage internes sont mises en service.
Si j'y écris des "0" alors elles sont hors service et les entrées sont "flottantes".

/* Programme de test des instructions travaillant sur les PORTS */
/* Pour tester l'instruction PORT et l'instruction PIN */

void setup() {
  DDRD = B11111111;   // Impose huit sorties sur 0 à 7.
  // Possibilité de donner 255 mais moins lisible que B11111111.
  DDRB = B0;}  // Impose que des entrées.

void loop() {
  PORTB = B11111111; //  Valide les résistances de forçage internes.
//  PORTB = B00000000; //  Inhibe les résistances de forçage internes.
  PORTD = PINB; } // Recopier sur 0 à 7 l'état lu sur B.

En apparence mon programme ci-avant donne les résultats escomptés. Donc je crois ne pas avoir proféré trop de bêtises. Si dans mes affirmations vous voyez des maladresses, alors n’hésitez pas à me le faire remarquer, c'est toujours ennuyeux de rester plus ou moins dans l'erreur.
Oui, je sais bien pour utiliser intégralement le port D on perd l’usage de la ligne série. Donc on peut télécharger le programme, et quand il tourne on oublie la ligne série. Il faut juste que les éléments de puissance sur ces deux broches soient compatibles. Si c’est une LED pas de problème, mais si c’est un gros moteur de 10kW, il vaut mieux le neutraliser durant le téléportage du programme !
Merci pour cette information, elle me permet d’avancer dans l’étude des ports. Je suis ravi, car j’avoue que pour moi travailler directement sur un port avec des masques logiques fait partie de mes habitudes.