Modbus a été publié par Modicon en 1979. Presque cinquante ans plus tard, il tourne encore sur des variateurs, des centrales de mesure, des onduleurs PV, des relais de protection et des automates de toutes marques. Pas parce qu’il est bon. Parce qu’il est minuscule, documenté, et que tout le monde l’implémente.
Ce guide couvre ce que vous devez réellement savoir pour mettre en service une liaison Modbus : le modèle de données, les trames, les codes fonction, et surtout les zones grises de la spécification qui font perdre des journées entières sur site.
Sommaire
Ce que Modbus fait, et ce qu’il ne fait pas
Modbus transporte des nombres 16 bits et des bits. C’est tout.
Il ne dit pas ce que ces nombres signifient. Il ne dit pas dans quelle unité ils sont. Il ne dit pas s’il faut lire deux registres consécutifs comme un entier 32 bits ou comme un flottant. Il n’a pas d’horodatage, pas de notion d’événement, pas d’authentification.
Cette pauvreté est la raison de sa survie. Une pile Modbus tient dans quelques kilo-octets. Un microcontrôleur à 2 € peut en héberger une. Mais elle explique aussi pourquoi 90 % des problèmes Modbus ne sont pas des problèmes de protocole : ce sont des problèmes d’interprétation ou de couche physique.
Retenez ce principe : la documentation constructeur fait partie du protocole. Sans elle, une trame Modbus valide reste illisible.
Le modèle client/serveur
La spécification actuelle parle de client et de serveur. Le vocabulaire historique — maître et esclave — reste très présent dans les manuels constructeurs et dans les logiciels de configuration. Les deux désignent la même chose :
| Terme actuel | Terme historique | Rôle |
|---|---|---|
| Client | Maître | Émet les requêtes |
| Serveur | Esclave | Répond, ne prend jamais l’initiative |
Un serveur Modbus ne parle jamais spontanément. Il n’existe pas de rapport par exception, pas de message non sollicité. Si vous voulez savoir qu’un disjoncteur a changé d’état, vous devez interroger le registre correspondant assez souvent pour le voir.
Cette conséquence est directe et souvent sous-estimée : le cycle d’interrogation détermine votre résolution temporelle. Sur un bus RS-485 avec 20 esclaves à 9600 bauds, un cycle complet prend facilement une à deux secondes. Tout événement plus rapide que ça est invisible.
Sur liaison série, un seul client. Sur Ethernet, plusieurs clients peuvent interroger le même serveur en parallèle, dans la limite de ses connexions TCP.
Les quatre espaces de données
Modbus range tout dans quatre tables. Deux en bits, deux en mots de 16 bits. Deux en lecture seule, deux en lecture/écriture.
| Table | Taille | Accès | Usage typique |
|---|---|---|---|
| Discrete inputs (entrées tout ou rien) | 1 bit | Lecture seule | Fin de course, contact auxiliaire |
| Coils (bits de sortie) | 1 bit | Lecture / écriture | Commande de relais, bit de consigne |
| Input registers (registres en lecture seule) | 16 bits | Lecture seule | Mesure analogique |
| Holding registers (registres lecture/écriture) | 16 bits | Lecture / écriture | Paramètre, consigne, compteur |
Les noms anglais sont conservés dans tout le site : c’est ce que vous lirez dans les manuels constructeurs et dans les logiciels de configuration, quelle que soit la langue de l’interface.
En pratique, beaucoup de constructeurs ignorent cette séparation et mettent tout dans les holding registers. C’est légal. Ne partez jamais du principe qu’une mesure est forcément dans un input register.
Le piège de l’adressage
Voici la source d’erreur numéro un en mise en service.
Dans la trame, les adresses sont codées sur 16 bits et commencent à 0. La plage utile est donc 0 à 65535.
Dans la documentation constructeur, les adresses sont très souvent écrites à partir de 1, avec un préfixe qui indique la table :
| Notation documentation | Table | Adresse réelle dans la trame |
|---|---|---|
| 0xxxx (00001 →) | Coils | Valeur − 1 |
| 1xxxx (10001 →) | Discrete inputs | Valeur − 10001 |
| 3xxxx (30001 →) | Input registers | Valeur − 30001 |
| 4xxxx (40001 →) | Holding registers | Valeur − 40001 |
Le registre documenté 40001 se lit donc à l’adresse 0 avec le code fonction 03. Le registre 40100 se lit à l’adresse 99.
Certains outils de configuration appliquent la conversion pour vous, d’autres non. Quand une lecture renvoie une valeur cohérente mais décalée d’un cran, c’est presque toujours ça.
La PDU : la partie qui ne change jamais
Modbus sépare proprement le message applicatif de son transport.
La PDU (Protocol Data Unit) contient le code fonction et les données. Elle est identique en RTU, en ASCII et en TCP. Sa taille maximale est de 253 octets.

Autour, chaque mode ajoute son enveloppe pour former l’ADU (Application Data Unit) :
| Mode | En-tête | Charge utile | Fin de trame | Taille max |
|---|---|---|---|---|
| RTU | Adresse, 1 octet | PDU ≤ 253 octets | CRC, 2 octets | 256 octets |
| ASCII | : puis adresse | PDU en hexadécimal texte | LRC puis CR LF | 513 caractères |
| TCP | MBAP, 7 octets | PDU ≤ 253 octets | — | 260 octets |
Cette limite de 253 octets est la raison pour laquelle vous ne pouvez pas lire plus de 125 registres en une requête. 125 × 2 octets = 250, plus le code fonction et le compteur d’octets. On y est.
Les trois modes de transmission
Modbus RTU
Codage binaire, un octet de données par octet transmis. C’est le mode dominant sur RS-485 et RS-232.
Le délimiteur de trame n’est pas un caractère : c’est un silence. Une trame commence après un silence d’au moins 3,5 temps de caractère, et se termine par le même silence. À l’intérieur d’une trame, un trou de plus de 1,5 temps de caractère invalide le message.
Au-delà de 19200 bauds, la spécification recommande des valeurs fixes plutôt que le calcul : 750 µs pour l’intervalle intra-trame, 1,75 ms pour le silence inter-trames.
Ce silence explique pourquoi Modbus RTU tolère mal les convertisseurs série/Ethernet bas de gamme et les ponts USB : ils bufferisent, cassent la temporisation, et le récepteur ne reconnaît plus les limites de trame.
Le format de caractère standard est 11 bits : 1 start, 8 données, 1 parité, 1 stop. Sans parité, on garde 11 bits en utilisant deux bits de stop. Un esclave configuré en 8N1 alors que le maître est en 8E1 communique de façon erratique — parfois ça passe, souvent non.
Contrôle d’erreur : CRC-16, polynôme 0xA001, transmis octet de poids faible en premier. C’est le seul champ de la trame où l’ordre est inversé.
Modbus ASCII
Chaque octet est transmis sous forme de deux caractères hexadécimaux lisibles. La trame commence par : et se termine par CR LF. Contrôle d’erreur par LRC, plus faible que le CRC.
Deux fois plus lent, deux fois plus de bande passante. Son seul avantage : les intervalles entre caractères peuvent aller jusqu’à une seconde, ce qui permet de passer par des liaisons lentes ou des modems capricieux. Vous le rencontrerez surtout sur du matériel ancien.
Modbus TCP
L’enveloppe série disparaît, remplacée par un en-tête MBAP de 7 octets :
| Champ | Taille | Rôle |
|---|---|---|
| Identifiant de transaction | 2 octets | Apparie requête et réponse |
| Identifiant de protocole | 2 octets | Toujours 0 pour Modbus |
| Longueur | 2 octets | Nombre d’octets qui suivent |
| Identifiant d’unité | 1 octet | Adresse esclave derrière une passerelle |
Plus de CRC : TCP s’en charge. Port par défaut 502.
L’identifiant de transaction permet au client d’avoir plusieurs requêtes en vol simultanément — impossible en RTU. L’identifiant d’unité n’a de sens que derrière une passerelle TCP/RTU ; en direct vers un équipement Ethernet, il vaut généralement 255 ou 1, et certains équipements l’ignorent complètement.
Comparaison rapide
| RTU | ASCII | TCP | |
|---|---|---|---|
| Support | RS-485 / RS-232 | RS-485 / RS-232 | Ethernet |
| Codage | Binaire | Hexadécimal texte | Binaire |
| Délimiteur | Silence 3,5 caractères | : et CR LF | Longueur MBAP |
| Contrôle d’erreur | CRC-16 | LRC | Aucun (TCP) |
| Requêtes simultanées | Non | Non | Oui |
| Clients multiples | Non | Non | Oui |
Les codes fonction
La spécification en définit une vingtaine. Six couvrent la quasi-totalité des besoins.
Les six essentiels
| Code | Nom | Action | Limite |
|---|---|---|---|
| 01 (0x01) | Read Coils | Lire n coils | 2000 bits |
| 02 (0x02) | Read Discrete Inputs | Lire n discrete inputs | 2000 bits |
| 03 (0x03) | Read Holding Registers | Lire n holding registers | 125 registres |
| 04 (0x04) | Read Input Registers | Lire n input registers | 125 registres |
| 06 (0x06) | Write Single Register | Écrire un registre | 1 registre |
| 16 (0x10) | Write Multiple Registers | Écrire n registres | 123 registres |
Le code 03 représente à lui seul la majorité du trafic Modbus dans le monde industriel.
Les autres
| Code | Nom | Remarque |
|---|---|---|
| 05 (0x05) | Write Single Coil | Valeur 0xFF00 = ON, 0x0000 = OFF |
| 07 (0x07) | Read Exception Status | Série uniquement |
| 08 (0x08) | Diagnostics | Série uniquement, compteurs de communication |
| 11 (0x0B) | Get Comm Event Counter | Série uniquement |
| 15 (0x0F) | Write Multiple Coils | 1968 bits max |
| 17 (0x11) | Report Server ID | Série uniquement |
| 20 / 21 (0x14 / 0x15) | Read / Write File Record | Rarement implémenté |
| 22 (0x16) | Mask Write Register | Modification d’un bit sans lecture préalable |
| 23 (0x17) | Read/Write Multiple Registers | Lecture et écriture en une transaction |
| 24 (0x18) | Read FIFO Queue | Rare |
| 43 (0x2B) | Encapsulated Interface Transport | Sous-code 0x0E : identification équipement |
Le code 22 mérite un mot. Il applique un masque ET et un masque OU directement sur le registre. C’est la seule façon propre de changer un bit dans un mot de commande sans risquer d’écraser les bits voisins modifiés entretemps par un autre client.
Lire une trame réelle
Requête : lire 2 holding registers à partir de l’adresse 0, sur l’esclave 1.
RTU — requête : 01 03 00 00 00 02 C4 0B
| Champ | Hex | Valeur | Rôle |
|---|---|---|---|
| Adresse esclave | 01 | 1 | Esclave interrogé |
| Code fonction | 03 | 3 | Read Holding Registers |
| Adresse de départ | 00 00 | 0 | Premier registre lu |
| Nombre de registres | 00 02 | 2 | Quantité demandée |
| CRC-16 | C4 0B | — | Poids faible transmis en premier |
RTU — réponse : 01 03 04 00 6E 00 05 5B ED
| Champ | Hex | Valeur | Rôle |
|---|---|---|---|
| Adresse esclave | 01 | 1 | Esclave qui répond |
| Code fonction | 03 | 3 | Écho du code demandé |
| Nombre d’octets | 04 | 4 | Deux fois la quantité |
| Registre 0 | 00 6E | 110 | Première valeur |
| Registre 1 | 00 05 | 5 | Seconde valeur |
| CRC-16 | 5B ED | — | — |
La même requête en TCP
00 01 00 00 00 06 01 03 00 00 00 02
| Champ | Hex | Valeur | Rôle |
|---|---|---|---|
| Identifiant de transaction | 00 01 | 1 | Apparie requête et réponse |
| Identifiant de protocole | 00 00 | 0 | Toujours 0 pour Modbus |
| Longueur | 00 06 | 6 | Octets qui suivent |
| Identifiant d’unité | 01 | 1 | Adresse esclave derrière une passerelle |
| Code fonction | 03 | 3 | Début de la PDU |
| Adresse de départ | 00 00 | 0 | PDU |
| Nombre de registres | 00 02 | 2 | PDU |
La PDU 03 00 00 00 02 est rigoureusement la même. Seule l’enveloppe change. C’est exactement ce que fait une passerelle Modbus TCP/RTU : elle retire le MBAP, ajoute l’adresse et le CRC, et pousse la trame sur le bus série.
La même requête en ASCII
:010300000002FA suivi de CR LF
| Champ | Caractères | Rôle |
|---|---|---|
| Début de trame | : | Délimiteur d’ouverture |
| Adresse esclave | 01 | Esclave interrogé |
| PDU | 0300000002 | Même contenu qu’en RTU, codé en texte |
| LRC | FA | Contrôle d’erreur |
| Fin de trame | CR LF | Délimiteur de fermeture |
Les réponses d’exception
Quand un serveur ne peut pas traiter une requête, il répond avec le code fonction augmenté de 0x80, suivi d’un code d’exception sur un octet.
Une requête FC 03 refusée donne donc 83.
01 83 02 C0 F1
| Champ | Hex | Valeur | Rôle |
|---|---|---|---|
| Adresse esclave | 01 | 1 | Esclave qui refuse |
| Code fonction | 83 | 131 | 0x03 + 0x80 |
| Code d’exception | 02 | 2 | Illegal Data Address |
| CRC-16 | C0 F1 | — | — |
| Code | Nom | Ce que ça veut dire en vrai |
|---|---|---|
| 01 | Illegal Function | L’équipement n’implémente pas ce code fonction |
| 02 | Illegal Data Address | Registre inexistant, ou plage demandée qui déborde |
| 03 | Illegal Data Value | Valeur hors bornes, ou quantité demandée invalide |
| 04 | Server Device Failure | Erreur interne pendant le traitement |
| 05 | Acknowledge | Requête acceptée, traitement long en cours |
| 06 | Server Device Busy | Occupé, réémettez plus tard |
| 08 | Memory Parity Error | Erreur mémoire sur accès fichier |
| 0A | Gateway Path Unavailable | Passerelle mal configurée |
| 0B | Gateway Target Device Failed to Respond | L’équipement derrière la passerelle ne répond pas |
Les deux plus fréquentes en mise en service sont 02 et 03.
L’exception 02 vient presque toujours de l’adressage à base 1 non converti, ou d’une lecture qui dépasse la fin d’un bloc contigu. Un équipement peut très bien accepter la lecture des registres 0 à 9 et 20 à 29, mais refuser 0 à 29 parce que la plage 10-19 n’existe pas.
L’exception 0B est précieuse : elle vous dit que la passerelle fonctionne et que le problème est côté série. C’est une information de diagnostic, pas une panne réseau.
Types de données : là où ça se complique
Un registre fait 16 bits. Les mesures réelles n’y tiennent pas.
Pour transporter un entier 32 bits ou un flottant IEEE 754, les constructeurs utilisent deux registres consécutifs. Mais la spécification ne dit rien sur l’ordre à respecter. Résultat : quatre combinaisons circulent.
Prenons la valeur flottante 1,0, soit 3F 80 00 00 :
| Ordre | Registre n | Registre n+1 | Nom courant |
|---|---|---|---|
| ABCD | 3F80 | 0000 | Big-endian |
| CDAB | 0000 | 3F80 | Mots inversés |
| BADC | 803F | 0000 | Octets inversés |
| DCBA | 0000 | 803F | Little-endian |
Symptôme classique : une mesure de tension qui affiche 0,0002 V ou 1,4 × 10³⁸ au lieu de 230 V. Le lien série est parfait, le CRC est bon, la valeur est absurde. Essayez les quatre combinaisons, l’une donnera un résultat plausible.
Autre convention fréquente : la valeur entière multipliée par un facteur d’échelle. Un registre à 2305 représentant 230,5 V. Rien dans la trame ne l’indique. Seul le manuel le dit.
La couche physique RS-485
La plupart des « problèmes Modbus » sont des problèmes de bus.
Points à vérifier avant de suspecter le protocole :
- Topologie en guirlande. Pas d’étoile, pas de dérivations. Les antennes créent des réflexions.
- Terminaison 120 Ω aux deux extrémités uniquement. Ni au milieu, ni sur chaque équipement. Trop de terminaisons chargent le bus et écrasent le signal.
- Polarisation. Sans résistances de polarisation, le bus au repos flotte et le récepteur interprète du bruit comme des bits de start. Un seul point de polarisation sur le bus.
- Référence commune. RS-485 est différentiel, mais chaque émetteur-récepteur a besoin d’une référence de masse dans sa plage de mode commun. Le troisième fil n’est pas optionnel.
- 32 charges unitaires maximum par segment en standard. Certains circuits modernes présentent 1/8 de charge, ce qui permet d’aller plus loin, mais vérifiez la fiche technique.
- Longueur et débit. Environ 1200 m à 9600 bauds. La longueur utile chute quand le débit monte.
- Blindage relié à la terre en un seul point. Deux points créent une boucle de masse.
Un bus qui fonctionne avec deux équipements et tombe en défaut quand on en branche un troisième pointe presque toujours vers la terminaison, la polarisation ou une adresse dupliquée.
Sécurité
Modbus n’a aucun mécanisme de sécurité. Pas d’authentification, pas de chiffrement, pas de contrôle d’intégrité au-delà du CRC — qui détecte le bruit, pas la malveillance.
N’importe qui ayant accès au réseau peut écrire dans un holding register. Une trame FC 06 forgée est indiscernable d’une trame légitime.
Les parades réelles :
- Segmentation réseau et filtrage strict du port 502
- Passerelles unidirectionnelles ou pare-feu industriels avec inspection Modbus
- VPN pour toute liaison sortant du site
- Modbus/TCP Security, extension publiée par la Modbus Organization : TLS 1.2, certificats X.509v3, rôles d’autorisation, sur le port 802
L’adoption de Modbus/TCP Security reste limitée. Sur un parc existant, la segmentation reste votre meilleur levier.
Questions fréquentes
Modbus RTU et Modbus TCP sont-ils compatibles ?
Au niveau applicatif, oui : la PDU est identique. Une passerelle suffit pour faire le pont. Au niveau physique, non — ce sont deux réseaux différents.
Combien d’esclaves sur un bus Modbus RTU ?
L’adressage autorise 1 à 247, l’adresse 0 étant réservée à la diffusion. La limite réelle vient du RS-485 : 32 charges unitaires par segment sans répéteur.
Pourquoi ma lecture est-elle décalée d’un registre ?
Adressage à base 1 dans la documentation, à base 0 dans la trame. Le registre 40001 se lit à l’adresse 0.
Qu’est-ce que la diffusion en Modbus ?
Une écriture envoyée à l’adresse 0 est traitée par tous les esclaves, sans réponse. Elle ne fonctionne qu’avec les codes fonction d’écriture, et uniquement sur liaison série.
Peut-on faire de la commande temps réel en Modbus ?
Non. L’interrogation cyclique et l’absence de rapport par exception rendent le temps de réponse dépendant de la taille du cycle. Pour des verrouillages ou du transfert de déclenchement, il faut un protocole conçu pour ça.
Quel est le débit maximal en Modbus RTU ?
Le protocole ne fixe pas de limite. Les équipements courants montent à 115200 bauds. Au-delà de 19200, respectez les temporisations fixes recommandées, sinon la détection de fin de trame devient aléatoire.
Modbus est-il encore pertinent aujourd’hui ?
Oui, pour ce qu’il fait bien : lire des mesures simples sur du matériel hétérogène. Pour la modélisation de données, l’horodatage ou la sécurité, il faut regarder vers OPC UA ou IEC 61850.
