Bien souvent on a besoin de lire l'état des capteurs ou des boutons poussoirs dans un montage électronique à microprocesseur, pour effectuer des actions appropriées. Mais lorsque leur nombre devient élevé, on se tourne alors vers des circuits d’interfaces spécialisés, capable d’assurer la demande.

Le but de cet article est de proposer une solution possible à ce besoin. On prendra comme exemple la gestion d’un groupe de boutons poussoirs en utilisant un registre à décalge, le 74HC165 couplé à une carte Arduino Uno. On peut aussi remplaçer les boutons poussoirs par des DIP switches.

 

Voici les différents points qui seront abordés:

> une présentation rapide du composant,

> la saisie informatique du schéma du montage,

> le programme d'essai,

> la simulation du fonctionnement,

> la réalisation du montage sur plaque à essais,

Puis, on proposera:

> une idée pour augmenter le nombre d'entrées,

> la réalisation du montage amélioré sur plaque à essais,

> le programme modifié,

> le test fonctionnel,

Et le mot de la fin:

> Pour finir

Commençons d'abord par présenter ce composant :

Le circuit intégré 74HC165 est un registre à décalage à 8 entrées parallèles A, B, C, D, E, F, G, H ;  une entrée série SER et une sortie série QH.  Les états logiques présents sur chacune des entrées sont tous mémorisés simultanément lorsqu'une impulsion négative est appliquée sur la broche SH/LD.  Ces états logiques sont transférés sur la sortie série au rythme des fronts montants des impulsions d’horloge appliqués sur la broche CLK, à condition que SH/LD soit positionné à l’état haut, et la broche CLK-INH à l’état bas. Après le transfert, tant qu'une nouvelle impulsion n'est pas appliquée sur la broche SH/LD, et que celle-ci reste à l’état haut, aucun changement ne sera observé sur la sortie QH, peut importe que le signal d’horloge soit présent ou non.  En outre le circuit dispose aussi d’une sortie inversée /QH.

La broche CLK-INH a pour rôle de bloquer ou d’inhiber l’action du signal d’horloge sur le circuit. Les fonctions des broches CLK et CLK-INH sont interchangeables ;  en effet, il suffit d’appliquer un état bas sur CLK, pour que tout front montant sur CLK-INH fasse transférer les états logiques des entrées vers la sortie série QH. L’entrée SER permet de mettre en cascade plusieurs circuits, lorsqu’on veut augmenter le nombre d’entrées parallèles.

Diagramme logique :

Le circuit est essentiellement constitué des portes logiques Ou,  Non, Non-ET, et de 8 bascules SR munies d’une entrée d’horloge et une entrée D. La sortie de chaque bascule est reliée à l’entrée D de la bascule suivante, de la gauche vers la droite.

 

Diagramme logic 74hc165

       Extrait tiré de la documentation technique de Texas Instruments

 

Les lignes suivantes expliquent le fonctionnement de ce composant à l'aide des signaux.

Chronogrammes de fonctionnement :

 

chrnonogrammes 74hc165

         Extrait tiré de la documentation technique de Texas Instruments

 

Supposons par exemple que chacune des entrées prenne le niveau logique suivant :

A état Haut ;  B état Bas ; C état Haut ; D état Bas ; E état Haut ; F état Bas ; G état Haut ; et H état Haut.

Un signal d’horloge permanent est présent sur la broche CLK.

Lorsqu'un signal sous forme d’impulsion negative, est appliqué sur SH/LD, les 8 entrées sont simultanément mémorisées (Load). Dès que CLK-INH passe à l’état Bas, les états logiques mémorisés sont transférées à tour de rôle vers la sortie QH, au rythme des impulsions d’horloge appliquées sur la broche CLK, en commençant par l’état logique présent de l’entrée H.

Pour plus de détails sur les caractéristiques de ce circuit, il faudra se référer à la document technique.

Le montage :

La réalisation ici consiste à connecter 8 boutons poussoirs, tous reliés à +5V par l'intermédaire des résistances de 22 KOhms, sur les entrées parallèles du 74HC165, puis, de visualiser l’état de chacun des boutons poussoirs, sur l’écran d’un ordinateur, en utilisant une carte Arduino Uno.

Selon le schéma ci-après:

 

schema test 74hc165

 

Ce schéma a été réalisé sous Proteus, ce choix nous permet de simuler le fonctionnement du montage sans quitter l’environnement graphique, avant de câbler le tout sur une plaque à essai. Cela explique la présence du composant "terminal" dans le dessin.

Programmation :

Avec la carte Arduino Uno il faudra générer les signaux nécessaires pour communiquer avec le 74HC165 conformément aux chronogrammes proposés dans la documentation technique. 

Le tableau ci-après propose les connexions réalisées entre le circuit intégré et Arduino Uno:

 

Broche du 74HC165Borne E/S  Arduino

CLK

12

QH ou /QH

11

CLK-INH

10

SH/LD

9

VCC

+5V

GND

GND

 

Pour finir Arduino sera relié au PC par un câble USB. Côté PC, l’application Putty, servira de terminal pour visualiser les données reçues par la liaison série. On peut aussi au besoin utiliser  HyperTerminal pour accomplir cette tâche.

Pour piloter le 74HC165 à l'aide d'un programme, peut utiliser soit la librairie SPI d’Arduino, soit créer un programme qui effectue cette tâche. La librairie SPI, impose d'utiliser des broches bien précises de la carte; tant dis que si l'ion choisit une methode de programmation personnelle, on a le choix sur l'utilisation des broches d'Entrée/Sorties de la carte Arduino. 

On va plutôt opter pour un programme qui n'utilise pas la librairie SPI.

 

Les lignes de code qui suivent n’ont rien de particulier :

Dans un premier temps on va définir les broches qui vont être utilisées :

 

const int Load = 9;
const int clockPinEnable = 10;
const int dataIn = 11; 
const int clockIn = 12;

unsigned long pinValues; unsigned long oldPinValues;

 

Ensuite l’initialisation, réalisée par la fonction setup(), consiste à définir le rôle de chaque broche, de définir la vitesse de transmission de la liaison série; puis d'afficher un état de départ des 8 sorties :

 

Serial.begin(9600);
pinMode(Load, OUTPUT);
pinMode(clockPinEnable, OUTPUT);
pinMode(clockIn, OUTPUT);
pinMode(dataIn, INPUT);

digitalWrite(clockIn, LOW); digitalWrite(Load, HIGH);

pinValues = read_shift_register(); print_byte(); oldPinValues = pinValues;

 

Le programme principal tourne en boucle grâce à la fonction « loop() », qui à son tour appelle les fonctions read_shift_register() et print_value().

read_shift_register() va lire les données séries reçues sur la broche dataIn, puis stockera  le résultat final sous forme d’un octet dans la variable octetRead en commençant par le bit de poids faible (entrée A du 74HC165).

print_value() affiche la valeur binaire des 8 sorties lorsqu'il y a un changement sur l'une des entrées, c'est à dire lorsqu'on appui sur un bouton poussoir. Grâce à la commande Serial.print(); qui envoi l'état des 8 bits sur la liaison série.

Le programme global se résume aux quelques instructions qui suivent :


/* Main.ino file generated by New Project wizard * * Created: Mon Dec 13 2021 * Processor: ATmega328P * Compiler: Arduino AVR */ //Example of using 74HC165 Shift Register #define DATA_WIDTH 8 //shift register has 8 bits datat const int Load = 9; const int clockPinEnable = 10; const int dataIn = 11; const int clockIn = 12; unsigned long pinValues; unsigned long oldPinValues; void setup() { Serial.begin(9600); pinMode(Load, OUTPUT); pinMode(clockPinEnable, OUTPUT); pinMode(clockIn, OUTPUT); pinMode(dataIn, INPUT); digitalWrite(clockIn, LOW); digitalWrite(Load, HIGH); pinValues = read_shift_register(); print_value(); oldPinValues = pinValues; } void loop() { pinValues = read_shift_register(); if(pinValues != oldPinValues) { print_value(); oldPinValues = pinValues; } } unsigned long read_shift_register() { long bitVal; unsigned long octetRead = 0; digitalWrite(clockPinEnable, HIGH); digitalWrite(Load, LOW); delayMicroseconds(5); digitalWrite(Load, HIGH); digitalWrite(clockPinEnable, LOW); for(int i = 0; i < DATA_WIDTH; i++) { bitVal = digitalRead(dataIn); octetRead |= (bitVal << ((DATA_WIDTH-1) - i)); digitalWrite(clockIn, HIGH); delayMicroseconds(5); digitalWrite(clockIn, LOW); } return(octetRead); } void print_value() { byte i; Serial.println("Input logic level...\r\n"); for(byte i=0; i<=DATA_WIDTH-1; i++) { Serial.print(pinValues >> i & 1, BIN); } Serial.println("\r"); }

Simulation :

Le fonctionnement sera simulé directement à l’aide de Proteus VSM.   On commencera par copier le programme dans VSM en cliquant sur l'onglet "Source Code" (à côté de "Schematic Capture"), puis il suffit de cliquer sur la flèche « Run simulation » en bas à gauche de la fenêtre.

La capiure d'écran suivante montre ce qu’on obtient lorsqu'on appui sur un bouton; c'est le troisième bouton qui est actionné:

 

simulation 74hc165

Réalisation du montage sur plaque à essai :

La photo ci-après montre le résultat obtenu lorsqu'on appuie sur une touche câblée sur la plaque à essai:

 

test 74hc165

 

Amélioration:

On va faire évoluer le montage précédent en ajoutant 8 entrées supplémentaires, ce qui fera en tout 16 de plus pour la carte Arduino Uno.

Afin de réaliser cette opération, on va mettre en cascade deux registres à décalages 74HC165.

Schéma du montage:

Le câblage reste inchangé, à ceci près que la sortie QH du premier registre est reliée à l'entrée SER (broche 10) du second registre.

 

schema test 74hc165x2

 

Réalisation:

Le montage sera câblé sur plaque essai, conformément au schéma précédent.

Programmation:

Le programme n'est pas différent du programme utilisé pour un seul composant. Seule la variable DATA_WITH change de valeur car ici elle tiendra compte du nombre de composants définit par NUMBER_OF_SHIFT_CHIPS.

 


/* Main.ino file generated by New Project wizard * * Created: Mon Dec 13 2021 * Processor: ATmega328P * Compiler: Arduino AVR */ //Example of using 74HC165 Shift Register #define NUMBER_OF_SHIFT_CHIPS 2 #define DATA_WIDTH NUMBER_OF_SHIFT_CHIPS * 8 const int Load = 9; const int clockPinEnable = 10; const int dataIn = 11; const int clockIn = 12; unsigned long pinValues; unsigned long oldPinValues; void setup() { Serial.begin(9600); pinMode(Load, OUTPUT); pinMode(clockPinEnable, OUTPUT); pinMode(clockIn, OUTPUT); pinMode(dataIn, INPUT); digitalWrite(clockIn, LOW); digitalWrite(Load, HIGH); pinValues = read_shift_register(); print_value(); oldPinValues = pinValues; } void loop() { pinValues = read_shift_register(); if(pinValues != oldPinValues) { print_value(); oldPinValues = pinValues; } } unsigned long read_shift_register() { long bitVal; unsigned long octetRead = 0; digitalWrite(clockPinEnable, HIGH); digitalWrite(Load, LOW); delayMicroseconds(5); digitalWrite(Load, HIGH); digitalWrite(clockPinEnable, LOW); for(int i = 0; i < DATA_WIDTH; i++) { bitVal = digitalRead(dataIn); octetRead |= (bitVal << ((DATA_WIDTH-1) - i)); digitalWrite(clockIn, HIGH); delayMicroseconds(5); digitalWrite(clockIn, LOW); } return(octetRead); } void print_value() { byte i; Serial.println("Input logic level:\r\n"); for(byte i=0; i<=DATA_WIDTH-1; i++) { Serial.print(pinValues >> i & 1, BIN); } Serial.println("\r"); }

Test fonctionnel:

La vidéo ci-après montre le fonctionnement de deux registres à décalage, montés sur une plaque à essai, et connecté à Arduino.

La visualisation des états des boutons poussoirs se fait sur l'écran du PC à l'aide de Putty.

 

 

Pour finir:

Nous venons de voir que le registre à décalage Parallèle -> Série 74HC165 permet d’augmenter le nombre d’entrées d’un microcontrôleur. Ce composant peut être monté en cascade, ainsi on peut avoir plusieurs entrées: 16, voire plus. On ne peut par lui envoyer des commandes d'écriture; ce composant ne pourra être que lu exclusivement, par le microcontrôleur. Les programmes de pilotage réalisés dans cet article n'utilisent pas la librairie SPI, des exemples de mise en oeuvre de cette librairie peuvent être trouvés dans le site arduinocc, ou dans de nombreux sites sur la toile. Des circuits intégrés spécialisées capables de multiplier le nombre d'entrées d'un microcontrôleur existent, ils supportent le protocole SPI ou I2C.