Pour certains projets, le nombre d'entrées-sorties proposées par le microcontrôleur peut s'avérer insuffisant. Dans ce cas on peut faire appel à des circuits d'interfaces pour combler cette lacune.
Cet article a pour but de mettre en oeuvre une solution possible face à ce besoin. Comme exemple d'application, on va gérer plusieurs boutons poussoirs avec un registre à décalge (74HC165) connecté à Arduino Uno. On peut aussi remplaçer les boutons poussoirs par des DIP switches.
On va commencer par présenter brièvement le composant, puis le schéma du montage, ensuite le programme, la simulation et les tests sur plaque à essais.
On verra aussi comment on peut augmenter le nombre d'entrées de Arduino.
Présentation du 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.
Extrait documentation technique Texas Instruments
Fonctionnement à l'aide des chronogrammes:
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.
Le schéma :
Ce schéma a été réalisé sous Proteus, en choisissant ce logiciel, on peut 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 d'un "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 74HC165 | Borne 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é à 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é:
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:
Amélioration:
On va faire évoluer le montage précédent en ajoutant 8 entrées supplémentaires, ce qui fera 16 boutons poussoirs reliés à Arduino Uno.
Pour réaliser cela, 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.
Réalisation:
Le montage sera câblé sur plaque essai, en suivant le 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:
On peut observer 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.
Conclusion:
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 pas envoyer des commandes d'écriture à ce composant; il ne fonctionne qu'en lecture, 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.
JtBB