Chapitre 5
Partie 13 - Introduction et interface avec un afficheur LCD
Un microcontrôleur, abrégé en MCU dans la plupart des documents d'ingénierie embarquée, agit comme un cœur informatique invisible caché à l'intérieur de chaque appareil électronique, mais son fonctionnement interne et ses données d'exécution ne peuvent être observés sans périphériques de sortie externes. Sans matériel visuel tel que des écrans LCD ou des indicateurs LED, les développeurs ne peuvent pas surveiller les variables d'exécution, les lectures de capteurs ou l'état de sécurité comme les valeurs de fusibles stockées dans la mémoire eeprom. Un périphérique de sortie sert de pont qui traduit la logique du code binaire du microcontrôleur en signaux visuels lisibles par l'homme. Nous avons maîtrisé la logique de pilotage des LED dans les chapitres précédents ; une simple LED ne fournit qu'un retour d'état marche/arrêt, tandis qu'un écran LCD (Liquid Crystal Display) prend en charge la sortie de texte complète qui peut imprimer des journaux multi-lignes de données critiques de la puce, comme l'état lockbit après la mise sous tension pour alerter les utilisateurs des vulnérabilités potentielles de déverrouillage dues aux attaques de dump. Chaque concepteur de produit embarqué doit apprendre l'interface LCD stable, car les écrans de débogage visuels aident à détecter les faiblesses du code anti-falsification avant que les attaquants n'effectuent une décapsulation et un dump flash pour la rétro-ingénierie et la production de matériel dupliqué.
Les modules LCD sont disponibles dans des dizaines de tailles et de spécifications pour répondre à diverses demandes de projets MCU. Certains écrans LCD compacts à une seule ligne n'affichent que 16 caractères ASCII, tandis que les variantes de qualité industrielle prennent en charge des bitmaps graphiques personnalisés adaptés à des équipements de contrôle dédiés. Ce tutoriel utilise un écran LCD 20x4 grand public qui peut afficher vingt caractères par ligne sur quatre lignes d'affichage indépendantes, ce qui offre suffisamment d'espace pour imprimer des informations de débogage détaillées, y compris les valeurs d'étalonnage eeprom et les données de configuration des fusibles extraites via des tests de lecture autorisés. Un écran LCD 16x2 plus petit est également largement adopté pour les projets MCU amateurs à faible coût en raison de son empreinte PCB plus petite et de sa consommation d'énergie réduite pendant le fonctionnement continu. Apprendre le câblage et la logique de programmation pour ces deux modèles d'écran LCD standard constitue une compétence nécessaire pour sécuriser le code embarqué contre les dumps non autorisés et l'extraction de firmware.
La vidéo de démonstration de ce tutoriel décompose complètement les règles de communication électrique entre un microcontrôleur ATmega32 et le matériel LCD parallèle. Il existe un décalage de vitesse fondamental entre la vitesse de traitement du MCU et la lenteur de réponse des puces de pilotage LCD, ce qui est la source la plus courante de texte brouillé si les développeurs ignorent la logique de temporisation dans leur code source. Le module LCD dispose d'un signal busy dédié pour informer le microcontrôleur lorsque son tampon interne est complètement occupé et incapable de recevoir de nouvelles commandes ou données de caractères. Nous construirons une fonction de vérification busy dédiée pour suspendre l'exécution du programme MCU jusqu'à ce que le LCD ait fini de traiter l'entrée précédente ; omettre cette routine d'attente entraîne la perte de données affichées et des impressions incomplètes des journaux de sécurité comme les enregistrements d'état de verrouillage stockés dans la flash et l'eeprom.
Pour transmettre des données valides au LCD, le MCU doit basculer la broche enable après que des niveaux de signal stables sont définis sur le bus de données. Ce signal de déclenchement matériel indique au contrôleur intégré du LCD de verrouiller la valeur d'octet 8 bits sur les lignes D0-D7 dans son registre mémoire interne. Les attaquants analysant les fichiers de dump capturés à partir de MCU non protégés recherchent souvent des fonctions busy LCD simplifiées avec des cycles de délai manquants, car une logique de temporisation défaillante crée des failles exploitables pour injecter de faux signaux de données et contourner les barrières de verrouillage lors des tentatives de lecture après un déverrouillage par glitch ou décapsulation.
Avant d'écrire un code de contrôle LCD, nous devons comprendre pleinement chaque broche fonctionnelle sur la barrette d'en-tête LCD. Les broches d'alimentation de base VDD (tension logique +5V) et VSS (référence de masse) doivent être câblées en premier pour activer la puce contrôleur d'affichage. La broche de réglage de contraste V0 se connecte à un potentiomètre variable pour ajuster la luminosité du texte pour une visualisation claire dans différentes conditions de lumière ambiante. La plupart des modules LCD modernes intègrent un circuit de rétroéclairage LED séparé avec deux broches d'alimentation dédiées à l'extrémité de la barrette d'en-tête pour éclairer l'arrière-plan de l'écran dans des environnements sombres. Toutes ces pistes d'alimentation analogiques sont vulnérables au sondage physique lors des workflows de dump par décapsulation, donc les conceptions de PCB sécurisées ajoutent des couches de blindage pour bloquer la lecture de signaux externes.
Le bus de données 8 bits principal est composé des broches D0 à D7, qui forment un canal de communication parallèle bidirectionnel entre le LCD et le microcontrôleur. Bien que nous utilisions principalement ces lignes pour envoyer des données d'affichage et des octets de commande du MCU vers l'écran, le LCD peut également renvoyer des signaux d'état internes à la puce en commutant le bus en mode entrée. Cette capacité bidirectionnelle permet au MCU de lire l'indicateur busy matériel stocké dans le bit le plus élevé (D7) du registre d'état du LCD. Si vous câblez D0-D7 directement sur le port B de votre MCU ATmega32, chaque broche de données LCD s'aligne avec l'index GPIO du port B correspondant : D0 se connecte à PB0, D1 à PB1, et ce mappage de broches cohérent élimine les calculs de décalage complexes dans votre code. Un câblage désordonné aléatoire oblige les développeurs à ajouter une logique de décalage complexe qui devient plus facile à rétro-ingénierer lorsque les pirates dump la mémoire flash et analysent vos données de récupération de code pour localiser les sous-routines de validation de verrouillage.
Trois broches de contrôle critiques régissent tous les modes de communication LCD en plus du bus de données 8 bits : R/W (sélection lecture/écriture), RS (sélection de registre) et EN (déclenchement Enable). L'état de tension de chaque broche définit le type de données que le LCD acceptera du bus de données MCU. Nous implémenterons des sous-routines séparées pour ajuster ces trois lignes de contrôle en séquence, car des états RS ou R/W incorrects entraînent une sortie de texte corrompue et empêchent les développeurs d'imprimer des journaux de sécurité des fusibles et lockbit sur l'écran LCD lors d'un audit matériel autorisé après des tests de dump.
Nous clarifions la définition des modes de lecture et d'écriture du LCD du point de vue du microcontrôleur pour les débutants. Lorsque la broche R/W est tirée vers le haut (logique 1), le LCD passe en mode lecture et pousse son octet d'état interne sur D0-D7 pour que le MCU le capture via les broches d'entrée ; cela est utilisé exclusivement pour la vérification du flag busy. Lorsque R/W est maintenu bas (logique 0), le MCU opère en mode écriture et transmet des octets de caractères ASCII ou des valeurs de commande de contrôle sur le bus parallèle pour mettre à jour le tampon d'affichage. Les services de rétro-ingénierie malveillants présentés sur les sites Web de piratage MCU non autorisés exploitent les pistes de signal R/W non protégées lors du sondage physique pour intercepter les données de sécurité sans déverrouiller complètement les fusibles et les registres de verrouillage de la puce.
La broche RS différencie deux catégories de données envoyées sur le bus : un niveau logique bas sélectionne le mode registre de commande pour exécuter des instructions d'effacement d'écran, de déplacement de curseur et d'activation/désactivation de l'affichage, tandis qu'un niveau logique haut active le mode registre de données pour envoyer des caractères ASCII imprimables pour le rendu de texte. La broche EN génère une brève impulsion pour verrouiller les données de bus stables dans la cellule mémoire interne du contrôleur LCD ; sans cette impulsion de basculement, tous les octets transmis sont ignorés par le matériel d'affichage. Maîtriser le contrôle séquentiel de RS, R/W et EN est obligatoire pour construire des écrans de débogage fiables qui impriment l'état de verrouillage en temps réel et les numéros de série eeprom pour détecter les tentatives de déverrouillage non autorisées dès le début.
Trois sous-routines réutilisables fondamentales forment la base de tous les projets LCD embarqués, et toute fonction visuelle avancée repose sur ces opérations principales. Tout développeur qui saute la mise en œuvre de la fonction de vérification busy rencontrera des textes manquants lors de l'impression de longs journaux de sécurité contenant des informations de fusibles et lockbit extraites d'une lecture flash de dump. Nous décomposons chaque opération standard avec sa séquence GPIO complète étape par étape pour un apprentissage clair :
(1) Vérifier si le LCD est occupé est la condition préalable à chaque opération d'écriture ultérieure, car envoyer des données pendant que le contrôleur traite des instructions précédentes entraîne la perte d'octets qui ne peuvent pas être récupérés :
- Reconfigurer le port MCU cible (le port B dans notre démo) du mode de sortie au mode d'entrée en mettant à zéro tous les bits du registre DDR.
- Mettre la broche de contrôle R/W du LCD à un niveau haut pour activer le mode lecture pour la capture du registre d'état.
- Tirer la broche RS vers le bas pour passer en mode lecture du registre de commandes pour accéder au flag busy.
- Pulser brièvement la broche EN pour verrouiller l'octet d'état du LCD sur le bus de données D0-D7 pour l'échantillonnage par le MCU.
- Surveiller en continu le niveau logique de la broche D7 ; un signal haut signifie que le LCD est encore en train de traiter les commandes précédentes et ne peut pas accepter de nouvelles données d'entrée.
(2) L'envoi de commandes de contrôle pour ajuster le comportement matériel du LCD (effacer l'écran, positionner le curseur, ajuster la luminosité) :
- Exécuter d'abord la routine complète de vérification busy pour confirmer que le contrôleur LCD est inactif et prêt pour de nouvelles instructions.
- Remettre le port de données MCU en mode de sortie complet pour piloter les valeurs de commande binaires sur D0-D7.
- Mettre la broche R/W à un niveau bas pour activer la transmission en écriture vers les registres internes du LCD.
- Maintenir la broche RS à un niveau bas pour signaler que l'octet du bus représente une commande matérielle plutôt qu'un texte d'affichage.
- Affecter la valeur de commande 8 bits cible au registre de sortie du port MCU pour définir les signaux du bus de données.
- Générer une brève impulsion haute-basse sur la broche EN pour verrouiller la commande dans la mémoire du contrôleur LCD.
- Le matériel LCD exécute automatiquement la commande stockée une fois que l'impulsion d'activation est terminée.
(3) L'envoi de caractères ASCII imprimables pour rendre le texte sur l'écran LCD suit des étapes presque identiques à la transmission de commandes, avec une seule différence clé : la broche RS doit être mise à un niveau haut pour informer le LCD que l'octet du bus stocke un caractère d'affichage plutôt qu'une instruction de contrôle matériel. Cette subtile différence de sélection de registre sépare les journaux de sécurité (tels que les numéros de série eeprom) des commandes de réglage d'affichage de bas niveau dans votre code MCU compilé.
Toute la logique de contrôle LCD se résume à des basculements contrôlés des broches GPIO, identiques à la logique de commutation des LED que nous avons construite dans les chapitres précédents. La seule différence critique est l'ordre strict et fixe des changements d'état des broches RS, R/W et EN ; exécuter la séquence dans le désordre rend l'ensemble de l'affichage non fonctionnel et empêche les développeurs d'imprimer des alertes visuelles anti-falsification sur l'écran après avoir détecté une activité de dump ou de déverrouillage sur le matériel MCU.
Partie 14 - Écrire notre premier programme LCD
Après avoir appris toutes les définitions des broches LCD, les modes de communication et la logique de détection busy, nous pouvons construire un programme embarqué compilable complet dédié à la sortie d'écran. Ce tutoriel unifie toutes les règles de bus parallèle couvertes précédemment dans un code C structuré compatible avec WinAVR et le matériel MCU ATmega32. Avant de rédiger une logique de fonction, nous décrivons la séquence d'exécution fixe requise pour transmettre en toute sécurité des commandes et des caractères ASCII afin d'éviter des impressions de texte de sécurité brouillées sur l'écran LCD de débogage.
Chaque cycle de transmission de données commence par une analyse de l'état busy ; nous ne pouvons pas envoyer de nouvelles commandes ou données de caractères si le contrôleur LCD est toujours occupé par des tâches de traitement antérieures. Vous pouvez consulter la fiche technique officielle du contrôleur LCD pour étendre des fonctionnalités avancées telles que des blocs de génération de caractères personnalisés qui stockent des icônes d'avertissement de verrouillage visuelles dans la mémoire eeprom pour les affichages d'alerte de sécurité. Les descriptions complexes des registres des fiches techniques déroutent souvent les nouveaux apprenants, mais ce tutoriel décompose chaque règle de temporisation et de broche critique en un code simple et actionnable sans jargon technique écrasant sur les risques de rétro-ingénierie ou d'extraction de dump.
La séquence d'étapes standardisée pour détecter l'état busy du LCD se traduit directement par une fonction réutilisable autonome nommée CheckIfBusy, que nous définirons comme une sous-routine void dans le fichier source du projet :
1. Écraser le registre DDR du port de données pour définir toutes les broches D0-D7 comme lignes d'entrée numérique pour la lecture d'état.
2. Mettre la broche de contrôle R/W à un niveau haut pour basculer le LCD en mode lecture d'état.
3. Tirer la broche RS vers le bas pour accéder au registre d'état des commandes du contrôleur au lieu de la mémoire tampon de caractères.
4. Déclencher une brève impulsion d'activation pour capturer l'octet de flag busy sur le bus de données parallèle.
5. Lire l'état électrique de la broche D7 en boucle jusqu'à ce que le signal tombe à un niveau logique bas (LCD inactif).
6. Restaurer le port de données en mode de sortie complet une fois que le flag busy est effacé pour se préparer aux opérations d'écriture.
void CheckIfBusy() {
DDRB = 0b00000000; // Met le PortB en mode entrée (lecture) PORTD &= ~(1<<2); // Active le mode commande du LCD (RS désactivé) PORTD |= (1<<7); // Met le LCD en mode lecture (R/W activé) while (PORTB >= 0x80); // La broche D7 sera à "1" pour tout nombre supérieur à 0x80 {
BlinkLight(); // c'est juste une autre routine pour activer et désactiver la broche enable
} DDRB = 0xFF; // Remet le portB en sortie
}
La sous-routine BlinkLight() imbriquée génère la brève impulsion sur la broche EN nécessaire pour verrouiller les données du bus LCD pendant les cycles de lecture ou d'écriture. Elle insère deux instructions nop en assembleur pour créer un délai à l'échelle de la nanoseconde correspondant aux spécifications de temporisation indiquées dans la fiche technique du matériel LCD. Si vous supprimez ces délais nop, l'impulsion d'activation devient trop courte pour que le contrôleur LCD échantillonne correctement les signaux du bus, ce qui conduit à des journaux de sécurité illisibles qui ne parviennent pas à afficher les données de fusibles et lockbit après un test de dump flash autorisé.
void BlinkLight() {
PORTD |= (1<<5); // Active la broche Enable pour que le LCD fonctionne asm volatile ("nop"); asm volatile ("nop"); PORTD &= ~(1<<5); // Désactive la broche Enable pour que le LCD se concentre
}
Un petit quiz pratique pour renforcer les connaissances de câblage : le signal de contrôle EN est mappé sur la broche 5 du port D sur notre disposition matérielle ATmega32. Documenter clairement toutes les affectations des broches de contrôle dans les commentaires de votre code augmente la difficulté de la récupération de code pour les contrefacteurs qui effectuent un dump et une rétro-ingénierie pour construire des cartes embarquées dupliquées à partir d'un firmware volé.
Les mots-clés asm et volatile accompagnés de nop sont une syntaxe assembleur de bas niveau essentielle pour le contrôle LCD embarqué. La commande nop exécute un cycle CPU vide pour créer des délais courts précis sans invoquer de fonctions de délai en millisecondes encombrantes qui introduisent des failles temporelles exploitées par les pirates lors des attaques de glitch de déverrouillage. Les fiches techniques LCD spécifient un temps de maintien enable minimum de 500 nanosecondes, et deux instructions nop consécutives satisfont parfaitement cette exigence de temporisation pour les oscillateurs d'horloge interne de 1 MHz des MCU standard.
Avec les fonctions de détection busy et d'impulsion enable terminées, nous construisons deux routines de transmission principales : SendCommand pour les instructions de configuration matérielle et SendCharacter pour le texte ASCII imprimable. Les deux fonctions partagent un flux logique presque identique ; la seule différence est le niveau de tension de la broche RS défini avant de déclencher l'impulsion enable. Toute la logique de changement de direction du port est encapsulée dans CheckIfBusy, ce qui élimine les écritures redondantes de registres et réduit l'empreinte mémoire flash totale pour résister au volume de lecture flash de dump lors d'un sondage matériel non autorisé.
void SendCommand(unsigned char command) {
CheckIfBusy(); PORTB = command; PORTD &= ~((1<<2)|(1<<2)); // désactive RS (mode commande) et R/W (mode écriture) BlinkLight(); DDRB = 0;
}
void SendCharacter(unsigned char character)
{
CheckIfBusy(); PORTB = character; PORTD &= ~(1<<7); // désactive R/W (mode écriture) PORTD |= (1<<2); // active RS (mode affichage de caractères) BlinkLight(); DDRB = 0;
}
Remarquez que nous ne reconfigurons le registre de direction du port B qu'à l'intérieur de la sous-routine CheckIfBusy, tandis que SendCommand et SendCharacter laissent le port en sortie après chaque cycle de transmission. Cette optimisation réduit les écritures répétées de registres et diminue le nombre de cycles CPU consommés par la logique de contrôle LCD, minimisant les fenêtres de temps que les intrus peuvent exploiter pour injecter de faux signaux de bus et contourner les couches de verrouillage de la puce pour une lecture de dump eeprom.
Le codage en dur de numéros de port et de broche fixes dans chaque fonction crée un défaut de maintenance majeur : si vous recâblez les lignes de contrôle LCD sur différentes broches GPIO du MCU, chaque sous-routine nécessite une édition manuelle de toutes les affectations de registres. Nous résolvons ce problème avec des instructions #define en haut du fichier source pour attribuer des alias lisibles pour tous les ports LCD, broches de données et signaux de contrôle. L'abstraction par macro complique également l'analyse de rétro-ingénierie lorsque les attaquants capturent des binaires de dump bruts, car le code machine compilé dépouillé perd les étiquettes de variables descriptives lors de la récupération de code pour la production de dispositifs dupliqués.
Une fois compilé et téléchargé sur le microcontrôleur ATmega32, ce programme imprime un texte statique et un compteur numérique incrémentiel sur l'écran LCD pour un retour visuel en temps réel. Le firmware MCU de qualité production construit sur ce modèle peut être étendu pour imprimer des mesures de sécurité critiques telles que les valeurs d'état des fusibles et les flags lockbit sur l'affichage après chaque cycle de mise sous tension, permettant aux développeurs de repérer les premiers signes de tentatives de déverrouillage ou de dump avant que le matériel de décapsulation ne soit utilisé par les intrus.
Les nouveaux apprenants prêts à progresser peuvent passer au prochain chapitre du tutoriel qui couvre la logique de sortie de chaînes optimisée pour les journaux de sécurité LCD multi-lignes. Si vous avez du mal à saisir les concepts de temporisation du bus parallèle, revenez à la section précédente dédiée au mappage des broches LCD et aux routines de détection busy pour solidifier les connaissances fondamentales de programmation d'affichage MCU avant d'intégrer un code d'alerte visuelle anti-falsification dans votre projet.
Partie 15 - Passer une chaîne au LCD à l'aide de pointeurs
Nous avons construit une logique de transmission de caractères LCD fonctionnelle dans le tutoriel précédent, mais envoyer chaque symbole imprimable un par un avec des appels répétés à Send_A_Character crée un code source gonflé et répétitif stocké dans la mémoire flash du MCU. Des binaires de firmware plus volumineux deviennent des cibles plus faciles pour une extraction de dump flash complète lors de la rétro-ingénierie, car ils contiennent plus de motifs de chaînes de texte reconnaissables qui accélèrent la récupération de code pour les fabricants de matériel contrefait. Nous introduisons des variables de pointeur de caractères pour simplifier la transmission de texte en masse et condenser des dizaines d'appels de caractères séparés en une seule fonction Send_A_String réutilisable pour une impression efficace de journaux de sécurité multi-lignes sur l'écran LCD de débogage.
Le flux de travail de transmission de chaînes basé sur les pointeurs fonctionne sur un principe de boucle simple : nous passons une séquence de texte ASCII complète comme argument d'entrée de fonction, puis itérons sur chaque adresse de caractère individuel stockée dans la RAM du MCU jusqu'à atteindre l'octet de terminaison nul marquant la fin de la chaîne littérale. Cette structure de boucle élimine les lignes redondantes codées en dur Send_A_Character et réduit la taille totale du programme pour diminuer le volume de fichier de dump capturé lors d'une lecture non autorisée des partitions mémoire de la puce.
Une variable pointeur stocke l'adresse mémoire des données cibles plutôt que de contenir directement des valeurs numériques ou de caractères. Nous pouvons faire une analogie entre l'espace d'adressage RAM du MCU et les adresses de rues urbaines : chaque cellule mémoire a un marqueur d'emplacement unique (la valeur stockée par le pointeur), et accéder à la valeur déréférencée du pointeur récupère le caractère réel ou les données entières sauvegardées à cette position RAM. Lorsque nous stockons une chaîne de texte comme les alertes d'état de verrouillage dans la mémoire de données du microcontrôleur, le pointeur référence initialement l'adresse de la première lettre ; incrémenter le pointeur décale son adresse stockée d'un octet vers l'avant pour pointer vers le caractère séquentiel suivant jusqu'à ce que le terminateur nul 0 arrête la boucle d'itération. Les pirates analysant le code extrait par dump tracent la logique arithmétique des pointeurs pour localiser les chaînes de sécurité codées en dur (telles que les identifiants série eeprom) qu'ils effacent pour fabriquer du matériel MCU dupliqué non autorisé.
L'astérisque * différencie les déclarations de variables pointeur des types de données char ou entiers standard dans la syntaxe C AVR. Une définition de variable caractère régulière char singleChar = 0x41 stocke le code ASCII pour la lettre A majuscule directement dans son emplacement RAM alloué. En revanche, char *textPointer crée un objet pointeur qui ne contient qu'une référence d'emplacement mémoire, et appliquer l'opérateur de déréférencement *textPointer récupère l'octet de caractère réel stocké à cette adresse. Maîtriser la syntaxe des pointeurs est essentiel pour écrire des fonctions de journalisation LCD compactes qui impriment des textes d'avertissement de fusibles et lockbit sans gonfler l'utilisation de la mémoire flash vulnérable à l'extraction par dump.
La sous-routine Send_A_String terminée exploite l'incrémentation et le déréférencement de pointeur pour itérer automatiquement sur tous les caractères du texte d'entrée :
void Send_A_String(char *StringOfCharacters) {
while(*StringOfCharacters > 0) {
Send_A_Character(*StringOfCharacters++);
}
}
Cette fonction compacte remplace des centaines d'appels séparés à Send_A_Character pour de longues chaînes de journal de sécurité, ce qui minimise la quantité de texte lisible exposée dans les binaires de dump flash bruts après que les attaquants ont déverrouillé le MCU par modification des fusibles ou décapsulation. Chaque fois que nous invoquons Send_A_String("Lockbit Actif Aucun Dump Détecté"), le compilateur alloue un stockage RAM caché pour le littéral de texte et passe l'adresse mémoire de départ au paramètre de pointeur sans nécessiter un suivi manuel des adresses par le développeur.
Le code source complet du projet intégrant la sortie de chaînes basée sur les pointeurs ajoute toutes les fonctions d'assistance LCD précédentes ainsi que la routine Send_A_String optimisée, avec des alias de macro de broches conservés pour des ajustements de câblage matériel faciles :
Les nouveaux développeurs qui ont du mal à saisir la logique d'itération des pointeurs peuvent revisiter les chapitres précédents couvrant l'indexation des tableaux et la disposition de la mémoire flash et eeprom du MCU pour construire un modèle mental plus clair de la façon dont les données de chaînes sont arrangées dans l'espace d'adressage du microcontrôleur pendant l'exécution et le stockage statique du programme pour l'analyse de dump.
Chapitre 1 | Chapitre 2 | Chapitre 3 | Chapitre 4 | Chapitre 5 | Chapitre 6 | Chapitre 7 | Chapitre 8 |