GPIO

Maintenant que nous avons vu comment associer une fonction à une pin par les registres PINSELx, nous allons regarder comment l'utiliser dans sa fonction Entrée/Sortie à usage général.

On parle alors de General Purpose Input/Output, les fameuses GPIO ...

Ces pins peuvent être programmées indépendamment les unes des autres, soit en entrée, soit en sortie.

Ces entrées sont compatibles 5V (on dit qu'elles sont 5V tolerant), et fournissent un signal 3.3V en sortie.


En entrée ou en sortie (IODIR) ?

Une GPIO peut donc être utilisée en entrée ou en sortie. On va choisir son sens de travail grâce au registre IODIR.

Un des 32 bits de IODIR positionné à 1 mettra la pin correspondante en sortie. Si ce bit est à 0, cette pin sera programmée en entrée. Le registre IODIR est localisé à l'adresse 0xE002 8008.



Configuration en Sortie:


Par exemple, pour mettre la pin P0.3 en sortie, on mettra le bit b3 de IODIR à 1:

On va donc faire un OU logique entre la valeur actuelle de IODIR et le numéro du bit à traiter:


IODIR = IODIR | 0x00000008 // Syntaxe C du or

// soit

IODIR |= 0x00000008 // Autre syntaxe C du or

De cette façon, nous avons placé P0.7 en sortie.

Rappel: La numérotation des 32 bits se fait de b31 à b0.


Configuration en entrée:

Pour la mettre en entrée, on remettra ce même bit b3 de IODIR à 0:


IODIR &= ~0x00000008; // Syntaxe C du and


autrement dit


IODIR = IODIR & ~0x00000008 // Autre syntaxe C du and

On fait ici un ET (and) logique entre la valeur actuelle du registre IODIR et la valeur complémentée du numéro du bit à traiter.


➢ Pourquoi ne pas y écrire 0 directement ? La notation binaire va nous aider à y voir plus clair.


Réfléchissons en binaire ...


Pour les Sorties:


La valeur correspondant à la pin P0.3 est bien 00000000000000000000000000001000, b3 = n° du P0.3


On défini le masque OUT qui équivaut à ce numéro de pin: 00000000000000000000000000001000, Masque Out


On applique alors ce masque par un OR sur le Port P0:


11010000000000000000000000000000 Etat actuel de P0


OR 00000000000000000000000000001000 Masque Out


=> 11010000000000000000000000001000 P0.3 Sortie



Pour mettre cette GPIO en sortie, on a donc fait un OR avec la valeur du masque, et ceci sans toucher aux autres bits du port, CQFD.



Pour les Entrées:



Pour la remettre en entrée, on va faire un AND avec la valeur complémentée correspondant à la pin à traiter:


La valeur correspondant à la pin P0.3 est toujours 00000000000000000000000000001000, b3 = n° du P0.3


En complémentant à un, on obtient le masque IN: 11111111111111111111111111110111, Masque IN


En faisant un AND entre le port et ce masque IN, on aura:


11010000000000000000000000001000, P0 actuel par ex.


AND 11111111111111111111111111110111, Masque IN


=> 11010000000000000000000000000000, P0.3 Entrée



On a donc bien remis P0.3 à 0 donc en entrée, sans toucher aux autres bits du port.



Remarque:


Les GPIO P0.2 et P0.3 partagent les fonctions du d'horloge et de ligne de données du bus I²C. Ces deux pins sont des entrées/sorties à drain ouvert 5V tolérantes, afin de respecter la norme I²C. Pour les utiliser normalement en GPIO classiques, il faut donc utiliser des résistances de rappel à Vcc. On utilisera 2K2 par exemple.


Nous savons à présent mettre ces pins d'I/O en entrée ou en sortie, mais il va maintenant falloir les lire quand elles sont en entrée, et les activer ou les désactiver lorsqu'elles sont configurées en sortie...


Pour cela, d'autres registres viennent à notre aide: IOSET, IOCLR et IOPIN.



Sorties à 1 (IOSET)


Ce registre IOSET va nous permettre de mettre les pins du port P0 à l'état haut.

Pour cela, il suffira d'écrire 1 sur le bit correspondant à la GPIO à traiter.

Ecrire 0 n'aura aucun effet, il faut indiquer ici quelle pin sera affectée par IOSET.

Le registre IOSET se situe à l'adresse 0xE0028004.


IOSET = 0x00000004; // P0.3 est mise à 1


Sorties à 0 (IOCLR)

Ce registre va quant à lui nous permettre de mettre les pins du port P0 à l'état bas.

Pour cela, il suffira d'écrire 1 sur le bit correspondant à la GPIO à traiter.

Ecrire 0 n'aura aucun effet, il faut indiquer ici quelle pin sera affectée par IOCLR.

Le registre IOCLR se situe à l'adresse 0xE002800C.


IOCLR = 0x00000004; // P0.3 est mise à 0


Lecture de l'état des entrées (IOPIN)

Ce registre IOPIN va nous permettre de lire la valeur d'une GPIO configurée en entrée. Il suffit de lire ce registre et de faire un masque avec le numéro de l'entrée à traiter.

Le registre IOPIN se situe à l'adresse 0xE0028000.

Exemple:


VarLecture = IOPIN; // Lecture de P0 entier


Mask = 0x00000008; // Mask de P0.3


if (VarLecture & Mask) // Si P0.3 est à 1,


{

// alors ...

}


Ici, nous avons lu les 32 bits du registre représentant l'état du port 0 (IOPIN), et par l'application d'un masque, nous connaissons l'état de l'entrée considérée. On pourra alors lire l'état des touche du clavier.


Nous sommes à présent prêts pour notre premier programme, Blinky ...