Logiciels > Programmation PIC > Bases > MP > Lecture / écriture sur bus I2C > PCF8574

Dernière mise à jour : 08/09/2013

Présentation

Les exemples décrits ici montrent comment utiliser les expandeurs de port PCF8574 et PCF8574A câblés sur un même bus I2C, en association avec un microcontrôleur de type PIC 18F2420 utilisé en maître. Une partie du texte explique comment adresser ces composants en fonction de l'adresse affectée localement, au niveau physique des PCF8574(A) eux-mêmes.

Electronique mise en oeuvre

Les exemples de code logiciel qui suivent montrent comment lire ou écrire une valeur tenant dans un octet (valeur comprise entre 0 et 255), depuis ou vers un PCF8574 grâce à une liaison bifilaire I2C

Schéma électronique (001a) pour lecture et écriture
Pour la mise en pratique de ces exemples, le montage dont le schéma suit est mis en oeuvre.

pic_tuto_base_i2c_pcf8574_001a

Ce schéma peut sembler un peu complexe et touffu, mais il permet de lire et d'écrire sur le même bus I2C. Et si on y regarde bien, il n'y a finalement pas grand chose : 3 circuits intégrés, quelques interrupteurs, des leds et des réseaux de résistances. En réalité et comme on peut s'en douter un peu, le PIC est le seul composant indispensable pour l'ensemble des opérations de lecture et d'écriture. Les deux schémas suivant montrent les composants réellement utilisés si on ne fait que lire (schéma 001b) ou que écrire (schéma 001c) les données au travres des PCF8574 via le bus I2C.

Schéma électronique (001b) pour lecture seulement
Cette partie de schéma permet de lire des données provenant du PCF8574 (U1), de telle sorte que ses lignes d'entrées / sorties se comportent en entrées. 

pic_tuto_base_i2c_pcf8574_001b

L'état logique des huit lignes du PCF8574 configurée en entrées sont répliquées sur les lignes configurées en sorties du PORTB du PIC. L'état logique de chaque ligne d'entrée du PCF8574 est modifiable grâce aux interrupteurs regroupés dans le bloc DSW1.

Schéma électronique (001c) pour écriture seulement
Cette partie de schéma permet d'écrire des données en direction du PCF8574A (U2), de telle sorte que ses lignes d'entrées / sorties se comportent en sorties. 

pic_tuto_base_i2c_pcf8574_001c

L'état que prennent les lignes du PCF8574A configurées en sortie dépend de l'état logique des lignes configurées en entrées du PORTA du PIC. L'état logique de chaque ligne d'entrée du port A du PIC est modifiable grâce aux interrupteurs regroupés dans le bloc DSW2.

Principe de fonctionnement général
Un PCF8574 et un PCF8574A sont mis en parallèle sur le même bus I2C (voir schéma complet 001a). Ces deux composants fonctionnent exactement de la même façon, la différence réside dans l'adresse de base avec lesquelles on doit les adresser, qui est différente entre les deux. Pour le PCF8574, l'adresse de base est $40, et pour le PCF8574A l'adresse de base est $70. Cette histoire d'adresse ne doit pas vous faire peur, il s'agit juste d'un moyen qui permet à chaque membre d'un réseau I2C de savoir si oui ou non on s'adresse à lui. C'est une façon de faire le tri dans toutes les données qui peuvent circuler sur le bus I2C et qui ne concernent pas forcement tout le monde. Dans le cas présent il n'y a que deux composants reliés sur le même bus I2C, mais on peut aller beaucoup plus loin ! Les PCF8574 et PCF8574A disposent tous deux de trois entrées d'adresse complémentaires, qui permettent de décaller leur adresse d'affectation de base. Ces trois entrées d'adresse complémentaires permettent huit combinaisons possibles, ce qui correspond à huit valeurs d'adresses différentes. Comme les adresses de base des PCF8574 et PCF8574A sont différentes, on peut mettre en parallèle 8 circuits PCF8574 et 8 circuits PCF8574A - chacun avec une adresse différente, ce qui permet de travailler avec 128 lignes de données distinctes (16 x 8 bits). Pour plus de détails, voir paragraphe "Adresses du PCF8574(A)" après le descriptif du code logiciel.

Remarque
L'extension du nombre de lignes de données peut egalement être réalisée avec d'autres types de circuits non I2C. Si on veut juste ajouter des lignes de sortie additionnelles, on peut par exemple utiliser le CD4094 qui dispose de 8 sorties (exemples Voltmètre 005 et Horloge 002). Et pour un usage en entrée ou sortie, on peut aussi utiliser des multiplexeurs, à condition toutefois de disposer de plus de lignes pour la commande de ces circuits (3 lignes ou plus selon le cas, exemple Testeur de câble 001). Si le nombre de lignes disponibles sur le PIC n'est que de deux, alors les expandeurs de port PCF8574 (ou PCF8574A) constituent une solution vraiment pratique et simple à mettre en oeuvre.

Lecture et écriture de données avec le PCF8574

Le code exemple qui suit comporte deux ensembles de routines :
- routines de lecture depuis les lignes d'extension du PCF8574
- routines d'écriture vers les lignes d'extension du PCF8574A
Pas d'erreur dans les références des circuits utilisés, on met bien en oeuvre deux circuits électroniques PCF8574 différents :
- un PCF8574 pour utilisation en entrées additionnelles
- un PCF8574A pour utilisation en sorties additionnelles
Ce choix d'utilisation est arbitraire, on pourrait parfaitement faire l'inverse, c'est-à-dire utiliser le PCF8574 pour disposer de sorties additionnelles et utiliser le PCF8574A pour disposer d'entrées additionnelles.

Logiciel
Le code ci-dessous correspond au programme complet.

program electronique_pic_tuto_base_i2c_pcf8574_001a;

const
cPCF8574_W = $40; // -> $4E;
cPCF8574_R = $41; // -> $4F;
cPCF8574A_W = $70; // -> $7E;
cPCF8574A_R = $71; // -> $7F;

var
Values: byte;

procedure Main_Init;
begin
CMCON := $07; // turn off comparators
ADCON1 := ADCON1 or $0F; // turn off analog inputs
TRISA := $FF; // inputs
TRISB := $00; // outputs
I2C1_Init(100000); // I2C comm init
end;

procedure PCF8574_Write;
begin
I2C1_Start; // signal START
I2C1_Wr(cPCF8574A_W); // addresse PCF8574A
Values := PORTA;
I2C1_Wr(Values); // écriture données
I2C1_Stop; // signal STOP
end;

procedure PCF8574_Read;
begin
I2C1_Start; // signal START
I2C1_Wr(cPCF8574_R); // addresse PCF8574
Values := I2C1_Rd(0); // lecture données
  PORTB := Values;

I2C1_Stop; // signal STOP

end;

// programme principal

begin
Main_Init;
delay_ms(500);
while true do
begin
// lecture lignes PCF8574
PCF8574_Read;
Delay_ms(250);
// écriture sur lignes PCF8574A
PCF8574_Write;
Delay_ms(250);
end;
end.


Descriptif du logiciel

Procédure Init
Cette routine d'initialisation générale, qui est appelée une seule fois au moment de la mise sous tension du PIC, permet de définir l'orientation des broches des ports A et B, grâce aux lignes TRISA et TRISB. La ligne CMCON = 7 permet de désactiver le fonctionnement des comparateurs du PIC. La ligne ADCON1 permet de désactiver les fonctions liées au convertisseur Analogique / Numérique, toutes les lignes sont en effet utilisées ici de façon logique. La ligne I2C1_Init permet d'initialiser le module MSSP utilisé pour les fonctions de lecture / écriture sur bus I2C.

Lecture de données en provenance du PCF8574 (lignes d'entrée additionnelles)
Les données présentes sur les lignes P0 à P7 du PCF8574 (U1) sont répliquées sur le port B du PIC 18F2420 (U3). Si l'entrée P0 du PCF8574 (U1) est à l'état logique haut, alors la led connectée sur la broche RB0 du PIC s'allume. Si l'entrée P1 du PCF8574 (U1) est à l'état logique haut, c'est la led connectée sur la broche RB1 du PIC s'allume, etc.

Ecriture de données vers le PCF8574 (lignes de sortie additionnelles)
Les données du port A du PIC 18F2420 (U3) sont répliquées sur les lignes du PCF8574A (U2). Si la broche RA0 du PIC est à l'état logique haut, alors la led connectée sur la broche P0 du PCF8574A (U2) s'allume. Si la broche RA1 du PIC est à l'état logique haut, alors c'est la led connectée sur la broche P1 du PCF8574A (U2) qui s'allume, etc.

Programme principal
Dans le programme principal se déroule des actions qui se répètent indéfiniment, grace à l'emploi d'une boucle infinie (qui ne s'arrête jamais ca aucune condition n'impose son arrêt). Voici précisement ce qui est fait de façon répétée :
- on lit l'état logique des entrées additionnelles mises à disposition par le PCF8574
- on attend 250 ms sans rien faire
- on écrit sur les sorties additionnelles mises à disposition par le PCF8574A
- on attend 250 ms sans rien faire

Adresses des PCF8574 et PCF8574A

Chaque composant I2C esclave possède une adresse qui lui est propre, et la portion de code suivante (extraite du code complet vu ci-avant) précise à quelle numéro de rue on doit frapper pour dialoguer avec les PCF8574(A).

const
cPCF8574_W = $40; // -> $4E;
cPCF8574_R = $41; // -> $4F;
cPCF8574A_W = $70; // -> $7E;
cPCF8574A_R = $71; // -> $7F;


Dans le cas présent, la définition des adresses est faite "en dur" dans le code logiciel via des constantes, avec des valeurs qui collent avec le schéma proposé en début d'article. Mais dans certains cas vous pouvez être ammené à modifier l'adresse de ces composants, ne serait-ce que si vous en mettez plusieurs en parallèle, par exemple huit PCF8574 et huit PCF8574A pour disposer de 128 lignes d'entrées / sorties. Dans ce cas, les numéros d'adresses utilisées dans le logiciel du PIC doivent être adaptées en fonction du composant avec lequel dialoguer. Le procédé d'adressage est assez simple à comprendre : les PCF8574 et PCF8574A disposent d'une adresse fixe (qu'on appelle adresse de base) et cette adresse fixe peut être décalée d'une certaine valeur grâce aux broches d'adresse A0 à A2. Si vous branchez en même temps plusieurs composants sur le même bus, alors chacun doit avoir une adresse différentes parmi les huit possibles. Pour dialoguer avec un PCF8574 configuré avec les broches A2..A0 à 000, vous devez utiliser les adresses $40 et $41 dans le code. Pour dialoguer avec un PCF8574A configuré avec les broches A2..A0 à 110, alors vous devez utiliser les adresses $7C et $7D dans le code.Vous trouverez dans le tableau qui suit les adresses à utiliser selon l'état logique donné aux broches A0 à A2, pour les PCF8574 et PCF8574A.

A2A1A0PCF8574
Ecriture
PCF8574
Lecture
PCF8574A
Ecriture
PCF8574A
Lecture
000$40 (064d)$41 (065d)$70 (112d)$71 (113d)
001$42 (066d)$43 (067d)$72 (114d)$73 (115d)
010$44 (068d)$45 (069d)$74 (116d)$75 (117d)
011$46 (070d)$47 (071d)$76 (118d)$77 (119d)
100$48 (072d)$49 (073d)$78 (120d)$79 (121d)
101$4A (074d)$4B (075d)$7A (122d)$7B (123d)
110$4C (076d)$4D (077d)$7C (124d)$7D (125d)
111$4E (078d)$4F (079d)$7E (126d)$7F (127d)

Pour rappel, la valeur effective et complète de l'adresse est codée sur les sept bits de poids fort de l'octet d'adresse envoyé sur le bus I2C, le dernier bit (de poids faible) étant reservé à l'information de direction des données. Le texte qui suit détaille la procédure qui a été suivie pour remplir le tableau précédent. Les valeurs numériques notées selon la forme xxxd sont exprimées en décimal et les valeurs notées selon la forme $xx sont exprimées en héxadécimal.

Adresse de base du PCF8574 : 0100 000x
- bits 7 à 4 = adresse fixe = 0100 ($40 ou 064d)
- bits 3 à 1 = adresse variable = 000 ($00 ou 000d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Pour obtenir la valeur de l'adresse complète (part fixe plus part variable), il suffit d'additionner les valeurs de ces trois informations :
- pour écriture : 064d + 000d + 0 = 064d = $40
- pour lecture : 064d + 000d1 = 065d = $41

Exemple avec adresse variable du PCF8574 = 001 (A2 = 0, A1 = 0 et A0 = 1), alors on a :
- bits 7 à 4 = adresse fixe = 0100 ($40 ou 064d)
- bits 3 à 1 = adresse variable = 001 ($02 ou 002d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Ce qui donne les valeurs suivantes pour l'adresse complète :
- pour écriture : 064d + 002d + 0 = 066d = $42
- pour lecture : 064d + 002d1 = 067d = $43

Exemple avec adresse variable du PCF8574 = 111 (A2 = 1, A1 = 1 et A0 = 1), alors on a :
- bits 7 à 4 = adresse fixe = 0100 ($40 ou 064d)
- bits 3 à 1 = adresse variable = 111 ($0E ou 014d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Ce qui donne les valeurs suivantes pour l'adresse complète :
- pour écriture : 064d + 014d + 0 = 078d = $4E
- pour lecture : 064d + 014d1 = 079d = $4F

Notez bien le décallage de 1 bit de la valeur d'adresse variable, idéal pour se planter dans les calculs si on ne fait pas gaffe ! Et bien sûr, même principe pour le PCF8574A.

Adresse de base du PCF8574A : 0111 000x
- bits 7 à 4 = adresse fixe = 0111 ($70 ou 112d)
- bits 3 à 1 = adresse variable = 000 ($00 ou 000d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Pour obtenir la valeur de l'adresse complète (part fixe plus part variable), il suffit d'additionner les valeurs de ces trois informations :
- pour écriture : 112d + 000d + 0 = 112d = $70
- pour lecture : 112d + 000d1 = 113d = $71

Exemple avec adresse variable du PCF8574A = 011 (A2 = 0, A1 = 1 et A0 = 1), alors on a :
- bits 7 à 4 = adresse fixe = 0111 ($70 ou 112d)
- bits 3 à 1 = adresse variable = 011 ($06 ou 006d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Ce qui donne les valeurs suivantes pour l'adresse complète :
- pour écriture : 112d + 006d + 0 = 118d = $76
- pour lecture : 112d + 006d 1 = 119d = $77

Exemple avec adresse variable du PCF8574A = 110 (A2 = 1, A1 = 1 et A0 = 0), alors on a :
- bits 7 à 4 = adresse fixe = 0111 ($70 ou 112d)
- bits 3 à 1 = adresse variable = 110 ($0C ou 012d)
- bit 0 = bit de direction = 0 pour écriture ou 1 pour lecture
Ce qui donne les valeurs suivantes pour l'adresse complète :
- pour écriture : 112d + 012d + 0 = 124d = $7C
- pour lecture : 112d + 012d1 = 125d = $7D

Quand vous utilisez plusieurs PCF8574(A), vous pouvez utiliser les adresses que vous voulez, l'important est que deux composants physiques ne partagent pas la même. Mais vous pouvez adopter la même configuration pour les broches A0..A2 s'il s'agit de PCF8574 et PCF8574A puisque leur adresse de base (partie fixe) est différente. Il n'y a aucune obligation d'utiliser des adresses contigues, ni de commencer avec la part varable de l'adresse à 000. De même, la lecture des différents PCF8574(A) peut se faire dans l'ordre que vous voulez. Vous pouvez ainsi câbler quatre PCF8574(A) sur le même bus et utiliser les adresse suivantes :
- PCF8574 n°1 : adresses $44 (écriture) et $45 (lecture), broches A2..A0 = 010
- PCF8574 n°2 : adresses $4E (écriture) et $4F (lecture), broches A2..A0 = 111
- PCF8574A n°1 : adresses $7A (écriture) et $7B (lecture), broches A2..A0 = 101
- PCF8574A n°2 : adresses $7E (écriture) et $7F (lecture), broches A2..A0 = 111
Et lire en premier le PCF8574A n°1, ensuite le PCF8574 n°2, etc.

Historique

08/09/2013
- Correction erreur dans commentaires du code (mais code correct).
- Clarification des explications concernant les adresses à utiliser quand plusieurs PCF8574(A) sont utilisés en même temps.
25/04/2010
- Première mise à disposition