Croisement obligatoire
TX d’un appareil se connecte au RX de l’autre, et inversement. Un câblage TX→TX ne fonctionne pas.
Les bus de communication
Découvrir les trois bus série les plus courants en électronique embarquée et savoir lequel choisir selon le cas d'usage.
Pré-requis :
Un microcontrôleur est rarement seul : il pilote un écran, interroge un capteur de température, échange avec un module Bluetooth. Encore faut-il que tous ces composants se comprennent, qu’ils parlent la même langue.
Ces langages communs, ce sont les bus de communication. Comme des humains, les composants ont plusieurs façons de discuter : à deux dans un couloir (UART), en petit groupe où chacun répond à son nom (I2C), ou par une ligne dédiée très rapide (SPI). Ce concept présente ces trois « dialectes » et t’aide à choisir le bon.
À la fin de ce concept, tu sauras :
Relier chaque périphérique au CPU par un fil par bit serait impraticable : l’écran de l’atelier (240 × 320 pixels) reçoit plus de 150 000 octets par image. Les bus de communication série transmettent les données sur un petit nombre de fils, en envoyant les bits l’un après l’autre. Une liaison parallèle, à l’inverse, envoie plusieurs bits en même temps, un par fil : plus rapide à fréquence égale, mais bien plus encombrante.
| Question | Les deux réponses possibles |
|---|---|
| Combien d’interlocuteurs ? | Point à point (deux appareils) ou multipoint (plusieurs sur les mêmes fils) |
| Une horloge partagée ? | Synchrone (un fil d’horloge cadence les bits) ou asynchrone (chacun compte de son côté, à une vitesse convenue) |
| Les deux sens en même temps ? | Full-duplex (oui, sur deux fils de données) ou half-duplex (chacun son tour, sur le même fil) |
| Comment choisir le destinataire ? | Une adresse écrite dans le message (logiciel) ou un fil de sélection par composant (matériel) |
Pour le sens de circulation, pense au téléphone et au talkie-walkie : au téléphone, les deux interlocuteurs peuvent parler en même temps (full-duplex) ; au talkie-walkie, il faut attendre son tour (half-duplex).
Ces quatre réponses suffisent à décrire les trois bus de cette page, et la plupart des autres : RS-232 et SATA sont point à point, RS-485, Ethernet et USB multipoints, CAN asynchrone comme l’UART…
UART est le bus le plus simple : deux fils, point à point (une liaison directe entre deux appareils seulement), sans horloge partagée.
| Fil | Rôle |
|---|---|
| TX | Transmission (sortie du µC) |
| RX | Réception (entrée du µC) |
La vitesse est fixée à l’avance des deux côtés : c’est le baud rate. Ici, un signal à deux niveaux transporte un bit par symbole, donc 1 baud vaut 1 bit/s (ce n’est pas vrai de toutes les liaisons). Les vitesses usuelles sont normalisées : 1 200, 2 400, 4 800, 9 600 et 115 200 bauds, la plus courante sur un microcontrôleur moderne. Les deux appareils partagent aussi leur masse (GND) : sans référence commune, un niveau de tension ne veut rien dire.
Sans horloge partagée, comment le récepteur sait-il quand lire ? Par convention : la ligne est au repos à HIGH, et chaque octet est encadré de bits de synchronisation.
LOW) annonce le début ;HIGH).C’est ce que résume la notation 8N1 : 8 bits de données, No parité, 1 bit de stop. Les deux extrémités doivent partager exactement le même format et la même vitesse, sinon les octets sont mal découpés. Huit bits suffisent pour un caractère ASCII (codes 0 à 127) ou n’importe quel octet (0 à 255).
D’autres formats existent, que l’on rencontre sur des appareils plus anciens ou industriels :
N), paire (E, even) ou impaire (O, odd) : un bit ajouté pour que le nombre total de 1 soit pair (ou impair), ce qui permet de détecter une erreur sur un bit ;7E1 désigne ainsi 7 bits de données, une parité paire et 1 bit de stop.
Entre deux cartes, les niveaux sont ceux des broches : 0 V pour un 0, 3,3 V (ou 5 V sur une carte Arduino Uno) pour un 1, avec la ligne à 1 au repos. Une telle liaison ne porte qu’à un mètre environ : au-delà, les fils captent des parasites et déforment les fronts.
Pour aller plus loin, on intercale un convertisseur de niveaux (une puce MAX3232, par exemple) qui transforme la liaison en RS-232, l’ancien port série des ordinateurs : des tensions plus élevées, positives et négatives, bien plus robustes. La règle est toujours la même : plus la vitesse est basse, plus on peut aller loin. À titre indicatif, on compte une quinzaine de mètres à 9 600 bauds, une soixantaine à 2 400 bauds, mais seulement deux à trois mètres au-delà de 38 400 bauds ; ces valeurs dépendent beaucoup des câbles.
Serial.begin(115200); // ouvre le port série du moniteur
Serial.println("Hello !"); // envoie une ligne
int v = analogRead(A0);
Serial.println(v); // affiche la valeur dans le moniteur série
I2C relie plusieurs périphériques sur seulement 2 fils grâce à un système d’adressage.
| Fil | Rôle |
|---|---|
| SDA | Données (bidirectionnel) |
| SCL | Horloge (générée par le maître) |
Chaque composant I2C possède une adresse 7 bits unique (ex : 0x3C pour un écran OLED SSD1306). Le maître (l’appareil qui dirige les échanges, ici l’ESP32-S3) initie toujours la communication ; les autres, les esclaves, ne répondent que lorsqu’il les sollicite, et ne se parlent jamais entre eux. C’est aussi le maître qui fixe la vitesse, puisqu’il génère l’horloge.
C’est un bus multipoint, synchrone (le maître génère l’horloge sur SCL) et half-duplex (SDA sert dans les deux sens, chacun son tour).
Un échange I2C suit toujours le même rituel, orchestré par le maître :
C’est ce système d’accusé de réception qui permet au scanner d’adresses (plus bas) de savoir « qui est là ».
En pratique, les bibliothèques de capteurs font tout cela pour toi ; savoir lire ce déroulement sert surtout à déboguer, à l’analyseur logique ou à l’oscilloscope.
Une adresse sur 7 bits offre 128 valeurs, dont 16 sont réservées par la norme (de 0x00 à 0x07 et de 0x78 à 0x7F) : il en reste 112 pour les composants. L’adresse est fixée par le fabricant ; certains composants permettent d’en choisir une parmi deux ou quatre, par une broche à relier à GND ou au 3,3 V (le capteur BME280 répond en 0x76 ou en 0x77).
Deux composants à la même adresse sur le même bus se répondent l’un par-dessus l’autre : il faut changer l’adresse de l’un d’eux, ou les placer sur deux bus I2C différents (l’ESP32-S3 en a deux). Une variante à 10 bits d’adresse existe, mais elle reste rare.
| Mode | Vitesse |
|---|---|
| Standard | 100 kHz |
| Fast | 400 kHz |
| Fast+ | 1 MHz |
| High Speed | 3,4 MHz |
Plus le bus est rapide, plus il doit être court : comptez un à deux mètres au plus, souvent moins à 400 kHz et au-delà.
#include <Wire.h>
Wire.begin(SDA_PIN, SCL_PIN); // démarre I2C
// Les bibliothèques de capteurs utilisent Wire en arrière-plan
Les lignes SDA et SCL sont en open-drain (voir GPIO & monde numérique) : les composants ne peuvent que tirer la ligne vers LOW ou la relâcher. Il faut donc deux résistances de pull-up (typiquement 4,7 kΩ) reliant SDA et SCL au 3,3 V : sans elles, le bus reste bloqué et rien ne communique. Leur valeur s’ajuste à la longueur du bus et à sa vitesse : plus elle est faible, plus les fronts remontent vite, mais plus chaque composant doit absorber de courant pour tirer la ligne à 0.
C’est aussi ce qui rend le bus sûr : chacun peut tirer la ligne à 0 ou la relâcher, mais personne n’impose un 1. Deux composants ne peuvent donc jamais se contredire et créer un court-circuit.
On ne connaît pas toujours l’adresse d’un composant. Un petit programme balaie toutes les adresses possibles et affiche celles qui répondent :
#include <Wire.h>
void setup() {
Wire.begin(SDA_PIN, SCL_PIN);
Serial.begin(115200);
for (byte adr = 1; adr < 127; adr++) {
Wire.beginTransmission(adr);
if (Wire.endTransmission() == 0) { // 0 = un composant a répondu
Serial.printf("Trouvé à 0x%02X\n", adr);
}
}
}
void loop() {}
C’est le premier réflexe de débogage quand un capteur I2C « ne répond pas ».
SPI est le bus le plus rapide des trois. Il utilise 4 fils et une logique maître/esclave.
| Fil | Rôle |
|---|---|
| MOSI | Master Out Slave In (données vers le périphérique) |
| MISO | Master In Slave Out (données depuis le périphérique) |
| SCK | Horloge (générée par le maître) |
| CS | Chip Select : sélectionne l’esclave actif (1 fil par esclave) |
La transmission est synchrone (l’horloge SCK cadence chaque bit) et full-duplex (MOSI et MISO actifs simultanément).
SCK, MOSI et MISO sont partagés ; chaque esclave a son propre fil CS. Pas d’adresse : le maître met à 0 le CS de l’esclave qu’il veut, et les autres laissent leur MISO en haute impédance. Selon les composants, les broches portent d’autres noms : SCLK ou SCL pour SCK ; SS, nCS, nSS, CSN ou STE pour CS ; SDI, DI ou SI pour l’entrée de données (côté esclave, MOSI) ; SDO, DO ou SO pour sa sortie (MISO). MOSI et MISO ne vont chacun que dans un sens, contrairement au SDA de l’I2C.
Ni adresse, ni accusé de réception : rien ne garantit que l’esclave a bien reçu. C’est le prix de la vitesse. Quand le maître ne fait qu’écrire (comme vers l’écran de l’atelier), MISO n’est même pas câblé.
Certains composants (des registres à décalage, des pilotes de LED) se câblent en chaîne (daisy chain) : un seul CS pour tous, et la sortie de données de chaque esclave reliée à l’entrée du suivant.
Les octets traversent les esclaves l’un après l’autre : pour en commander trois, le maître envoie trois octets d’affilée, puis remonte le CS. Ce montage économise des broches, mais tous les esclaves doivent le prévoir dans leur fiche technique.
De quelques MHz à 80 MHz sur ESP32-S3, bien plus rapide que I2C. En contrepartie, le SPI ne porte que sur de courtes distances, quelques dizaines de centimètres ; des circuits d’amplification de ligne (buffers) permettent d’aller un peu plus loin.
#include <SPI.h>
SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS_PIN);
Le maître et l’esclave doivent aussi s’accorder sur la forme de l’horloge : son niveau au repos (CPOL, bas ou haut) et le front sur lequel chaque bit est lu (CPHA, premier ou second front). Les quatre combinaisons forment les modes SPI :
| Mode | Horloge au repos (CPOL) | Bit lu sur le front (CPHA) |
|---|---|---|
| 0 | Bas | Premier (montant) |
| 1 | Bas | Second (descendant) |
| 2 | Haut | Premier (descendant) |
| 3 | Haut | Second (montant) |
Le mode est imposé par le périphérique (sa datasheet l’indique) et le maître s’y adapte ; le mode 0 est le plus courant. Un mauvais mode ne produit aucune erreur : l’esclave lit simplement des bits décalés, et l’écran reste noir.
Pour l’écran de l’atelier, cet appel suffit à router le bus sur les broches du PCB : SPI.begin(D9, -1, D10, -1) (pas de MISO, CS relié à GND). La bibliothèque Adafruit ST7789 se charge ensuite de toutes les trames : tu ne manipules jamais les octets toi-même.
Un microcontrôleur gère ses bus avec des périphériques matériels dédiés, dont la liste figure dans sa datasheet : tous n’ont pas les mêmes (certains ajoutent CAN ou USB, d’autres n’ont qu’un UART). Par exemple, l’ESP32-S3 a trois UART, deux I2C et deux SPI disponibles pour l’utilisateur, que la GPIO matrix route vers presque n’importe quelle broche. Le processeur prépare les octets, le périphérique s’occupe du chronométrage bit par bit.
Quand le périphérique manque (une petite puce, un bus exotique), on peut émuler le bus en pilotant les broches par logiciel, bit après bit : c’est le bit-banging. Ça marche pour des vitesses modestes, mais le processeur est occupé pendant tout l’échange, et une interruption au mauvais moment déforme le chronométrage. Quand un périphérique matériel existe, on l’utilise.
UART, I2C et SPI couvrent l’essentiel des besoins sur une carte, et l’I2C et le SPI sont les deux à connaître en priorité. D’autres bus se rencontrent dès qu’on sort de la carte :
| Bus | Fils | Principe | Où on le trouve |
|---|---|---|---|
| CAN | 2 (paire différentielle) | Multipoint (une vingtaine à une trentaine de nœuds), asynchrone, robuste aux parasites : de l’ordre de 30 m à 1 Mbit/s, jusqu’à plusieurs kilomètres à 10 kbit/s | Automobile, machines industrielles |
| 1-Wire | 1 de données + la masse (parfois l’alimentation) | Multipoint, half-duplex, une résistance de tirage, environ 16 kbit/s ; chaque composant a un numéro unique gravé en usine | Capteur de température DS18B20 |
| USB | 2 de données + alimentation | Point à point vers un hôte, rapide, avec détection automatique des appareils | Programmation de la XIAO, claviers, clés |
L’ESP32-S3 intègre un contrôleur compatible CAN (appelé TWAI chez Espressif) : il suffit de lui ajouter une puce d’interface (transceiver, comme le TJA1050) pour rejoindre un réseau CAN. Sur une carte qui n’a pas de contrôleur CAN, un module à MCP2515 en fournit un, piloté en SPI. On croise aussi, hors des cartes électroniques, SATA (disques), RS-485 (réseaux industriels) ou Ethernet.
| Critère | UART | I2C | SPI |
|---|---|---|---|
| Fils (hors masse) | 2 (TX, RX) | 2 (SDA, SCL) | 3 (SCK, MOSI, MISO) + 1 CS par esclave |
| Liaison | Point à point | Multipoint | Multipoint |
| Horloge | Asynchrone | Synchrone | Synchrone |
| Sens | Full-duplex | Half-duplex | Full-duplex |
| Choix du destinataire | Aucun (un seul) | Adresse 7 bits | Fil CS |
| Accusé de réception | Non | Oui (ACK) | Non |
| Vitesse | ~1 Mbit/s | 100 kbit/s à 3,4 Mbit/s | Jusqu’à 80 Mbit/s sur ESP32-S3 |
| Distance | Environ 1 m | 1 à 2 m | Quelques dizaines de cm |
| Usage type | Debug, modules | Capteurs, OLED | Écrans, carte SD |
Ces valeurs sont indicatives : la distance utile dépend de la vitesse, de la qualité des fils et des composants.
flowchart TD
A["Quel périphérique ?"] --> B{"Besoin de vitesse élevée ?"}
B -->|Oui| C["SPI\n(écran, SD)"]
B -->|Non| D{"Plusieurs composants\nsur peu de fils ?"}
D -->|Oui| E["I2C\n(capteurs, OLED)"]
D -->|Non| F["UART\n(debug, GPS, BT)"]
1. Combien de fils pour l’UART, l’I2C et le SPI ?
2. Pourquoi faut-il des pull-ups sur un bus I2C ?
3. Deux capteurs identiques répondent tous les deux à l’adresse I2C 0x76. Que faire ?
4. Quel bus choisir pour un écran TFT rapide ?
8N1) ; un échange I2C = start → adresse+R/W → ACK → données → stop.