Les ENTRÉES-SORTIES






Les PORTs de l'ARDUINO UNO
Les ports de l'Atmega 328
En interne le microcontrôleur possède 3 ports d'entrées/sorties :
PORTB : 8 broches,
PORTC : 7 broches,
PORTD : 8 broches.

Pour chaque PORT sont affectés des broches correspondant au microcontrôleur.
PORTB : broches 14, 15, 16, 17, 18, 19, 9 10,
PORTC : broches 23, 24, 25, 26, 27, 28, 1,
PORTD : broches 2, 3, 4, 5, 6, 11, 12, 13.

Pour éviter d'avoir un circuit intégré avec de très nombreuses broches, utile en fonction du projet à réaliser, certaines sont multifonctions.
Le programmeur choisit par programmation la fonction qu'il veut utiliser pour chaque broche,

Nota :
• L'utilisation des fonctions du microcontrôleur repose sur l'utilisation et la manipulation de registres internes, 
• Lorsque l'on utilise les fonctions de l'arduino, l'IDE nous décharge de la manipulation de ces registres et l'on doit utiliser la numérotation de la platine arduino uno, programmation en haut niveau,
• Lorsque l'on programme en bas niveau il faut impérativement connaître les registres concernés et utiliser la numérotation de l'Atmega 328.

Les correspondances des broches de l'Atmega 328 et la platine de l'arduino uno ne sont pas identiques :

correspondance des broches
Correspondance des broches de l'Atmega 328 et l'Arduino uno
Les ENTRÉES-SORTIES
Généralités
L'arduino uno possède :
• 14 entrées/sorties numériques dont 6 peuvent être utilisées comme PWM (Pulse Widht Modulation),
   • Numérotées 0 à 13 (arduino uno),
   • Les broches 0 et 1 sont utilisées pour la communication série. Il est préférable de ne pas les utiliser,
   • Une Led avec une résistance sont branchées sur la sortie 13. Si on utilise la résistance de pull-up interne, la tension sera d'environ 1,7 V au lieu des 5 V prévus, car la led et la résistance abaissent le niveau   de tension, ce qui signifie qu’elle retourne toujours un état BAS. Il est déconseillé d'utiliser le mode INPUT_PULLUP pour cette broche. Si on désire utiliser la broche 13 comme ENTRÉE numérique, il faut utiliser une résistance de pull-down de tirage externe.

• 6 entrées/sorties analogiques numérotées A0 à A5 (arduino uno) et utilisables,
  • Comme entrées/sorties numériques,
  • Conjointement avec un convertisseur analogique/numérique d'une précision de 10 bits.

Nota : Le nombre de broches des 3 PORTs de l'Atmega 328 sont au nombre de 23, et sont réduites à 20 sur la platine de l'arduino uno en raison de l'utilisation de 3 broches pour le QUARTZ et le RESET.
Si on exclut les broches 0, 1 et 13 il reste à notre disposition : 17 broches utilisables.

Les sorties numériques et analogiques fonctionnent en tout ou rien, c'est à dire que la broche est à l'état haut, HIGH, ou à l'état bas, LOW,
Le sens d'utilisation d'une broche en entrée ou en sortie peut être modifié pendant l'exécution du programme.
  
En Sortie
• Lorsque la sortie est à l'état bas, LOW,  la tension de sortie est 0v,
• Lorsque la sortie est à l'état haut, HIGH, la tension de sortie est de 5 volts,
• En sortie une broche peut fournir un courant maximum de 40 mA, 
• Le courant maximal fournit par l'arduino uno ne doit pas dépasser 200 mA.
 
En Entrée
• En entrée toutes les tensions inférieures à 2,4 volts seront considérés comme un état BAS,
• En entrée toutes les tensions supérieures à 2,4 volts seront considérés comme un état HAUT,
• En entrée le programmeur peut activer des résistances de tirage (pull-up) interne de 20 à 50 kOhms qui sont désactivées par défaut. Ces résistances permettent de « tirer » le niveau de l'entrée au 5V (HIGH).  
 
Les INSTRUCTIONS d'ENTRÉES-SORTIES en HAUT NIVEAU
Utilisation des entrées sorties
Une broche pouvant être utilisée en entrée ou en sortie, il faut l'indiquer en ligne de commande dans le void setup ().

Pour configurer une broche on utilise la commande :
En ENTRÉE :
pinMode (broche, INPUT);

En SORTIE :
pinMode (broche, OUTPUT);
Gestion de la broche
Ensuite pour commander la broche correspondante, c'est à dire la positionner à l'état haut ou bas, il faut l'indiquer en ligne de commande dans le void loop ().

Pour un état haut
digitalWrite (broche, HIGH);
 
Pour un état bas
digitalWrite (broche, LOW);
 
Lecture de l'état d'une broche
Pour pouvoir lire l'état d'une broche, c'est à dire déterminer si elle est à l'état haut ou bas, pour connaitre la position d'un interrupteur par exemple, on le réalise en ligne de commande dans le void loop ().

La commande utilisée est :
Pour une broche NUmérique
digitalRead(numéro_broche_numérique_ou_analogique);

Ces instructions sont utilisées en réalisant ensuite un TEST par l'instruction IF pour connaitre l'état du bouton, HIGH ou LOW :
• if (digitalRead(numéro_broche_numérique_ou_analogique) = = HIGH; ou if (digitalRead(numéro_broche_numérique_ou_analogique) = = LOW; 

Pour une broche ANalogique
analogRead(numéro_broche_analogique);

Ces instructions sont utilisées en réalisant une lecture de l'entrée et en la stockant dans une variable de type INT. Ensuite un TEST par l'instruction IF permet de connaitre la valeur donnée par le convertisseur Analogique/Numérique :
• int valeurLue = analoglRead(numéro_broche_analogique);
• if valeurLue (test) une valeur {instructions à exécuter} ;

Les INSTRUCTIONS d'ENTRÉES-SORTIES en BAS NIVEAU
Généralités
Dans certains cas, notamment pour des questions de vitesse d'exécution, il peut être préférable d'utiliser la programmation en bas niveau plutôt que celle en haut niveau.

Pour programmer en bas niveau il est impératif de connaitre le fonctionnement du microcontrôleur de manière plus précise, datasheet du composant, et plus spécialement le rôle des registres qui le compose et qui permettent de le faire fonctionner d'une certaine manière.

L'utilisation de l'IDE de l'arduino nous décharge de la gestion et même de la connaissance de ces registres.
Cela présente l'avantage de simplifier la programmation mais la contrepartie est que les instructions sont exécutées moins vite voire beaucoup moins vite que lorsque le programme est écrit en bas niveau.

Pour nous l'écriture en bas niveau d'un programme dans son intégralité n'est pas nécessaire mais la connaissance et l'utilisation de certaines de ces commandes peut avoir son intérêt.

Nous allons en voir certaines que nous pourrons incorporer dans notre programme tout en utilisant et profitant de l'IDE de l'arduino.

Comme nous allons manipuler directement les registres du microcontrôleur on doit utiliser la numérotation des broches de l'Atmega 328 et pas celle de la platine arduino uno.

Il faut donc vérifier à qu'elle broche de la platine arduino uno corresponde ceux de l'Atmega 328 ou inversement.
Les registres
Pour gérer les entrées/sorties ont doit manipuler 3 registres :
DDRx détermine la direction de chaque broche : Entrée ou Sortie, correspondant à : pinMode (broche, INPUT); ou pinMode (broche, OUTPUT);
PORTx permet de configurer les broches dans un état Haut ou Bas, correspondant à digitalWrite (broche, HIGH); ou digitalWrite (broche, LOW);
PINx permet la lecture d'une broche pour déterminer si elle est dans un état Haut ou Bas, correspond à :
    • if (digitalRead(numéro_broche_numérique_ou_analogique) = = HIGH; ou 
    • if (digitalRead(numéro_broche_numérique_ou_analogique) = = LOW;

Comme vue au début de cette page, les broches entrées/sortie d'un microcontrôleur sont affectées à un PORT :
PORTB : broches 14, 15, 16, 17, 18, 19, 9, 10,
PORTC : broches 23, 24, 25, 26, 27, 28, 1,
PORTD : broches 2, 3, 4, 5, 6, 11, 12, 13.

Utilisation des entrées sorties
Le registre permettant de configurer les broches en entrées ou sorties est :
DDRB : broches 14, 15, 16, 17, 18, 19, 9 10,
DDRC : broches 23, 24, 25, 26, 27, 28, 1,
DDRD : broches 2, 3, 4, 5, 6, 11, 12, 13.

Nota : Il s'agit des broches de l'Atméga 328.

Nous allons faire clignoter la led de la platine arduino uno qui est positionnée sur la sortie 13 (arduino), Port D (PD3) broche 5 de l'Atméga 328.

equivalence des broches Atmega et platine Arduino uno
Equivalence des broches Atmega et platine Arduino uno
En SORTIE
La ligne de commande :
pinMode (broche, OUTPUT); est remplacée par,
DDRD = 0b00100000; Dans cette instruction on positionne le byte 5 du PORTB à 1.

En ENTRÉE
La ligne de commande :
pinMode (broche, INPUT); est remplacée par,
DDRD = 0b00000000; Dans cette instruction on positionne le byte 5 du PORTB à 0.

 
const byte led = 13; //Déclaration de la broche de la Led 
  
void setup()  


DDRB = 0b00100000; //Equivalent à pinMode (led, OUTPUT);//Broche 13 en Sortie 
 

 
void loop()  

//Fréquence de Base du Clignotement de la Led : 1Hz  

 digitalWrite (led, HIGH); //Broche 13 à l'état haut 

 delay (500); //Temporisation de 500 ms 
 
 digitalWrite (led, LOW); //Broche 13 à l'état BAS 

 delay (500);  //Temporisation de 500 ms 
}
Utilisation de l'instruction DDRx

Gestion de la broche
A l'état HAUT
Le registre permettant de configurer les broches dans un état HAUT ou BAS est : PORTx (x représente la lettre du PORT (B ou C ou D pour un Atméga 328) :

Pour positionner le byte à l'état HAUT on utilise la commande :
PORTB |= (1<<5), ou
PORTB |= (1<<PB5), ou 
PORTB = 0b00100000; pour la led broche 5 Atméga 328 ou 13 platine arduino uno.

L'avantage avec l'instruction PORTB = 0b00100000; est que l'on peut commander par exemple l'allumage ou l'extinction de leds branchés sur un même port en une seule instruction, là où il en faudrait plusieurs.
Le PORT B est constitué de 8 broches : 14, 15, 16, 17, 18, 19, 9, 10. En utilisant une instruction comme : 
digitalWrite (broche, HIGH);
   • L'instruction est exécutée en 60 cycles d'horloge :  * 8 = 480 cycles d'horloge pour allumer ou éteindre les 8 leds,
PORTB = 0b11111111;
   • L'instruction est exécutée en 3 cycles d'horloge pour le PORT dans son intégralité. 480 / 3 = 160. La vitesse d'exécution est multipliée par 160.


A l'état BAS
Le registre permettant de configurer les broches dans un état HAUT ou BAS est : PORTx (x représente la lettre du PORT (B ou C ou D pour un Atméga 328) :

Pour positionner le byte à l'état BAS on utilise la commande :
PORTB & = ~ (1<<5), ou
PORTB & = ~ (1<<PB5), ou 
PORTB = 0b00000000; pour la led broche 5 Atméga 328 ou 13 platine arduino uno.

Comme pour l'état HAUT l'utilisation de la commande PORTB = 0b00000000; permet de mettre le PORT dans son ensemble à l'état bas.

 
void setup()  

DDRB = 0b00100000;//Equivalent à pinMode (led, OUTPUT);//Broche 13 en Sortie 

 
void loop()  

//Fréquence de Base du Clignotement de la Led : 1Hz  

PORTB |= (1<<PB5); //Equivalent à digitalWrite (led, HIGH);//Broche 13 à l'état haut 
delay (500); //Temporisation de 500 ms 
 
PORTB &=~ (1<<PB5); //Equivalent à digitalWrite (led, LOW);//Broche 13 à l'état BAS 
delay (500); //Temporisation de 500 ms 
}
Utilisation de l'instruction PORTB
Lecture de l'état d'une broche
Pour une broche NUmérique ou Analogique
La ligne de commande :
if (digitalRead(numéro_broche_numérique_ou_analogique) = = HIGH) ou if (digitalRead(numéro_broche_numérique_ou_analogique) = = LOW)  est remplacée par,

if ((PINx & (broche_à_tester) (test) (valeur à tester);
Ou :
• x correspond aux PORT de l'Atméga 328,
• & broche_à_tester correspond à la broche concernée,
• test correspond au test à réaliser : egalité, supérieur, inférieur,...
• valeur à tester.

ou 
• if (bitRead(PINx, broche_à_tester) == HIGH) {instructions} ou 
• if (bitRead(PINx, broche_à_tester) == LOW) {instructions}.

Ou :
• x correspond aux PORT de l'Atméga 328,
• broche_à_tester correspond à la broche concernée du PORT concerné,
• test correspond au test à réaliser,
• HIGH ou LOW.


Nota : La commande analogRead (numéro_broche_numérique_ou_analogique) est utilisée pour la lecture d'une tension conjointement avec le convertisseur analogique numérique de l'atméga 328. 

Arrêtons-nous un instant sur cette instruction.

La broche à tester est fonction de sa position dans le PORT concerné de l'Atméga 328.

position des bytes pour le port b
Position des bytes pour le PORT B

position des bytes pour le port c
Position des bytes pour le PORT C

position des bytes pour le port d
Position des bytes pour le PORT D

Si on prend l'exemple d'un interrupteur branché sur la broche 13 de l'ATméga 328 qui correspond à la broche 7 de l'arduino uno, on emploiera l'instruction :
• if ((PIND & 0b10000000) = = 0b10000000); teste la condition HIGH,
• if ((PIND & 0b01000000) = = 0); teste la condition LOW.

Comment déterminer le chiffre, ici, 128 :
C'est la qu'il y a une petite difficulté mais très vite surmontée après avoir lu ce qui suit :
• La valeur dépend en fait de la valeur formée par le chiffre binaire du PORT considéré :

valeur du test portb
Valeur du test en fonction de la broche à tester : PORTB

valeur du test portc
Valeur du test en fonction de la broche à tester : PORTC

valeur du test portd
Valeur du test en fonction de la broche à tester : PORTD
Le petit logiciel qui suit à pour fonctionnement simple :
• Relâchement du bouton : Allumage des deux leds en sortie 13 et 8 (Arduino uno),
• Appui sur le bouton : Extinction des deux leds.

 
void setup()  

DDRB = 0b00100001;//Equivalent à pinMode (led, OUTPUT);//Broches 13 et 8 en Sortie 
 
pinMode (7, INPUT_PULLUP);//Broche 7 en entrée et pull-up mise en place d'un interrupteur 

 
void loop()  

if ((PIND&0b10000000) == 0) 

PORTB &=~ (1<<PB0); //digitalWrite (led, LOW);//Broche 8 Etat Bas, extinction de la Led 
PORTB &=~ (1<<PB5); //digitalWrite (led, LOW);//Broche 13 Etat Bas, extinction de la Led 
}  
 
if ((PIND&0b10000000) == 0b10000000) 

PORTB |= (1<<PB0);// digitalWrite (led, HIGH);//Broche 8 Etat Haut, allumage de la Led 
PORTB |= (1<<PB5);// digitalWrite (led, HIGH);//Broche 13 Etat Haut, allumage de la Led 

 
}
Utilisation de l'instruction if ((PINx & xxxxx) = = xxxxx)

Le chiffre 128 peut prendre plusieurs formes :
• En décimal : 128
• En binaire : 0b10000000,
• En hexadécimal : 0x80.

Nota : On peut même panacher les représentations du nombre du moment qu'il s'agit du même.