Êtes-vous fatigué des compromis à cause du manque de ports d'E/S lorsque vous développez vos projets avec votre plateforme préférée ? Vous en souhaitez plus pour gérer votre multitude de signaux et d'actionneurs ? Cette carte d'interface, gérée par le bus I²C, vous permettra d'ajouter jusqu'à 16 E/S par unité, soit un maximum de 128 E/S sur votre système existant.

Il existe plusieurs cas concrets dans lesquels il est nécessaire de gérer plusieurs signaux et actionneurs avec un microcontrôleur, qui manque par contre d'un nombre de broches d'E/S suffisant. C'est dans ces conditions qu'il devient utile de recourir à ces circuits intégrés connus sous le nom d'expandeurs d'E/S, dont la fonction est de regrouper un certain nombre de lignes d'entrée et de sortie pour les contrôler via une seule E/S, c'est-à-dire une ligne de communication série telle que le bus I²C très courant et répandu, que l'on trouve dans de nombreux microcontrôleurs, et dans les cartes Arduino en particulier.   

Pour répondre au besoin d'accroître (étendre, en fait, comme le suggère le même terme "expandeur") les lignes E/S, nous avons réalisé la carte interface basée sur le MCP23017, proposé dans cet article, sur lequel nous trouvons un circuit intégré Microchip qui est, comme on peut s'y attendre, un expandeur d'E/S de 16 bits, ainsi que les composants à minima pour le faire fonctionner, qui dans ce cas consistent en un commutateur-dip et quelques résistances de tirage. Enfin, pour vous donner une idée de ce qui peut être accompli avec un expandeur d'E/S, nous allons vous proposer un exemple d'application où la carte breakout pilote une série de relais (huit en tout), montés sur une carte qui peut être pilotée par des niveaux TTL ou des appuis sur des boutons. Mais procédons par ordre et analysons d'abord le schéma du circuit.

Je m'abonne
Abonnez-vous à la balise thématique Microcontrôleurs pour être averti dès qu'une information relative à ce sujet sera publiée par Elektor !

Schéma du circuit de la carte d'extension

Comme vous pouvez le voir sur le schéma de la Figure 1, la carte d'extension est quelque chose d'extrêmement basique, puisqu'il contient le circuit intégré MCP23017 en version DIP (montage traditionnel), avec toutes les broches qui ont un pas de 2,54 mm sur le circuit imprimé, pour faciliter le montage futur de pin-strips, pour l'insertion dans d'autres cartes ou platines d'essais, à l'exception des trois broches concernant les bits les moins significatifs de l'adresse du bus I²C du périphérique. A cet effet, un dip-switch à 3 voies (étiqueté SW1 dans le schéma de câblage) a été fourni, pour définir l'adresse de communication sur le bus I²C, dont les broches A0, A1, et A2 sont maintenues au niveau logique haut à travers les résistances R1 à R3 lorsque les interrupteurs sont ouverts.

Breakout board Schematic diagram MCP23017

Figure 1 : Le schéma de la carte d'extension.

En résumé, toutes les broches liées aux E/S des registres A et B ont été portées vers l'extérieur sur des barrettes de broches mâles. Ces broches ont été disposées des deux côtés afin que nous puissions connecter facilement notre carte, mais il s'agit bien sûr de broches d'E/S numériques ; vous pouvez donc connecter ce que vous voulez, dans les limites du courant et de la tension supportés par le circuit intégré MCP23017. Outre les bandes de broches latérales au pas de 2,54 mm, qui permettent également de loger le module dans une plaque de prototypage, 4 autres broches ont été prévues sur une bande (également au pas de 2,54 mm) appelée I2C afin que nous puissions nous connecter au bus directement sur la partie supérieure du module. Il est évident que les broches latérales suffisent pour la communication et l'interfaçage avec le module, c'est pourquoi les quatre broches du connecteur I2C sont placées en parallèle avec celles qui existent déjà sur la carte.

Notez que sur le circuit imprimé, pour des raisons de commodité, les broches du registre A ont été placées d'un côté et les broches B de l'autre, toujours dans le but de simplifier les connexions. Les broches appartenant au bus I²C ont été replacées dans la barrette de broches marquée I²C, de même que le positif 5 V et la masse ; tous deux sont dotés de résistances de tirage. Le reset de notre carte d'extension d'E/S n'est pas utilisé, par conséquent, pour le désactiver, nous avons placé la broche correspondante (18, RST) au niveau logique haut à travers la résistance R4.

Entre les broches latérales de la carte, nous trouvons également à nouveau la masse GND et le +5 V. L'élément principal du circuit est bien sûr le MCP23017, que nous pouvons considérer comme un convertisseur I²C /parallèle, fabriqué par Microchip (marqué U1). Le circuit intégré, dont vous voyez le schéma fonctionnel interne dans la Figure 2, fonctionne comme un périphérique (esclave) du bus I²C, et supporte les deux modes d'entrée et de sortie. Dans le premier, il permet de transférer les états E/S des registres A et B sur le bus en format série, un octet pour chaque registre, à la demande du dispositif maître du bus I²C. Et dans le second, il configure les lignes E/S en convertissant les données entrantes sur le bus I²C en l'état correspondant des lignes des registres A et B.

Block diagram of the MCP23017: the SPI variant, which distinguishes MCP23017 from MCP23017, is also shown.
Figure 2 : Schéma logique interne du MCP23017 : la variante SPI, qui distingue le MCP23S17 du MCP23017, est également représentée.

Le MCP23017

La puce au cœur de la carte d'extension décrite ici est un expandeur I/O de 16 bits, divisé en deux ports de 8 bits chacun, interfacé via un bus I²C. Cela signifie qu'avec seulement deux fils, référencés à la masse, il permet d'acquérir l'état ou de définir la sortie d'un nombre de liaisons pouvant aller jusqu'à 16.
Ses caractéristiques techniques sont les suivantes :

  • Interface de données I²C à grande vitesse, fonctionnant à 100 kHz, 400 kHz ou 1,7 MHz
  • Adresse de bus I²C réglable en 8 combinaisons
  • Broches d'interruption configurables, par niveau et fonction logique
  • Source d'interruption paramétrable
  • Registre d'inversion de polarité

Pour les entrées :

  • Entrée de réinitialisation externe
  • Courant de repos de 1 μA max.
  • Tension d'alimentation de 1,8 V à 5,5 V

La puce intégrée MCP23017 fournit une extension d'E/S série/parallèle générique de 16 bits et est disponible en deux versions : celle utilisée ici, équipée d'une interface de bus I²C, est la MCP23S17, une variante d'interface SPI. La puce est un expandeur d'E/S de 16 bits, divisé en deux ports de 8 bits chacun, interfacé via le bus I²C. Cela signifie qu'avec seulement deux fils, référencés à la masse, il permet d'acquérir l'état de pas moins de 16 voies (mode entrée) ou de définir l'état logique de chacune d'entre elles (mode sortie). Les voies d'E/S fonctionnent par défaut comme des entrées.

Le MCP23017 se compose de plusieurs registres en configuration 8 bits pour la sélection des entrées, des sorties et de la polarité. Le système maître peut activer les E/S en tant qu'entrées ou sorties en écrivant les bits de configuration E/S correspondants (IODIRA/B). Les données de chaque entrée ou sortie sont stockées dans le registre d'entrée ou de sortie correspondant. La polarité du registre du port d'entrée peut être inversée à l'aide du registre d'inversion de polarité. Tous les registres peuvent être lus à partir du système maître. Le port E/S 16 bits est structurellement composé de deux ports 8 bits, à savoir le port A et le port B, qui sont portés par les broches 21÷28 et 1÷8, respectivement. Le MCP23X17 peut être configuré pour fonctionner en mode 8 bits ou 16 bits, et il dispose en outre de deux broches d'interruption, INTA et INTB, qui peuvent être associées à leurs ports respectifs (INTA pour le port A et INTB pour le port B9) ou être soumises à l'opération logique OR de sorte que ces deux broches s'activent si les deux ports entraînent une interruption.

La sortie d'interruption peut être configurée pour se déclencher dans deux conditions (mutuellement exclusives) :
  • lorsqu'un état d'entrée diffère de l'état du registre du port d'entrée correspondant, cette condition est utilisée pour indiquer au maître du système qu'une entrée a changé d'état
  • lorsque l'état d'une entrée est différent de la valeur préconfigurée du registre (registre DEFVAL).

Les lignes d'interruption INTA et INTB peuvent être configurées comme actives à l'état haut, actives à l'état bas ou à collecteur ouvert. Le registre de capture d'interruption saisit les valeurs des ports au moment où l'interruption est déclenchée, stockant ainsi la condition qui a provoqué l'interruption. La réinitialisation sous tension (Power-On-Reset, POR) ramène les registres à leurs valeurs par défaut et initialise la machine d'état de l'appareil. La nécessité d'un fonctionnement bidirectionnel est due au fait que chaque périphérique du bus I²C doit à la fois être capable de lire (par exemple, des commandes) et d'envoyer des données acquises sur 8+8 bits sur le bus. Comme toutes les unités pour le bus I²C, le MCP23017 permet de définir son adresse dans une plage de 8 adresses, et les broches A0, A1, et A2 sont là pour cela, permettant de définir les adresses de l'unité esclave, si elle est adressée directement à partir du bus I²C. Chacune de ces voies est définie par un commutateur dip-switch SW1 : chaque dip fermé définit le zéro logique sur l'adresse respective, tandis que, vice versa, un dip ouvert détermine l'état logique 1. La possibilité de définir huit adresses permet de placer jusqu'à huit expandeurs d'E/S sur le même bus et de contrôler ainsi un maximum de 128 E/S avec seulement trois voies.

L'ensemble du circuit est alimenté par le contact 5 V (nous avons en fait deux contacts : 1 et 15, situés sur les côtés longs de la carte) référencé à la masse (contacts GND, c'est-à-dire 2 et 23 des rangées latérales). Avec ce matériel, la logique de fonctionnement est la suivante : chaque fois qu'il reçoit une trame sur la ligne SDA du bus I²C (cadencée par le signal d'horloge sur la ligne SCL), le circuit intégré MCP23017 exécute la commande qu'elle contient (dans ce cas, celle qui indique de charger l'octet de données) et dispose les 8 lignes de sortie IOA0÷IOA7 et IOB0÷IOB7 comme les bits correspondants, c'est-à-dire que IOA0 prendra l'état du premier bit de l'octet 1, IOA1 celui du deuxième bit, et ainsi de suite. Il en sera de même pour IOB0÷IOB7, qui reproduiront exactement les bits du deuxième octet de données.

Bien sûr, la conversion et la présentation sur les sorties ne se produisent que si la trame reçue pour U1 contient l'adresse du bus I²C correspondant à celle qui a été définie, par l'intermédiaire des commutateurs-dip de SW1. Lorsque chaque trame est reçue, l'intégrateur met à jour l'état de ses sorties, et les niveaux logiques respectifs déterminent si les LED des segments d'affichage sont allumées (ou restent à l'état éteint). Si aucune trame n'est envoyée par la suite, l'affichage conserve le numéro affiché car les sorties de l'intégrateur MCP23017 sont verrouillées. Ce qui précède s'applique au mode sortie, c'est-à-dire à l'écriture de l'état des deux bytes du bus I²C dans les registres de sortie A et B. Si, par contre, la commande provenant du bus est la lecture, le MCP23017 acquiert l'état I/O de chaque registre et génère deux bytes, le premier contenant l'état de IOA0÷IOA7 et le second la condition logique de IOB0÷IOB7. Il les envoie ensuite le long du bus I²C en guise de réponse. Pour chaque application à laquelle vous voudrez affecter la carte d'expansion, nous vous donnons la correspondance entre les adresses et le réglage des commutateurs-dip dans le Tableau 1.

230469-006-94-ORIGINAL-tabella 1.png
Tableau 1 : Configuration des adresses périphériques du MCP23017.

Réalisation pratique

Maintenant, après avoir décrit le schéma de câblage, nous pouvons passer aux remarques concernant la construction. Ensuite nous proposerons un exemple d'application basé sur l'interfaçage avec une carte Arduino accompagné du programme (sketch) correspondant. Comme d'habitude, nous avons dessiné un circuit imprimé disponible au téléchargement (il s'agit d'un circuit double face). À partir de là, vous pouvez procéder à la réalisation du circuit imprimé par photogravure, et après l'avoir gravé et percé, vous pouvez assembler les quelques composants nécessaires, qui dans ce projet, sont tous traditionnels, de type traversants, pour ceux qui n'aiment pas trop la technique CMS. Insérez et soudez d'abord les résistances, puis passez à l'embase pour le circuit intégré (à placer avec l'encoche orientée comme indiqué dans le plan de montage que vous voyez dans cet article) et au commutateur-dip à trois voies, à monter avec le commutateur 1 orienté vers la gauche, en regardant la carte avec l'embase pour U1 sur le dessus.

Au final, insérez et soudez dans les trous respectifs la barrette à 4 broches marquée I²C, puis, sur le côté opposé du circuit imprimé, insérez et soudez deux rangées de connecteurs à 12 broches qui permettront le montage sur des cartes de prototypages ou l'insertion sur d'autres cartes, comme éventuellement se connecter à Arduino en utilisant des cavaliers classiques mâle/femelle. Une fois les composants soudés, insérez le MCP23017 dans le support, en le tenant avec l'encoche orientée comme indiqué dans le plan de montage sur ces pages. Ceci fait, votre carte est prête pour l'expérimentation ou le prototypage.

230469-002-94-ORIGINAL-fig. 2.png
Figure 3 : Schéma de câblage de l'application de contrôle des relais commandés par bouton-poussoir.
Je m'abonne
Abonnez-vous à la balise thématique Arduino pour être averti dès qu'une information relative à ce sujet sera publiée par Elektor !

Voyons l'utilisation avec Arduino

La carte d'extension a été créé pour être interfacée avec un microcontrôleur, puisque typiquement, les expandeurs d'E/S sont utilisés par des dispositifs équipés d'une interface série sur le bus I²C.  Parce que Arduino supporte ce bus, téléchargez l'exemple de code pour les E/S du MCP23017 afin que vous puissiez l'écrire sur votre carte via l'IDE. Ce sketch permet essentiellement d'écrire l'état du registre du Port A en fonction d'un octet envoyé par Arduino sur le bus, dont les bits correspondent à l'état lu sur le Port B, qui sert cette fois d'entrée. Pour donner à l'exemple une application concrète, nous avons décidé d'utiliser les états logiques des E/S du Port A, qui fonctionneront ici comme des sorties numériques, pour piloter une carte à relais. Plus précisément, nous devons connecter les 8 lignes de commande de sorties de relais de la carte RELAY8CH à la banque d'E/S du Port A, tandis que 8 boutons-poussoirs normalement ouverts doivent être connectés au Port B, ayant en commun le pôle connecté à GND. Pour réaliser cette application, il est nécessaire de connecter l'Arduino UNO, la carte d'extension, la carte de relais et les boutons, comme le montre le schéma de câblage proposé à la Figure 3, tandis que la Figure 4 montre le prototype réel de cette application. Puisqu'il s'agit de boutons poussoirs assez communs (normalement ouverts) et qu'ils n'ont pas d'électronique externe, les résistances de tirages (pull-ups) internes du microcontrôlleur ont été activés (via la bibliothèque) pour les gérer et reconnaître le changement d'état, de sorte que nous avons activé la sortie respective lorsque le bouton est amené à la masse (GND). Pour ce faire, un code simple basé sur Arduino UNO a été écrit, en tirant parti de la bibliothèque Adafruit, qui, comme vous le voyez dans le Listing 1, est incluse dans la première ligne du sketch qui suit :

#include <Adafruit_MCP23X17.h>.
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp;
int i = 0;
int OUT[] = {7,6,5,4,3,2,1,0};   //Represents MCP23017 PIN (A7...A0)
int IN[] = {8,9,10,11,12,13,14,15}; //Represents MCP23017 PIN (B0...B7)
int STATO[] = {0,0,0,0,0,0,0,0}; ◦ //For each output, every toggle the status is being saved

void setup()
{
Serial.begin(9600);
Serial.println("MCP23017 INPUT/OUTPUT");
if (!mcp.begin_I2C(0x20)) //0x20 is MCP23017's address with A0=A1=A2 > ON(GND)
{
Serial.println("MCP Error!"); //If MCP is not found, the error is visualized
while (1);
}
//bank A Pin set as outputs and B bank as inputs
//The STATO variable to 0 to indicate idling outputs
for (i=0; i<8; i=i+1)
{
mcp.pinMode(OUT[i], OUTPUT);
mcp.pinMode(IN[i], INPUT_PULLUP);
STATO[i] = 0;
}
}
//******************* L O O P **********************
void loop()
{
String Testo_Debug = "";
for (i=0; i<8; i=i+1)
{
//If button pressed or output not activated, I activate it
if ((mcp.digitalRead(IN[i])==0) && (STATO[i]==0))
{
STATO[i] = 1;
Testo_Debug = "Pulsante" + String(i+1) + "premuto";
Serial.println(Testo_Debug);
mcp.digitalWrite(OUT[i], HIGH);
}
//If button released and output is active, I deactivate it
if ((mcp.digitalRead(IN[i])==1) && (STATO[i]==1))
{
STATO[i] = 0;
Testo_Debug = "Pulsante" + String(i+1) + "rilasciato";
Serial.println(Testo_Debug);
mcp.digitalWrite(OUT[i], LOW);
 }
}
delay(10);
}


Avant de charger le code dans la mémoire programme de notre carte Arduino, il est essentiel de télécharger la bibliothèque d'Adafruit et de l'installer en utilisant le Library Manager inclus dans l'IDE, ou simplement d'extraire le contenu du fichier ZIP et de copier l'ensemble du dossier Adafruit_MCP23017_Arduino_Library dans le répertoire librairies qui se trouve normalement dans le système d'exploitation dans le chemin Documents\Arduino\libraries. Après avoir chargé la bibliothèque, il suffira de charger notre exemple de code et de le charger à l'intérieur de la carte après avoir choisi le port COM correct dans le menu Outils de l'IDE.

Dans le code, un octet est demandé pour être envoyé au MCP23017, contenant l'état des boutons, et les données correspondantes sont traitées puis écrites dans un octet dirigé vers l'intégrateur, qui définira l'état des lignes du port A de manière stable, jusqu'au rafraîchissement. Pour que l'interfaçage fonctionne, les commutateurs-dip A0, A1 et A2 doivent être réglés correctement, car si l'adresse 0x20 n'était pas attribuée au capteur, un message d'erreur serait vu sur le port série. L'adresse de la carte d'interface est attribuée avec la combinaison 000 des trois bits A0, A1, A2, c'est-à-dire en mettant les trois commutateurs-dip à la masse. Si vous souhaitez modifier l'adresse, reportez-vous au tableau 1 habituel, en n'oubliant pas bien-sûr de modifier l'adresse inscrite dans le sketch.

Breakout board article: The hardware for testing the example sketch.
Figure 4 : Le matériel pour tester l'exemple de sketch.

Liste de composants
  • Résistances : R1 to R6: 4.7 kΩ
  • Condensateurs : C1 100 nF, céramique
  • Semiconducteur : U1 MCP23017-E/SP
  • Divers : SW1 commutateur-dip 3 voies ; 14 + 14 Pin embase DIL ; 2 × 12 barrettes à broches mâles,  1 × 4 barrette à broches mâles ; 1 × circuit imprimé (voir texte)

Note de l'éditeur : Ce projet a été initialement publié dans Elettronica IN



Traduction : Laurent RAUBER