Le SPI est le bus série synchrone et rapide qui relie l’ESP32 à des périphériques exigeants — carte SD, écran TFT, capteurs à haut débit — sur quatre fils : SCK (horloge), MOSI (données sortantes), MISO (données entrantes) et un CS par périphérique. Sur ESP32, deux bus sont utilisables (VSPI et HSPI). Les broches VSPI par défaut sont SCK = GPIO18, MISO = GPIO19, MOSI = GPIO23, CS = GPIO5, et elles sont remappables, au prix d’une vitesse plafonnée si l’on quitte les broches natives.

À quoi ça sert ?

Là où l’I2C plafonne, le SPI transfère vite et en full-duplex (émission et réception simultanées) :

  • Stocker. Une carte microSD enregistre mesures et journaux. C’est l’usage le plus courant du SPI en projet.
  • Afficher richement. Les écrans TFT couleur rafraîchissent des images entières — impossible en I2C.
  • Lire vite. Certains ADC, capteurs de mouvement ou modules radio n’existent qu’en SPI pour leur débit.

Le fonctionnement du protocole (horloge, full-duplex, sélection par CS) est décrit dans la notion transverse SPI. Ici, on voit comment le câbler et le coder sur ESP32.

Procédure pas à pas

Quatre temps : câbler le faisceau, initialiser, exploiter via une bibliothèque, ajouter des périphériques.

1. Câbler : un faisceau partagé, un CS par module

SCK, MOSI et MISO sont communs à tous les périphériques du bus. Seul le CS (Chip Select) est propre à chacun : c’est lui qui désigne le module actif. Contrairement à l’UART, le SPI ne croise pas : MOSI va sur MOSI, MISO sur MISO.

Branchement SPI entre un ESP32 et un module (carte SD) : SCK sur GPIO18, MOSI sur GPIO23, MISO sur GPIO19, CS sur GPIO5, alimentation 3,3 V, masse commune|640

Warning

Périphérique en 3,3 V. L’ESP32 travaille en 3,3 V : un module SPI 5 V (certains lecteurs SD à régulateur) doit soit disposer d’une adaptation de niveau intégrée, soit passer par un adaptateur (voir niveaux de tension).

2. Initialiser le bus

SPI.begin() sans argument utilise VSPI (broches par défaut). Les bibliothèques (SD, TFT) appellent souvent begin() elles-mêmes. On leur passe surtout le CS :

#include <SPI.h>
 
const int CS = 5;   // VSPI : SCK=18, MOSI=23, MISO=19 par défaut

3. Exploiter via une bibliothèque

On manipule rarement SPI.transfer() à la main : une bibliothèque (SD, Adafruit GFX pour un TFT) gère le protocole. On lui indique le CS et, au besoin, une vitesse d’horloge.

4. Ajouter des périphériques

Pour un second module, on partage SCK/MOSI/MISO et on lui attribue un autre CS (un GPIO libre). Le code active un seul CS à la fois.

Exemple — Journaliser sur carte microSD

Cas concret : écrire une ligne de mesure dans un fichier sur carte SD, puis la relire. C’est le point d’entrée du datalogger embarqué.

#include <SPI.h>
#include <SD.h>
 
const int CS = 5;   // CS du lecteur SD sur GPIO5 (VSPI)
 
void setup() {
  Serial.begin(115200);
 
  if (!SD.begin(CS)) {                 // VSPI par défaut : SCK18 / MISO19 / MOSI23
    Serial.println("Carte SD absente ou mal cablee");
    return;
  }
 
  File f = SD.open("/mesures.csv", FILE_WRITE);   // ouvre (crée si besoin)
  if (f) {
    f.println("temps;valeur");         // en-tête
    f.println("0;512");                // une mesure
    f.close();                         // close() obligatoire : vide le tampon sur la carte
    Serial.println("Ecrit.");
  }
 
  // relecture
  f = SD.open("/mesures.csv");
  while (f && f.available()) {
    Serial.write(f.read());            // renvoie le contenu au moniteur
  }
  f.close();
}
 
void loop() {}

SD.begin(CS) initialise le bus VSPI et monte la carte. SD.open(..., FILE_WRITE) ouvre le fichier en écriture. Le close() est indispensable : il vide le tampon et referme le fichier, sans quoi la dernière écriture peut être perdue. La relecture rouvre le fichier et renvoie son contenu au moniteur.

Au moniteur :

Ecrit.
temps;valeur
0;512

Les deux dernières lignes ne viennent pas d’un println du sketch : c’est le contenu du fichier, relu octet par octet et renvoyé par Serial.write(). La preuve que l’écriture a bien atteint la carte.

Pièges

MOSI et MISO croisés. Réflexe hérité de l’UART, mais le SPI ne croise pas : MOSI sur MOSI, MISO sur MISO. Croiser donne un module muet.

CS oublié ou partagé. Deux modules sur le même CS répondent ensemble et se brouillent. Chaque périphérique a son CS sur un GPIO distinct.

Carte SD non détectée. Souvent un CS erroné, un fil MISO/MOSI inversé, ou une carte mal formatée (FAT32). Vérifier d’abord le câblage broche à broche contre le code.

Périphérique 5 V sur l’ESP32. Les lignes en 5 V agressent les broches 3,3 V. Choisir un module 3,3 V ou adapter le niveau.

Broches remappées, débit en baisse. Passer par d’autres GPIO que les broches natives fait transiter le signal par la matrice interne : la vitesse tombe (~40 MHz au lieu de 80). Pour la performance maximale, garder les broches VSPI par défaut.

Masse non reliée. Comme tout bus, le SPI exige une masse commune entre l’ESP32 et le périphérique.

Exercices

Exercice 1 — Datalogger cadencé

Reprenez la carte SD pour enregistrer une mesure chaque seconde, sans figer le programme. Indice : cadencer sur millis(), ouvrir/écrire/fermer à chaque relevé.

Exercice 2 — Deux périphériques sur le bus

Ajoutez un second module SPI (par exemple un écran) à côté de la carte SD. Que partagent-ils, qu’est-ce qui les distingue ?

Cas particulier — Le second bus et la vitesse

L’ESP32 offre un deuxième bus SPI, HSPI, pour séparer deux groupes de périphériques ou éviter une saturation. On l’instancie via SPIClass :

SPIClass hspi(HSPI);
hspi.begin(14, 12, 13, 15);   // SCK, MISO, MOSI, CS

La vitesse d’horloge se règle par SPISettings (souvent porté par la bibliothèque). Les broches natives (VSPI : 18/19/23/5 ; HSPI : 14/12/13/15) autorisent jusqu’à 80 MHz. Des broches remappées plafonnent plus bas.

Sur les variantes C3 / S3, l’organisation des bus SPI et les broches par défaut diffèrent. Se reporter au brochage via configurer les GPIO.

Raccrochage projet

  • Preuve de concept — dès qu’il faut stocker des mesures (datalogger) ou afficher richement, le SPI est le bus adapté. L’exemple carte SD valide l’enregistrement en quelques lignes.
  • Intégration et tests — journaliser sur SD pendant les essais donne une trace exploitable a posteriori. L’écran TFT affiche l’état du système en autonomie.

Voir aussi