Bus SPI : comprendre MOSI, MISO, SCK et CS avec Arduino
Qu'est-ce que le bus SPI ? MOSI, MISO, SCK et CS, modes et vitesse, plusieurs périphériques, brochage Uno, Mega, ESP32 et Pico, conflit carte SD et RFID.
Le SPI (Serial Peripheral Interface, interface série pour périphériques) est un mode de communication qui permet à un microcontrôleur d'échanger très rapidement des données avec des composants comme les cartes SD, les lecteurs RFID, les écrans TFT couleur ou les modules sans fil, au moyen de quatre fils. Il y a une ligne d'horloge (SCK), deux lignes de données séparées pour chaque sens (MOSI et MISO) et une ligne CS qui choisit le périphérique auquel on parle. Comme il peut être des dizaines de fois plus rapide que l'I2C, c'est le bus préféré des modules qui transportent beaucoup de données.
Dans cet article, tu vas apprendre comment fonctionne le SPI, le nom des broches et la nouvelle terminologie, les quatre modes SPI, les limites de vitesse, le brochage de l'Arduino Uno, du Mega, de l'ESP32 (VSPI et HSPI) et du Raspberry Pi Pico, comment brancher plusieurs périphériques sur le même bus et pourquoi une carte SD et un lecteur RFID RC522 posent problème ensemble. Dans la dernière partie, nous comparons le SPI à l'I2C et à l'UART.
Qu'est-ce que le SPI et comment fonctionne-t-il ?
En SPI, il y a toujours un contrôleur (autrefois appelé maître) et un ou plusieurs périphériques (autrefois appelés esclaves). Seul le contrôleur génère l'horloge : c'est donc l'Arduino qui démarre l'échange, fixe sa vitesse et le termine. À chaque impulsion d'horloge, le contrôleur envoie un bit sur MOSI pendant que le périphérique renvoie un bit sur MISO. Les registres à décalage des deux côtés forment une sorte d'anneau : après 8 impulsions, l'octet du contrôleur est passé dans le périphérique et celui du périphérique dans le contrôleur. C'est pourquoi le SPI est full duplex : lecture et écriture ont lieu en même temps.
| Ligne | Ancien nom | Nouveau nom | Sens | Rôle |
|---|---|---|---|---|
| SCK / SCLK | Serial Clock | SCK | Contrôleur → périphérique | Signal d'horloge ; un bit passe à chaque impulsion |
| MOSI | Master Out Slave In | COPI / SDO | Contrôleur → périphérique | Données de l'Arduino vers le module |
| MISO | Master In Slave Out | CIPO / SDI | Périphérique → contrôleur | Données du module vers l'Arduino |
| CS / SS | Slave Select | CS (Chip Select) | Contrôleur → périphérique | Tant qu'elle est à LOW, ce module écoute ; chaque périphérique a son propre CS |
Les inscriptions sur les modules ne sont pas toujours les mêmes, et c'est la principale source de confusion. Sur le module RFID RC522, la ligne CS s'appelle SDA (rien à voir avec le SDA de l'I2C), sur le nRF24L01 CSN, sur le MCP3008 CS/SHDN, et sur certains écrans tu verras DIN (MOSI), CLK (SCK) et DOUT (MISO). La règle est simple : l'entrée de données (DIN, SDI, MOSI) va sur le MOSI de l'Arduino et la sortie de données (DOUT, SDO, MISO) sur le MISO de l'Arduino.
- Le contrôleur met à LOW la ligne CS du périphérique auquel il veut parler. Tous les autres gardent leur CS à HIGH et libèrent la ligne MISO.
- Le contrôleur commence à générer des impulsions d'horloge sur SCK.
- À chaque impulsion, un bit sort sur MOSI et un bit entre sur MISO. L'ordre habituel est le bit de poids fort en premier (MSB first).
- Une fois les octets nécessaires transférés (commande, adresse, données), le contrôleur remet CS à HIGH et le périphérique termine l'opération.
Les modes SPI : CPOL et CPHA
Le SPI n'a pas de norme unique ; les périphériques diffèrent par le niveau de repos de l'horloge (CPOL, polarité d'horloge) et par le front d'horloge sur lequel les données sont lues (CPHA, phase d'horloge). Les quatre combinaisons de ces deux réglages forment les quatre modes SPI. Si le contrôleur et le périphérique ne sont pas dans le même mode, les données sont décalées d'un bit et tu lis des valeurs absurdes. Heureusement, la grande majorité des modules utilise le mode 0.
| Mode | CPOL | CPHA | Horloge au repos | Front de lecture | Exemples de composants |
|---|---|---|---|---|---|
| SPI_MODE0 | 0 | 0 | LOW | Montant | Carte SD, RC522, nRF24L01, MAX7219, MCP3008, 74HC595 |
| SPI_MODE1 | 0 | 1 | LOW | Descendant | Certains CAN et circuits de commande |
| SPI_MODE2 | 1 | 0 | HIGH | Descendant | Rarement utilisé |
| SPI_MODE3 | 1 | 1 | HIGH | Montant | Accéléromètre ADXL345, certains écrans ST7789 sans broche CS |
Vitesse SPI et longueur des câbles
En SPI, c'est le contrôleur qui fixe la vitesse, et la limite vient généralement du périphérique lui-même. L'Arduino Uno peut monter à 8 MHz, la moitié de son horloge de 16 MHz ; la valeur par défaut de la bibliothèque SPI est de 4 MHz. L'ESP32 peut générer jusqu'à 80 MHz sur ses broches SPI dédiées (IO_MUX), et cette limite baisse quand le signal passe par la matrice GPIO vers d'autres broches. Le Raspberry Pi Pico atteint environ 62,5 MHz avec une horloge système de 125 MHz. Les signaux SPI rapides demandent des fils courts : avec une breadboard et des fils de 10 à 20 cm, quelques MHz ne posent aucun problème ; à partir de 20–30 MHz, garde les fils courts et soude les connexions si possible. Plusieurs mètres de câble ne conviennent pas au SPI.
| Composant | Rôle | Horloge SPI maximale (fiche technique) | Mode SPI |
|---|---|---|---|
| Carte microSD | Enregistrement de données | 400 kHz au démarrage, puis jusqu'à 25 MHz | Mode 0 |
| RC522 (MFRC522) | Lecteur RFID | 10 MHz | Mode 0 |
| nRF24L01 | Radio 2,4 GHz | 10 MHz | Mode 0 |
| MAX7219 | Matrice LED / 7 segments | 10 MHz | Mode 0 |
| MCP3008 | CAN 8 voies 10 bits | 3,6 MHz à 5 V, 1,35 MHz à 2,7 V | Mode 0 ou 3 |
| ILI9341 | TFT couleur 2,4–3,2 pouces | 10 MHz en écriture (piloté bien plus vite en pratique) | Mode 0 |
Broches SPI : Arduino Uno, Mega, ESP32 et Raspberry Pi Pico
| Ligne | Arduino Uno / Nano | Arduino Mega | ESP32 VSPI (par défaut) | ESP32 HSPI | Raspberry Pi Pico SPI0 |
|---|---|---|---|---|---|
| SCK | D13 | D52 | GPIO 18 | GPIO 14 | GP18 |
| MOSI | D11 | D51 | GPIO 23 | GPIO 13 | GP19 (TX) |
| MISO | D12 | D50 | GPIO 19 | GPIO 12 | GP16 (RX) |
| CS (par défaut) | D10 | D53 | GPIO 5 | GPIO 15 | GP17 |
| Niveau logique | 5 V | 5 V | 3,3 V | 3,3 V | 3,3 V |
Sur l'Uno, les mêmes lignes SPI se trouvent aussi sur le connecteur ICSP à 6 broches au bord de la carte ; sur des cartes comme la Leonardo et la Micro, le SPI n'est disponible que sur l'ICSP. D10 n'est pas obligatoire pour CS : n'importe quelle broche numérique convient. Mais sur l'Uno, ne laisse pas D10 en entrée : si le matériel SPI lit LOW sur D10 alors qu'elle est en entrée, il quitte le mode contrôleur. SPI.begin() configure automatiquement cette broche en sortie, et tu ne dois pas la remettre en entrée pour autre chose. Sur l'ESP32, l'objet SPI d'Arduino utilise VSPI par défaut ; grâce à la matrice GPIO, tu peux aussi déplacer le SPI sur presque n'importe quelles broches. Sur le Pico, SPI0 et SPI1 peuvent être affectés à plusieurs groupes de broches (par ex. GP10, GP11, GP12 pour SPI1) ; tous les détails sont dans l'outil Pinout.
La bibliothèque SPI d'Arduino : fonctions de base
| Fonction | Que fait-elle ? |
|---|---|
| SPI.begin() | Démarre le matériel SPI ; met les broches SCK, MOSI et SS en sortie. |
| SPISettings(vitesse, MSBFIRST, SPI_MODE0) | Regroupe dans un objet la vitesse, l'ordre des bits et le mode d'un périphérique. |
| SPI.beginTransaction(réglages) | Applique les réglages et réserve le bus pour ce périphérique ; rend sûr le passage entre périphériques aux réglages différents. |
| SPI.transfer(octet) | Envoie un octet et renvoie l'octet reçu au même moment. |
| SPI.transfer16(valeur) | Envoie et reçoit une valeur de 16 bits d'un coup. |
| SPI.transfer(tampon, longueur) | Envoie un tableau ; les octets reçus écrasent le même tableau. |
| SPI.endTransaction() | Libère le bus ; à appeler après avoir remis CS à HIGH. |
Premier exemple : envoyer des données à un 74HC595 en SPI
Le plus simple pour comprendre le SPI est d'utiliser un registre à décalage 74HC595, car le 595 est en réalité le périphérique SPI le plus simple qui soit, sans MISO. La broche MOSI de l'Arduino va sur l'entrée DS du 595, SCK sur SH_CP et D10 sur ST_CP, qui sert de verrou (latch). Contrairement à la fonction shiftOut(), le SPI matériel envoie l'octet en quelques microsecondes :
1// Donanım SPI ile 74HC595: 8 LED'i iki kabloyla sürmek / 74HC595 over hardware SPI: 8 LEDs from two data wires
2// D11 (MOSI) -> DS (14), D13 (SCK) -> SH_CP (11), D10 -> ST_CP / latch (12)
3#include <SPI.h>
4
5const int LATCH_PIN = 10; // 595'te CS gibi davranır / acts like CS on the 595
6
7void write595(byte value) {
8 SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); // 4 MHz, mod 0 / 4 MHz, mode 0
9 digitalWrite(LATCH_PIN, LOW);
10 SPI.transfer(value); // 8 biti gönder / shift out 8 bits
11 digitalWrite(LATCH_PIN, HIGH); // yükselen kenarda çıkışlara aktar / latch on the rising edge
12 SPI.endTransaction();
13}
14
15void setup() {
16 pinMode(LATCH_PIN, OUTPUT);
17 digitalWrite(LATCH_PIN, HIGH);
18 SPI.begin();
19}
20
21void loop() {
22 for (int i = 0; i < 8; i++) { // yürüyen ışık / running light
23 write595(1 << i);
24 delay(100);
25 }
26}Lire des données en SPI : le CAN MCP3008
Pour voir la communication full duplex, utilisons le MCP3008. Ce circuit ajoute à l'Arduino 8 entrées analogiques de 10 bits supplémentaires ; c'est une bonne alternative au CAN peu linéaire de l'ESP32 ou aux 3 seules entrées analogiques du Pico. Nous avons expliqué les bases de la lecture analogique dans l'article Qu'est-ce qu'un CAN ?. Câblage : CLK → D13, DOUT → D12, DIN → D11, CS → D10, VDD et VREF → 5V, AGND et DGND → GND.
1// MCP3008 (8 kanal, 10 bit ADC) okuma / Reading an MCP3008 (8-channel 10-bit ADC)
2// D13 -> CLK, D12 <- DOUT, D11 -> DIN, D10 -> CS/SHDN
3#include <SPI.h>
4
5const int CS_PIN = 10;
6SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0); // 1 MHz, mod 0 / 1 MHz, mode 0
7
8int readMCP3008(byte channel) {
9 SPI.beginTransaction(mcpSettings);
10 digitalWrite(CS_PIN, LOW); // cihazı seç / select the chip
11 SPI.transfer(0x01); // başlangıç biti / start bit
12 byte high = SPI.transfer(0x80 | (channel << 4)); // tek uçlu + kanal / single-ended + channel
13 byte low = SPI.transfer(0x00); // kalan 8 bit / remaining 8 bits
14 digitalWrite(CS_PIN, HIGH); // seçimi bırak / release the chip
15 SPI.endTransaction();
16 return ((high & 0x03) << 8) | low; // 10 bitlik sonuç / 10-bit result
17}
18
19void setup() {
20 Serial.begin(9600);
21 pinMode(CS_PIN, OUTPUT);
22 digitalWrite(CS_PIN, HIGH); // başta seçili değil / not selected at start
23 SPI.begin();
24}
25
26void loop() {
27 int raw = readMCP3008(0);
28 float volts = raw * 5.0 / 1023.0;
29 Serial.print("CH0: ");
30 Serial.print(raw);
31 Serial.print(" ");
32 Serial.print(volts, 2);
33 Serial.println(" V");
34 delay(500);
35}Ici, nous envoyons trois octets et en recevons trois en même temps. Le premier octet (0x01) n'est que le bit de démarrage ; le deuxième transporte le mode d'entrée simple et le numéro de voie, pendant que le MCP3008 renvoie les 2 bits de poids fort du résultat. Le troisième octet vaut 0x00 ; son contenu n'a pas d'importance, il sert seulement à générer des impulsions d'horloge pour recevoir les 8 bits restants. En SPI, "lire" veut toujours dire envoyer quelque chose. Le résultat va de 0 à 1023 et se convertit en volts par rapport à VREF (ici 5 V).
Plusieurs périphériques SPI : des lignes CS séparées
La grande différence entre le SPI et l'I2C, c'est que le SPI n'utilise pas d'adresses. Les périphériques partagent les lignes SCK, MOSI et MISO, et chacun reçoit son propre fil CS depuis l'Arduino. Seul le périphérique dont le CS est à LOW écoute, et seul lui écrit sur MISO. Trois périphériques demandent 3 + 3 = 6 fils, cinq périphériques 3 + 5 = 8 ; le nombre de broches augmente avec le nombre de périphériques. Certains circuits comme le 74HC595 et le MAX7219 peuvent en revanche être chaînés (daisy chain) : la sortie de l'un entre dans le suivant et tous sont pilotés avec un seul CS.
- Un seul CS à LOW à la fois. Si deux périphériques sont sélectionnés ensemble, ils entrent en conflit sur MISO et tu lis des données corrompues des deux.
- Dans setup(), mets d'abord toutes les broches CS en sortie et à HIGH, puis démarre les bibliothèques. Une broche CS flottante peut paraître à LOW au hasard et monopoliser le bus.
- Utilise beginTransaction pour chaque périphérique. Une carte SD peut vouloir 25 MHz et un MCP3008 1 MHz ; les transactions appliquent automatiquement la bonne vitesse et le bon mode à chaque changement.
- Si tu utilises le SPI dans des interruptions, préviens la bibliothèque avec SPI.usingInterrupt(), ou ne fais aucune opération SPI dans l'interruption.
- Une pull-up de 10 kΩ sur la ligne CS de chaque périphérique évite qu'ils se sélectionnent tout seuls pendant le démarrage ou la réinitialisation de l'Arduino.
Carte SD et RFID sur le même bus : pourquoi ça ne marche pas ?
Une question classique des forums Arduino : le RFID RC522 fonctionne seul, le module carte SD fonctionne seul, mais sur le même bus SPI l'un des deux, voire les deux, se taisent. Même si les broches CS sont correctes dans le logiciel, le problème est le plus souvent matériel. Beaucoup de modules SD bon marché ont un tampon 74LVC125 qui convertit les signaux 5 V en 3,3 V, et le canal de ce circuit qui pilote la ligne MISO est toujours actif. Même avec le CS de la carte SD à HIGH, le module ne relâche donc pas MISO ; quand le RC522 essaie de répondre, deux sorties se battent pour la ligne.
- Choisis le bon module : les modules qui mettent MISO en haute impédance quand CS est à HIGH partagent le bus sans souci. Pour savoir si un module libère la ligne, tire MISO à travers 10 kΩ d'abord vers GND puis vers 5 V, CS à HIGH, et mesure au multimètre.
- Relie la broche de validation du tampon à CS : si tu sais souder, décoller de GND la broche OE du canal MISO du 74LVC125 et la relier à la ligne CS du module règle le problème définitivement.
- Ajoute une résistance série sur MISO : une résistance d'environ 1 kΩ en série sur la sortie MISO du module SD permet au RC522 d'imposer son signal. C'est un bricolage facile mais qui limite la vitesse.
- Utilise un bus SPI séparé : sur l'ESP32, si tu branches la carte SD sur VSPI et le RC522 sur HSPI, les deux périphériques ne se croisent jamais. L'Uno n'a pas de second SPI matériel, cette option n'existe donc pas.
- Respecte l'ordre de démarrage : mets d'abord tous les CS à HIGH, appelle ensuite SPI.begin(), puis SD.begin() et PCD_Init(). L'exemple ci-dessous suit cet ordre.
1// Aynı SPI hattında SD kart ve RC522 RFID / SD card and RC522 RFID on the same SPI bus
2// Ortak / shared: D11 MOSI, D12 MISO, D13 SCK. CS: SD -> D4, RC522 SDA(SS) -> D10, RC522 RST -> D9
3#include <SPI.h>
4#include <SD.h>
5#include <MFRC522.h>
6
7const int SD_CS = 4;
8const int RFID_CS = 10;
9const int RFID_RST = 9;
10
11MFRC522 rfid(RFID_CS, RFID_RST);
12
13void setup() {
14 Serial.begin(9600);
15 // Önce TÜM CS pinlerini HIGH yap: hiçbir cihaz hattı meşgul etmesin
16 // First drive ALL CS pins HIGH so no device grabs the bus
17 pinMode(SD_CS, OUTPUT);
18 digitalWrite(SD_CS, HIGH);
19 pinMode(RFID_CS, OUTPUT);
20 digitalWrite(RFID_CS, HIGH);
21
22 SPI.begin();
23 if (!SD.begin(SD_CS)) {
24 Serial.println(F("SD bulunamadi / SD not found"));
25 }
26 rfid.PCD_Init();
27 Serial.println(F("Karti okut / Scan a card"));
28}
29
30void loop() {
31 if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
32
33 String uid = "";
34 for (byte i = 0; i < rfid.uid.size; i++) {
35 if (rfid.uid.uidByte[i] < 0x10) uid += "0";
36 uid += String(rfid.uid.uidByte[i], HEX);
37 }
38 rfid.PICC_HaltA();
39
40 File f = SD.open("kartlar.txt", FILE_WRITE); // kütüphane CS'yi kendisi yönetir / the library handles CS itself
41 if (f) {
42 f.print(millis());
43 f.print(";");
44 f.println(uid);
45 f.close();
46 Serial.println("Kaydedildi / Saved: " + uid);
47 } else {
48 Serial.println(F("Dosya acilamadi / File open failed"));
49 }
50}Dans ce code, la bibliothèque SD et la bibliothèque MFRC522 mettent elles-mêmes leurs broches CS à LOW et à HIGH ; ton seul travail est de les laisser toutes les deux à HIGH au départ et de t'assurer que le matériel partage correctement MISO. Le code écrit l'UID de chaque carte lue, avec un horodatage, dans le fichier kartlar.txt. Sur l'Uno, ces deux bibliothèques utilisent ensemble environ la moitié de la RAM ; la macro F() libère de la place en gardant les textes constants en flash.
VSPI et HSPI sur l'ESP32 : deux bus SPI séparés
L'ESP32 contient quatre unités SPI ; SPI0 et SPI1 sont réservées à la flash interne, il te reste donc VSPI (SPI3) et HSPI (SPI2). Utiliser les deux est la façon la plus propre de séparer des périphériques aux vitesses et modes très différents, ou d'échapper au conflit sur MISO vu plus haut. Dans le core Arduino, tu crées un objet SPIClass pour le second bus et tu lui donnes ses broches avec begin(). Le code ci-dessous fait tourner la carte SD sur le VSPI par défaut et le MCP3008 sur HSPI, et ajoute une mesure à un fichier CSV chaque seconde :
1// ESP32: iki ayrı SPI hattı / two separate SPI buses
2// VSPI (varsayılan SPI / default SPI): SD kart / SD card -> SCK 18, MISO 19, MOSI 23, CS 5
3// HSPI: MCP3008 -> SCK 14, MISO 12, MOSI 13, CS 15
4#include <SPI.h>
5#include <SD.h>
6
7const int SD_CS = 5;
8const int ADC_CS = 15;
9
10SPIClass hspi(HSPI); // ikinci donanım SPI / second hardware SPI
11SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);
12
13int readMCP3008(byte channel) {
14 hspi.beginTransaction(mcpSettings);
15 digitalWrite(ADC_CS, LOW);
16 hspi.transfer(0x01);
17 byte high = hspi.transfer(0x80 | (channel << 4));
18 byte low = hspi.transfer(0x00);
19 digitalWrite(ADC_CS, HIGH);
20 hspi.endTransaction();
21 return ((high & 0x03) << 8) | low;
22}
23
24void setup() {
25 Serial.begin(115200);
26 pinMode(ADC_CS, OUTPUT);
27 digitalWrite(ADC_CS, HIGH);
28 hspi.begin(14, 12, 13, ADC_CS); // SCK, MISO, MOSI, SS
29
30 if (!SD.begin(SD_CS)) { // SD varsayılan VSPI'yi kullanır / SD uses the default VSPI
31 Serial.println("SD bulunamadi / SD not found");
32 }
33}
34
35void loop() {
36 int raw = readMCP3008(0);
37 File f = SD.open("/olcum.csv", FILE_APPEND); // ekle kipinde aç / open in append mode
38 if (f) {
39 f.printf("%lu,%d\n", millis(), raw);
40 f.close();
41 }
42 Serial.printf("CH0: %d\n", raw);
43 delay(1000);
44}Le SPI avec le Raspberry Pi Pico (MicroPython)
Le Pico possède deux unités SPI matérielles (SPI0 et SPI1), utilisées en MicroPython avec la classe machine.SPI. Les paramètres polarity et phase correspondent à CPOL et CPHA ; s'ils valent tous deux 0, c'est le mode 0. Tu gères toi-même le CS comme une broche de sortie ordinaire. La fonction write_readinto() illustre le mieux le caractère full duplex du SPI : pendant qu'elle envoie un tableau, elle écrit les octets reçus dans un autre. Lisons le même MCP3008, alimenté cette fois en 3,3 V :
1# Raspberry Pi Pico: SPI0 ile MCP3008 okuma / reading an MCP3008 on SPI0
2# GP18 -> CLK, GP19 -> DIN (MOSI), GP16 <- DOUT (MISO), GP17 -> CS. MCP3008 VDD ve VREF 3V3 / VDD and VREF on 3V3
3from machine import Pin, SPI
4import time
5
6spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0, # mod 0 / mode 0
7 sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8cs = Pin(17, Pin.OUT, value=1) # başta seçili değil / not selected at start
9
10def read_mcp3008(channel):
11 tx = bytearray([0x01, 0x80 | (channel << 4), 0x00])
12 rx = bytearray(3)
13 cs.value(0) # cihazı seç / select the chip
14 spi.write_readinto(tx, rx) # aynı anda gönder ve al / send and receive at once
15 cs.value(1)
16 return ((rx[1] & 0x03) << 8) | rx[2]
17
18while True:
19 raw = read_mcp3008(0)
20 print("CH0:", raw, "{:.2f} V".format(raw * 3.3 / 1023))
21 time.sleep(0.5)SPI, I2C et UART : comparaison
| Caractéristique | SPI | I2C | UART |
|---|---|---|---|
| Nombre de fils | 4 (+1 CS par périphérique supplémentaire) | 2 (SDA, SCL) | 2 (TX, RX) |
| Vitesse typique | 1–80 MHz | 100 kHz, 400 kHz, 1 MHz | 9600–115200 bauds (jusqu'à quelques Mbit/s) |
| Horloge | Oui (générée par le contrôleur) | Oui (générée par le contrôleur) | Non ; les deux côtés s'accordent sur la même vitesse en bauds |
| Sens | Full duplex | Half duplex | Full duplex |
| Sélection du périphérique | Fil CS dédié | Adresse sur 7 bits | Deux appareils seulement (point à point) |
| Composants supplémentaires | Aucun | Résistances de pull-up | Aucun |
| Distance | Courte (sur la carte, quelques dizaines de cm) | Courte (environ 1 m) | Quelques mètres ; bien plus avec le RS-485 |
| Modules typiques | Carte SD, RC522, TFT, nRF24L01, MAX7219 | OLED, adaptateur I2C pour LCD, RTC, BME280, MPU6050 | GPS, HC-05, SIM800L, ESP-01, ordinateur |
Le choix est souvent imposé par le module, mais pour tes propres montages cette règle aide : si la vitesse et le volume de données comptent (images d'écran, fichiers, son), prends le SPI ; s'il te faut peu de fils et beaucoup de capteurs lents, prends l'I2C ; pour une liaison simple, en texte, entre deux appareils, prends l'UART. Tu trouveras l'UART en détail dans l'article La communication série UART. Il est aussi très courant d'utiliser les trois dans un même projet : par exemple un enregistreur qui lit des capteurs en I2C, écrit sur une carte SD en SPI et reçoit sa position d'un GPS en UART.
Modules SPI et idées de projets
- Serrure à badge avec journal des accès : lis le badge avec un RC522 et écris la date et l'UID sur une carte SD.
- Enregistreur de température : enregistre les mesures des capteurs sur une microSD au format CSV et trace une courbe dans Excel.
- Panneau à texte défilant : affiche l'heure et des messages sur des modules matrice LED MAX7219 chaînés.
- Interface couleur : dessine graphiques et menus sur un écran TFT ILI9341 ; branche aussi la dalle tactile sur le même bus SPI.
- Télécommande sans fil : envoie des ordres à ta voiture robot avec deux modules nRF24L01.
- Mesure multivoie : construis avec un MCP3008 un contrôleur MIDI à 8 potentiomètres ou un arrosage avec 8 capteurs d'humidité du sol.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| On lit toujours 0xFF ou 0x00 | MISO non relié, MOSI et MISO inversés ou périphérique non alimenté | Relie DIN à MOSI et DOUT à MISO ; mesure le VCC du périphérique |
| Valeurs absurdes ou décalées d'un bit | Mauvais mode SPI ou horloge trop rapide pour le périphérique | Utilise le mode de la fiche technique, baisse la vitesse à 1 MHz et réessaie |
| Deux périphériques qui marchent seuls ne marchent pas ensemble | Un module ne libère pas MISO ou les CS ne sont pas à HIGH au départ | Mets d'abord tous les CS à HIGH ; remplace le module qui ne libère pas MISO ou utilise un bus SPI séparé |
| Le SPI s'arrête soudain sur l'Uno | D10 a été utilisée en entrée et tirée à LOW | Laisse D10 en sortie ; tu peux t'en servir comme CS |
| L'ESP32 ne démarre pas avec le HSPI branché | GPIO 12 reste à HIGH au démarrage | Déplace le MISO avec pull-up vers VSPI ou choisis une autre broche pour MISO |
| Erreurs aléatoires sur fils longs | Réflexions et parasites sur un signal rapide | Raccourcis les fils, baisse la vitesse, fais courir un fil GND le long des signaux |
Le SPI est la langue commune des modules rapides du monde Arduino, des cartes SD aux écrans couleur : une fois que tu connais les quatre fils, la logique du CS et les quatre modes, brancher un nouveau module SPI ne prend que quelques minutes. Dans l'application BlueGrays, tu trouveras les projets de lecture de badges RFID et de serrure, d'enregistreur de température sur microSD et d'horloge à matrice de points MAX7219, pas à pas avec schémas de câblage et code.
Questions fréquentes
Que signifie SPI ?
SPI est l'abréviation de Serial Peripheral Interface (interface série pour périphériques). Il permet à un contrôleur d'échanger des données rapidement et de façon synchrone avec des périphériques sur quatre lignes : SCK, MOSI, MISO et CS.
Que sont MOSI et MISO ?
MOSI (Master Out Slave In) est la ligne de données du contrôleur vers le périphérique ; MISO (Master In Slave Out) est la ligne de données du périphérique vers le contrôleur. Dans la nouvelle terminologie, on les appelle aussi COPI et CIPO. Sur les modules, DIN va généralement sur MOSI et DOUT sur MISO.
Quelles sont les broches SPI de l'Arduino Uno ?
Sur l'Arduino Uno et le Nano, SCK est D13, MISO D12, MOSI D11 et le CS par défaut D10. Les mêmes lignes se trouvent aussi sur le connecteur ICSP à 6 broches de la carte. Sur l'Arduino Mega, ce sont SCK D52, MISO D50, MOSI D51 et CS D53.
Quelle est la différence entre SPI et I2C ?
Le SPI utilise quatre fils, fonctionne en full duplex et peut tourner à des dizaines de MHz ; chaque périphérique a besoin de son propre fil CS. L'I2C n'utilise que deux fils et sélectionne les périphériques par adresse, mais il fonctionne à des vitesses bien plus faibles, comme 100–400 kHz, et demande des résistances de pull-up.
Combien de périphériques peut-on brancher sur un bus SPI ?
Il n'y a pas de limite théorique ; il suffit d'avoir une broche CS libre sur le contrôleur pour chaque périphérique. En pratique, des problèmes apparaissent à haute vitesse quand la capacité du bus et la longueur des fils augmentent. Si les broches manquent, tu peux multiplier les lignes CS avec un décodeur 74HC138 ou utiliser des circuits chaînables.
Pourquoi une carte SD et un RFID ne fonctionnent-ils pas sur le même bus SPI ?
Le convertisseur de niveau de nombreux modules SD bon marché ne relâche pas la ligne MISO même quand CS est à HIGH, ce qui fausse la réponse du RC522. Il suffit d'utiliser un module qui libère correctement MISO, de relier la broche de validation du tampon à CS ou, sur l'ESP32, de placer les deux périphériques sur des bus SPI séparés.
Projets à réaliser après cet article
Voir tous les projets
Lecture des valeurs RFID
Le badge de ton immeuble ou ta carte d'accès cache un numéro d'identité secret, et ce projet le lit. Approche la carte du lecteur RFID, et l'Arduino écrit son numéro sur l'écran de ton ordinateur. La

Authentification par RFID
Comme le badge d'entrée d'un immeuble : tu approches ta carte du lecteur RFID, et l'Arduino compare son numéro avec celui qu'il a en mémoire. Avec la bonne carte, la LED verte s'allume trois secondes,

Lecteur de cartes RFID RC522 pour ESP32 (avec LCD)
Dans ce projet, nous allons connecter le module RFID RC522 basé sur le MFRC522 à l'ESP32 via SPI afin de lire l'UID d'une carte ou d'un badge. Cela constitue la base d'applications telles que les serrures de porte, les systèmes d'adhésion et le contrôle d'accès. Nous afficherons l'UID lu sur un écran LCD ; cette version ne le compare pas à une liste de cartes autorisées. ATTENTION : le RC522 fonctionne uniquement en 3,3 V ; 5 V grillerait le module !

Serrure de porte RFID ESP32 (RC522 + servomoteur + écran OLED + buzzer + LED)
Nous réalisons une serrure intelligente à l'aide d'un ESP32, d'un module RFID RC522, d'un servomoteur SG90, d'un écran OLED SSD1306, d'un buzzer actif et de 2 LED. Lorsqu’une carte est lue, son code UID est comparé à la liste des cartes autorisées définie dans le code — si elle est autorisée, le servomoteur tourne pour déverrouiller la serrure (LED verte + 2 bips courts), puis celle-ci se verrouille automatiquement au bout de 5 secondes. En cas de carte non autorisée, la LED rouge s'allume, un a

Enregistreur de Température ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Construis un enregistreur de température horodaté avec ESP32 ! Lis la température/humidité du DHT22 chaque minute, obtiens l'heure réelle du DS1307 RTC et enregistre sur carte microSD au format CSV. L'OLED affiche en direct la température (grande police), le pourcentage d'humidité, l'horodatage et le compteur. Le fichier /temp_log.csv sur la carte SD s'ouvre dans Excel, Google Sheets ou Python pandas pour analyse — parfait pour surveillance de serre, suivi de température à domicile, c

Horloge et calendrier matriciel (MAX7219, DS1307)
Un panneau lumineux pour ton bureau ou ton mur, qui affiche l'heure et la date en texte défilant. Sur l'écran LED 8x32, une horloge à gros chiffres fait clignoter ses deux points chaque seconde ; au d

Animation matricielle 4x 32x8 LED et texte
Empile quatre longs modules à matrice de LED et tu obtiens un écran carré de plus de mille points lumineux. D'abord, des lettres tombent du haut comme une pluie de film, puis un rideau s'ouvre et deux

Serpent à pixels Matrice 8x8
Construis de tes mains le jeu classique du serpent et joue. Sur une matrice lumineuse colorée de 8x8, tu guides un serpent vert avec un joystick et tu manges des pommes rouges ; à chaque pomme, le ser
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 200 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

