Pilotage de registres à décalage 74HC595
publication: 15 janvier 2024 / mis à jour 15 janvier 2024
Appel à collaboration
Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.
Partagez-les ici sur ce site.
ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.
Vos montages peuvent aider d'autres développeurs.
Les montages des autres développeurs peuvent vous aider.
Pour proposer un article ou un montage, cliquez ici
Préambule
Début janvier 2024, j'ai commandé et reçu deux cartes ESP32-C3-Zero. Ce sont des cartes ESP32 mono coeur, avec un processeur RISC-V. C'est une vraie carte ESP32, mais qui fait la moitié de la longueur d'une carte ARDUINO Nano:
Contrairement à la carte ARDUINO NANO, cette carte ESP32-C3-Zero dispose des interfaces WiFi, Bluetooth, SPI, I2S, UART... Et aussi la carte ESP32-C3-Zero utilise un processeur cadencé à 160 Mhz, quand la carte ARDUINO NANO est cadencée seulement à 16 Mhz.
L'autre bonne surprise, c'est l'installation de ESP32forth. Elle s'est déroulée sans souci. Mais surtout, c'est la place disponible dans le dictionnaire FORTH:
--> ESP32forth v7.0.7.17 - rev af26e61de914602aa8f4193ce34d728cd0f209fa ESP32-C3 160 MHz 1 cores 4194304 bytes flash System Heap: 59840 free + 281920 used = 341760 total (17% free) 44020 bytes max contiguous Forth dictionary: 152048 free + 33132 used = 185180 total (82% free) 3 x Forth stacks: 2048 bytes each
Quand on connait l'extraordinaire compacité du langage FORTH, autant dire que ce sera très difficile d'exploiter toute cette place!
Seule bémol, c'est le nombre de ports GPIO disponibles, seulement 15 ports GPIO. C'est donc l'occasion, au travers de cet aricle de montrer que cette contrainte peut être contournée sans problème.
Le registre à décalage 74HC595
C'est un composant électronique monté dans un boitier DIN 16 broches. Disposition des pins:
- VCC alimentation de 2V à 5,5V
- GND masse
- Q0..Q7 sorties digitales
- Q7S sortie série, utilisée pour commander un autre registre 74HC595
- DS entrée série des données
- OE activation ou non du composant. Un niveau haut désactive le composant. Non utilisé
- SCTP gâchette du composant. Bascule les bits en attente vers les sorties Q0..Q7/Q7S
- SHCP entrée du signal d'horloge
- MR si cette netrée passe à l'état bas, le composant est réinitialisé. Pour l'utiliser, on appliquera une tension positive.
Voici comment le composant 74HC595 traite les signaux transmis par un micro-contrôleur:
Nous n'avons besoin de gérer que trois entrées sur le registre à décalage 74HC595: DS, SHCP et STCP. Voyons comment connecter ces entrées à notre carte ESP32-C3-Zero. A noter que les explications qui suivent sont valables sur toutes les cartes ESP32.
Câblage des registres 74HC595
Le câblage des registres 74HC595 ne nécessite que trois fils en sortie de la carte ESP32.
Voici les connections à réaliser entre la carte ESP32 et le registre 74HC595:
GPIO 06 CS1 -- 12 STCP GPIO 07 MOSI -- 14 DS GPIO 08 SCLK -- 11 SHCP
- CS1 GPIO 06 est connecté au pin 12 (STCP) de chacun des registres. Ici, fil orange;
- MOSI GPIO 07 est connecté au pin 14 (DS) du premier registre. Les autres registres sont chaînés par le pin 9 (QS7) --> pin 14 (DS). Ici fil bleu.
- SCLK GPIO 08 est connecté au pin 11 (SHCP) de chacun des registres, ici fil vert;
- tous les pins 10 (MR) des registres sont forcés à VCC. Ici fil rouge.
- tous les pins 8 (GND) sont connectés à GND. ici fil noir.
Avec ce montage, on peut gérer 24 sorties supplémentaires. Il n'y a pas de limite au nombre de registres 74HC595 pouvant être chaînés.
Paramétrer le port SPI de la carte ESP32
Sur la carte ESP32-C3-Zero, tous les pins GPIO 00 à 10 sont utilisables pour une sortie SPI. En pré-requis, vous devez implanter
la librairie SPI. Tout est expliqué ici:
Implémentation du vocabulaire SPI
J'ai été surpris, lors de mes recherches, avec ces mots clés "ESP32 SPI 74HC595", de voir que sur de très nombreux sites on affirme qu'on ne peut pas piloter le composant 74HC595 par un port SPI. Sur GITHUB, il existe quelques contributions démontrant le contraire, mais sans explication.
Seule une page web, utilisant micro-Python, explique les paramétrages de la carte SPI, mais pour ARDUINO!
J'ai procédé à quelques essais, en testant les signaux transmis, avec un oscilloscope d'entrée de gamme. Voici les paramètres du port SPI pour la carte ESP32-C3-Zero:
6 constant CS1 \ Chip Select, SS1 SPI signal 7 constant MOSI \ Master Out Slave In 8 constant SCLK \ Signal CLocK -1 constant MISO \ unused 100000 constant SPI_FREQ 0 constant LSBFIRST 1 constant MSBFIRST \ definition of SPI_MODE0..SPI_MODE3 constants 0 constant SPI_MODE0 1 constant SPI_MODE1 2 constant SPI_MODE2 3 constant SPI_MODE3 : SPI.init ( -- ) CS1 OUTPUT pinMode \ set pins mode [ SPI ] SCLK MISO MOSI CS1 SPI.begin \ set SPI GPIOs SPI_FREQ SPI.setFrequency \ set SPi frequency transmission MSBFIRST SPI.setBitOrder \ set bit order SPI_MODE0 SPI.setDataMode \ set SPI mode [ FORTH ] ;
Dans notre code source, cette ligne -1 constant MISO
indique qu'on n'attribue aucun
port GPIO au signal MISO (Master In Slave Out).
Dans la définition de SPI.init
, seule la sortie CS1 est paramétrée en sortie: CS1 OUTPUT pinMode
.
Il n'est pas nécessaire de paramétrer les autres sorties SCLK
, MOSI
et CS1
,
c'est SPI.begin
qui s'en charge.
Dans certains codes sources en langage C, la fonction SPI.begin
est utilisée en dernier. C'est une erreur. Cette fonction
doit être appelée avant de compléter le paramétrage du port SPI.
L'intérêt de passer par l'interface SPI est évident. Grâce à cet interface, il n'est plus nécessaire de gérer un signal d'horloge, sérialiser des octets. Si on respecte le standard SPI, voici le chronogramme des actions à réaliser pour transmettre un octet:
- mise au niveau bas de CS1
- transmission de l'octet par MOSI.
- Le signal CS se déclenche dès le début de la transmission par MOSI
Sauf que ce chronogramme NE FONCTIONNE PAS!
Transmission des données par le port SPI
Voici d'abord le code FORTH pour créer et gérer un tampon de données destinées à nos registres 74HC595:
3 constant NB_SHIFT_REGS create DATAS NB_SHIFT_REGS allot \ store byte at pos in DATAS, pos [0..NB_SHIFT_REGS-1] : data! ( byte pos -- ) DATAS + c! ;
Le tampon DATAS
est dimensionné en fonction du nombre de regsitres 74HC595. ici, il est dimensionné à trois octets.
Le mot data!
permet de mettre une valeur à transmettre, exemple 64 0 data!
enregistre la valeur 64 dans le premier octet
de DATAS
.
Voici le code pour transmettre le contenu du tampon DATAS
:
: DATAS.send ( -- )
[ SPI ]
NB_SHIFT_REGS 0 do
DATAS NB_SHIFT_REGS 1- i - +
c@ SPI.write
loop
1 SPI.setHwCs
1 ms
0 SPI.setHwCs
[ forth ]
;
Ici la boucle
do..loop
traite d'abord dle dernier octet dans DATAS et termine par le premier octet.C'est la séquence c@ SPI.write
qui transmet un octet vers les registres 74HC595.
Mais ce qui différence surtout cette définition par rapport au standard de transmission SPI, c'est l'utilisation du signal CS
après la transmission en série des octets. En fin de transmission, on met le pin CS1 à l'état haut avec 1 SPI.setHwCs
, puis on
attend une milliseconde et on redescend au niveau 0 avec 0 SPI.setHwCs
.
Sur cette photo, on a testé ce simple code de test:
SPI.init 255 0 data! DATA.send
Dans ce montage, seul un registre a décalage est câblé sur huit LEDs. L'ordre de transmssion des octets doit toujours s'effectuer en commençant par l'octet final. Si on numérote nos octets successivement c0 c1 et c2, l'ordre de transmission des octets sera c2 c1 et c0 selon notre boucle:
: DATAS.send ( -- ) [ SPI ] NB_SHIFT_REGS 0 do DATAS NB_SHIFT_REGS 1- i - + c@ SPI.write loop 1 SPI.setHwCs 1 ms 0 SPI.setHwCs [ forth ] ;
Il y a moyen de simplifier le code en bleu et rouge.
Transmission SPI sans boucle
C'est après une succession d'essais divers que le choix s'est arrêté sur le mot SPI.writeBytes
. Ce mot
accepte deux paramètres:
- l'adresse des données à transmettre;
- le nombre d'octets à transmettre.
En langage C, la fonction writeBytes() de la librairie SPI est très mal documentée. Et les codes sources exploitant cette fonction sont indigents. C'est malheureusement le lot des librairies utilisées telles quelles. En fait, les programmeurs utilisent du code sans chercher à approfondir.
On utilisera SPI.writeBytes
pour transmettre le contenu de DATAS
sans utiliser de boucle de transmission:
DATAS 3 SPI.writeBytes
Le souci, avec ce code, c'est que l'octet c0 sera transmis en premier, c1 en second, c2 en dernier. En transmettant les octets dans cet ordre, les registres à décalage vont traiter ces octets dans cet ordre:
- c0 est traité par le troisième registre 74HC595;
- c1 est traité par le second registre;
- c2 est traité par le premier registre;
La solution la plus simple consistera donc à inverser les valeurs à affecter aux octets de DATAS:
\ store byte for regn in DATAS, regn [0..NB_SHIFT_REGS-1] : data! ( byte regn -- ) NB_SHIFT_REGS 1- swap - \ calculate inverse offset DATAS + c! ;
Ici, le paramètre regn doit être le numéro de registre, 0 pour le premier registre, 1 pour le suivant, etc...
La définition DATAS.send
réécrite:
: DATAS.send ( -- )
DATAS NB_SHIFT_REGS SPI.writeBytes
nop
1 SPI.setHwCs
nop nop
0 SPI.setHwCs
;
Nous allons voir comment exploiter de manière pratique cette nouvelle définition.
Pilotage de huit LEDs connectées à un registre 74HC595
Voici le câblage de huit LEDs connectées à un registre 74HC595:
L'utilisation de LEDs n'a aucun intérêt pratique. Ici, ces LEDs servent à vérifier le bon fonctionnement du câblage et des définitions FORTH. En pratique, ce peut être des relais ou tout autre appareil pouvant être commandé par les sorties Q0..Q7 de nos registres à décalage 74HC595.
Voici une toute petite définition:
0 constant 1ST_74HC
: xs ( n -- )
1ST_74HC data!
DATAS.send ;
Résultat des tests:
1 xs
allume la première LED à partir de la droite;2 xs
allume la seconde LED à partir de la droite, etc....128 xs
allume la dernière LED à partir de la droite.
Toute autre valeur entre [1..255] matérialisera la valeur binaire utilisée par le mot xs
.
Il est déconseillé d'allumer toutes les LEDs, celles-ci étant alimentées via la carte ESP32. Pour allumer toutes les LEDs, il est fortement recommandé d'alimenter les registres à décalage avec une alimentation indépendante.
Les codes sources complets sont accessibles ici:
https://github.com/MPETREMANN11/ESP32forth/tree/main/__my%20projects/GPIOs/74HC595
Legal: site web personnel sans commerce / personal site without seling