Communication ESP32 SPI : Broches, SPI multiples, Périphériques (Arduino)

Communication ESP32 SPI : Broches, SPI multiples, Périphériques (Arduino)

Ceci est un guide simple sur le protocole de communication SPI avec l’ESP32 à l’aide de l’IDE Arduino. Nous examinerons les broches SPI ESP32, comment connecter des appareils SPI, définir des broches SPI personnalisées, comment utiliser plusieurs appareils SPI, et bien plus encore.

ESP32 SPI Communication Set Broches Plusieurs Interfaces de Bus SPI et Périphériques Arduino IDE

Table des matières:

Ce tutoriel se concentre sur la programmation de l’ESP32 à l’aide du noyau Arduino, donc avant de continuer, vous devez avoir le module complémentaire ESP32 installé dans votre IDE Arduino. Suivez le tutoriel suivant pour installer l’ESP32 sur l’IDE Arduino, si vous ne l’avez pas déjà fait.

Alternativement, vous pouvez également utiliser VS Code avec l’extension PlatformIO pour programmer vos cartes à l’aide du noyau Arduino :

Présentation du protocole de communication ESP32 SPI

SPI signifie Ssérie Ppériphérique jenterface, et c’est un protocole de données série synchrone utilisé par les microcontrôleurs pour communiquer avec un ou plusieurs périphériques. Par exemple, votre carte ESP32 communiquant avec un capteur supportant le SPI ou avec un autre microcontrôleur.

Dans une communication SPI, il y a toujours un manette (aussi appelé Maître) qui contrôle le périphérique appareils (également appelés des esclaves). Les données peuvent être envoyées et reçues simultanément. Cela signifie que le maître peut envoyer des données à un esclave et qu’un esclave peut envoyer des données au maître en même temps.

Présentation du protocole de communication ESP32 SPI

Vous pouvez avoir un seul maître, qui sera un microcontrôleur (l’ESP32), mais vous pouvez avoir plusieurs esclaves. Un esclave peut être un capteur, un écran, une carte microSD, etc., ou un autre microcontrôleur. Cela signifie que vous pouvez avoir un ESP32 connecté à plusieurs capteurs, mais le même capteur ne peut pas être connecté à plusieurs cartes ESP32 simultanément.

Interface SPI

Pour la communication SPI, vous avez besoin de quatre lignes :

  • MISO: Entrée Maître Sortie Esclave
  • MOSI: Sortie maître Entrée esclave
  • SCK: Horloge série
  • CS /SS: Chip Select (utilisé pour sélectionner l’appareil lorsque plusieurs périphériques sont utilisés sur le même bus SPI)

Sur un appareil uniquement esclave, comme les capteurs, les écrans et autres, vous pouvez trouver une terminologie différente :

  • MISO peut être étiqueté comme ODD (Sortie de données série)
  • MOSI peut être étiqueté comme IDS (Entrée données série)

Périphériques ESP32 SPI

L’ESP32 intègre 4 périphériques SPI : SPI0, SPI1, SPI2 (communément appelés HSPI), et SPI3 (communément appelé VSPI).

SP0 et SP1 sont utilisés en interne pour communiquer avec la mémoire flash intégrée, et vous ne devez pas les utiliser pour d’autres tâches.

Vous pouvez utiliser HSPI et VSPI pour communiquer avec d’autres appareils. HSPI et VSPI ont des signaux de bus indépendants et chaque bus peut piloter jusqu’à trois esclaves SPI.

Broches SPI par défaut ESP32

De nombreuses cartes ESP32 sont livrées avec des broches SPI par défaut pré-assignées. Le mappage des broches pour la plupart des cartes est le suivant :

IPS MOSI MISO SCLK CS
VSPI GPIO 23 GPIO 19 GPIO 18 GPIO 5
HSPI GPIO 13 GPIO 12 GPIO 14 GPIO 15

Avertissement: selon la carte que vous utilisez, les broches SPI par défaut peuvent être différentes. Assurez-vous donc de vérifier le brochage de la carte que vous utilisez. De plus, certaines cartes n’ont pas de broches SPI pré-assignées, vous devez donc les définir sur le code.

Noter: généralement, lorsqu’elles ne sont pas spécifiées, la carte utilise les broches VSPI lors de l’initialisation d’une communication SPI avec les paramètres par défaut.

Que votre carte soit livrée avec des broches pré-assignées ou non, vous pouvez toujours les définir sur le code.

Trouver les broches SPI par défaut de votre carte ESP32

Si vous n’êtes pas sûr des broches SPI par défaut de votre carte, vous pouvez télécharger le code suivant pour le savoir.

/*
  Rui Santos
  Complete project details at https://Raspberryme.com/esp32-spi-communication-arduino/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

//Find the default SPI pins for your board
//Make sure you have the right board selected in Tools > Boards
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.print("MOSI: ");
  Serial.println(MOSI);
  Serial.print("MISO: ");
  Serial.println(MISO);
  Serial.print("SCK: ");
  Serial.println(SCK);
  Serial.print("SS: ");
  Serial.println(SS);  
}

void loop() {
  // put your main code here, to run repeatedly:
}

Afficher le code brut

Important: assurez-vous de sélectionner le tableau que vous utilisez dans Outils > Planchesinon, vous risquez de ne pas obtenir les bonnes broches.

Après avoir téléchargé le code, ouvrez le moniteur série, RST votre carte et vous verrez les broches SPI.

ESP32 Connaître les broches SPI par défaut

Utilisation de broches ESP32 SPI personnalisées

Lorsque vous utilisez des bibliothèques pour vous interfacer avec vos périphériques SPI, il est généralement simple d’utiliser des broches SPI personnalisées car vous pouvez les transmettre en tant qu’arguments au constructeur de la bibliothèque.

Par exemple, jetez un coup d’œil à l’exemple suivant qui s’interface avec un capteur BME280 en utilisant le Adafruit_BME280 bibliothèque.

/*
  Rui Santos
  Complete project details at https://Raspberryme.com/esp32-spi-communication-arduino/
  Based on the Adafruit_BME280_Library example: https://github.com/adafruit/Adafruit_BME280_Library/blob/master/examples/bme280test/bme280test.ino

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#include <SPI.h>
#define BME_SCK 25
#define BME_MISO 32
#define BME_MOSI 26
#define BME_CS 33
#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

unsigned long delayTime;

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));

  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin();  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  Serial.println("-- Default Test --");
  delayTime = 1000;

  Serial.println();
}


void loop() { 
  printValues();
  delay(delayTime);
}

void printValues() {
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");
  
  // Convert temperature to Fahrenheit
  /*Serial.print("Temperature = ");
  Serial.print(1.8 * bme.readTemperature() + 32);
  Serial.println(" *F");*/
  
  Serial.print("Pressure = ");
  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
}

Afficher le code brut

Vous pouvez facilement transmettre vos broches SPI personnalisées au constructeur de la bibliothèque.

Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);

Dans ce cas, j’utilisais les broches SPI suivantes (pas par défaut) et tout fonctionnait comme prévu :

#define BME_SCK 25
#define BME_MISO 32
#define BME_MOSI 26
#define BME_CS 33

Si vous n’utilisez pas de bibliothèque, ou si la bibliothèque que vous utilisez n’accepte pas les broches du constructeur de bibliothèque, vous devrez peut-être initialiser le bus SPI vous-même. Dans ce cas, vous devrez appeler le SPI.begin() méthode sur la mettre en place() et passez les broches SPI en arguments :

SPI.begin(SCK, MISO, MOSI, SS);

Vous pouvez voir un exemple de ce scénario dans ce didacticiel, dans lequel nous initialisons un émetteur-récepteur SPI LoRa connecté à des broches SPI personnalisées. Ou cet exemple montrant comment utiliser des broches SPI personnalisées avec un module de carte microSD.

ESP32 avec plusieurs appareils SPI

Comme nous l’avons vu précédemment, vous pouvez utiliser deux bus SPI différents sur l’ESP32 et chaque bus peut connecter jusqu’à trois périphériques différents. Cela signifie que nous pouvons connecter jusqu’à six appareils SPI à l’ESP32. Si vous avez besoin d’en utiliser plus, vous pouvez utiliser un multiplexeur SPI.

Plusieurs périphériques SPI (même bus, broche CS différente)

Pour connecter plusieurs périphériques SPI, vous pouvez utiliser le même bus SPI tant que chaque périphérique utilise une broche CS différente.

Communication SPI plusieurs périphériques même bus

Pour sélectionner le périphérique avec lequel vous souhaitez communiquer, vous devez définir son CS épingler à BAS. Par exemple, imaginez que vous avez le périphérique 1 et le périphérique 2. Pour lire à partir du périphérique 1, assurez-vous que son CS la broche est réglée sur BAS (représenté ici par CS_1):

digitalWrite(CS_1, LOW); // enable CS pin to read from peripheral 1

/*
 use any SPI functions to communicate with peripheral 1
*/

Ensuite, au même point, vous voudrez lire à partir du périphérique 2. Vous devez désactiver le périphérique 1 CS pin en le réglant sur HAUTEet activez le périphérique 2 CS pin en le réglant sur BAS:

digitalWrite(CS_1, HIGH); // disable CS pin from peripheral 1
digitalWrite(CS_2, LOW);  // enable CS pin to read from peripheral 2

/*
 use any SPI functions to communicate with peripheral 2
*/

ESP32 utilisant deux interfaces de bus SPI (utilisez simultanément HSPI et VSPI)

Pour communiquer simultanément avec plusieurs périphériques SPI, vous pouvez utiliser les deux bus SPI ESP32 (HSPI et VSPI). Vous pouvez utiliser les broches HSPI et VSPI par défaut ou utiliser des broches personnalisées.

Interfaces de bus SPI multiples ESP32

En bref, pour utiliser HSPI et VSPI simultanément, il vous suffit de le faire.

1) Tout d’abord, assurez-vous d’inclure la bibliothèque SPI dans votre code.

#include <SPI.h>

2) Initialiser deux Classe SPI objets avec des noms différents, un sur le bus HSPI et un autre sur le bus VSPI. Par exemple:

vspi = new SPIClass(VSPI);
hspi = new SPIClass(HSPI);

3) Appeler le commencer() méthode sur ces objets.

vspi.begin();
hspi.begin();

Vous pouvez transmettre des épingles personnalisées au commencer() méthode si nécessaire.

vspi.begin(VSPI_CLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
hspi.begin(HSPI_CLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);

4) Enfin, vous devez également définir les broches SS comme sorties. Par exemple:

pinMode(VSPI_SS, OUTPUT);
pinMode(HSPI_SS, OUTPUT);

Ensuite, utilisez les commandes habituelles pour interagir avec les appareils SPI, que vous utilisiez une bibliothèque de capteurs ou les méthodes de la bibliothèque SPI.

Vous pouvez trouver un exemple d’utilisation de plusieurs bus SPI sur le Bibliothèque SPI arduino-esp32. Voir l’exemple ci-dessous :



/* The ESP32 has four SPi buses, however as of right now only two of
 * them are available to use, HSPI and VSPI. Simply using the SPI API 
 * as illustrated in Arduino examples will use VSPI, leaving HSPI unused.
 * 
 * However if we simply intialise two instance of the SPI class for both
 * of these buses both can be used. However when just using these the Arduino
 * way only will actually be outputting at a time.
 * 
 * Logic analyser capture is in the same folder as this example as
 * "multiple_bus_output.png"
 * 
 * created 30/04/2018 by Alistair Symonds
 */
#include <SPI.h>

// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus

#ifdef ALTERNATE_PINS
  #define VSPI_MISO   2
  #define VSPI_MOSI   4
  #define VSPI_SCLK   0
  #define VSPI_SS     33

  #define HSPI_MISO   26
  #define HSPI_MOSI   27
  #define HSPI_SCLK   25
  #define HSPI_SS     32
#else
  #define VSPI_MISO   MISO
  #define VSPI_MOSI   MOSI
  #define VSPI_SCLK   SCK
  #define VSPI_SS     SS

  #define HSPI_MISO   12
  #define HSPI_MOSI   13
  #define HSPI_SCLK   14
  #define HSPI_SS     15
#endif

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define VSPI FSPI
#endif

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * vspi = NULL;
SPIClass * hspi = NULL;

void setup() {
  //initialise two instances of the SPIClass attached to VSPI and HSPI respectively
  vspi = new SPIClass(VSPI);
  hspi = new SPIClass(HSPI);
  
  //clock miso mosi ss

#ifndef ALTERNATE_PINS
  //initialise vspi with default pins
  //SCLK = 18, MISO = 19, MOSI = 23, SS = 5
  vspi->begin();
#else
  //alternatively route through GPIO pins of your choice
  vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS); //SCLK, MISO, MOSI, SS
#endif

#ifndef ALTERNATE_PINS
  //initialise hspi with default pins
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  hspi->begin();
#else
  //alternatively route through GPIO pins
  hspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
#endif

  //set up slave select pins as outputs as the Arduino API
  //doesn't handle automatically pulling SS low
  pinMode(vspi->pinSS(), OUTPUT); //VSPI SS
  pinMode(hspi->pinSS(), OUTPUT); //HSPI SS

}

// the loop function runs over and over again until power down or reset
void loop() {
  //use the SPI buses
  spiCommand(vspi, 0b01010101); // junk data to illustrate usage
  spiCommand(hspi, 0b11001100);
  delay(100);
}

void spiCommand(SPIClass *spi, byte data) {
  //use it as you would the regular arduino SPI API
  spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer
  spi->transfer(data);
  digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer
  spi->endTransaction();
}

Afficher le code brut

Conclusion

Cet article était un guide rapide et simple vous montrant comment utiliser la communication SPI avec l’ESP32 à l’aide du noyau Arduino, l’ESP32 agissant comme un contrôleur (Maître).

En résumé, l’ESP32 dispose de quatre bus SPI, mais seuls deux peuvent être utilisés pour contrôler des périphériques, le HSPI et le VSPI. La plupart des ESP32 ont des GPIO HSPI et VSPI pré-assignés, mais vous pouvez toujours modifier l’affectation des broches dans le code.

Vous pouvez utiliser les bus HSPI et VSPI simultanément pour piloter plusieurs périphériques SPI, ou vous pouvez utiliser plusieurs périphériques sur le même bus tant que leur broche CS est connectée à un GPIO différent.

Nous n’avons pas approfondi les exemples, car chaque capteur, bibliothèque et scénario de cas est différent. Mais, maintenant, vous devriez avoir une meilleure idée de la façon d’interfacer un ou plusieurs appareils SPI avec l’ESP32.

Pour des informations plus détaillées sur le pilote SPI Master sur l’ESP32, vous pouvez consultez la documentation officielle espressif.

Nous n’avons pas couvert la configuration de l’ESP32 en tant qu’esclave SPI, mais vous pouvez vérifier ces exemples.

Nous espérons que vous trouverez ce tutoriel utile. Nous avons un article similaire, mais sur le protocole de communication I2C. Découvrez-le sur le lien suivant :

En savoir plus sur l’ESP32 avec nos ressources :

Merci d’avoir lu.