Vous êtes sur la page 1sur 134

‫اﻟﺠﻤﮭﻮرﯾﺔ اﻟﺠﺰاﺋﺮﯾﺔ اﻟﺪﯾﻤﻘﺮاﻃﯿﺔ اﻟﺸﻌﺒﯿﺔ‬

République Algérienne Démocratique et Populaire


‫وزارة اﻟﺘﻌﻠﯿﻢ اﻟﻌﺎﻟﻲ و اﻟﺒﺤﺚ اﻟﻌﻠﻤﻲ‬
Ministère de l’Enseignement Supérieur et de la Recherche Scientifique

‫ﺟﺎﻣﻌﺔ ﻣﺤﻤﺪ ﺧﯿﻀﺮ ﺑﺴﻜﺮة‬


Université Mohamed Khider Biskra
Faculté des Sciences et de la Technologie
‫ﻛﻠﯿﺔ اﻟﻌﻠﻮم و اﻟﺘﻜﻨﻮﻟﻮﺟﯿﺎ‬
Département de Génie Electrique ‫ اﻟﮭﻨﺪﺳﺔ اﻟﻜﮭﺮﺑﺎﺋﯿﺔ‬: ‫ﻗﺴﻢ‬
Filière d’Electronique ‫ اﻟﻜﺘﺮوﻧﯿﻚ‬: ‫ﺷﻌﺒﺔ‬

Microprocesseurs et
ses interfaces
Support de cours : 1 ere année Master
INSTRUMENTATION et Micro-informatique

Préparer par : Dr. Okba Benelmir

Année Universitaire : 2015-2016


Sommaire
Chapitre 1 : Introduction aux microprocesseurs ..........................................................................................4
I.1 Introduction ..................................................................................................................................4
I.2 Architecture d'un système à microprocesseur...........................................................................4
I.2.1 Le microprocesseur ......................................................................................................................4
I.2.2 La mémoire ...................................................................................................................................5
I.2.3 Interface I/O.................................................................................................................................6
I.3 Architecture de base d’un microprocesseur ..............................................................................6
I.3.1 Unité de traitement.......................................................................................................................6
I.3.2 Unité de commande ......................................................................................................................7
I.4 La famille de 80x86.......................................................................................................................7
I.4.1 Le microprocesseur 8086 (1978)..................................................................................................7
I.4.2 Le microprocesseur 8088 (1979)..................................................................................................8
I.4.3 Les microprocesseurs 80186 & 80188 (1982) .............................................................................8
I.4.4 Le microprocesseur 80286 (1982)................................................................................................8
I.4.5 Le microprocesseur 80386 (1984)................................................................................................8
I.4.6 Le microprocesseur 80486 (1989)................................................................................................9
I.4.7 Le microprocesseur Pentium (1993) ...........................................................................................9
Chapitre 2 : Le Microprocesseur Intel 8086 ................................................................................................10
II.1 Description physique du 8086....................................................................................................10
II.2 Schéma fonctionnel du 8086 ......................................................................................................10
II.2.1 Connexions de base ....................................................................................................................13
II.3 Organisation interne du 8086 ....................................................................................................13
II.4 La segmentation de la mémoire.................................................................................................15
Chapitre 3 : La programmation du microprocesseur 8086.......................................................................16
III.1 Généralités.....................................................................................................................................16
III.2 Les modes d'adressage ...............................................................................................................16
III.2.1 Adressage registre ....................................................................................................................17
III.2.2 Adressage immédiat .................................................................................................................17
III.2.3 Adressage direct .......................................................................................................................17
III.2.4 Adressage indirect par registre ...............................................................................................17

1
III.2.5 Adressage basé ...........................................................................................................................17
III.2.6 Adressage indexé .......................................................................................................................17
III.2.7 Adressage basé indexé ...............................................................................................................18
III.3 Les instructions de transfert .......................................................................................................18
III.3.1 Instruction MOV .......................................................................................................................18
III.3.2 Instruction de pile......................................................................................................................19
III.3.3 Instruction XCHG......................................................................................................................20
III.4 Les instructions arithmétiques .................................................................................................20
III.4.1 Instruction ADD .........................................................................................................................20
III.4.2 Instruction ADC ........................................................................................................................20
III.4.3 Instruction INC...........................................................................................................................21
III.4.4 Instruction SUB .........................................................................................................................21
III.4.5 Instruction SBB .........................................................................................................................21
III.4.6 Instruction DEC ........................................................................................................................21
III.4.7 Instruction NEG ........................................................................................................................21
III.4.8 Instruction CMP.........................................................................................................................21
III.4.9 Instruction MUL.........................................................................................................................22
III.4.10 Instruction DIV.........................................................................................................................22
III.4.11 Instructions IMUL et IDIV.....................................................................................................22
III.5 Les instructions logiques..........................................................................................................22
III.5.1 Instruction AND..........................................................................................................................22
III.5.2 Instruction OR ...........................................................................................................................22
III.5.3 Instruction XOR ........................................................................................................................23
III.5.4 Instruction TEST........................................................................................................................23
III.5.5 Instruction NOT .........................................................................................................................23
III.5.6 Instructions de Décalages...........................................................................................................23
III.5.7 Instructions de Rotations ...........................................................................................................24
III.6 Les instructions de branchement .............................................................................................24
III.6.1 Instruction de saut inconditionnel ...........................................................................................25
III.6.2 Instructions de sauts conditionnels ..........................................................................................25
III.6.3 Instruction CALL.......................................................................................................................25
III.6.4 Instruction RET ..........................................................................................................................26

2
III.6.5 Instructions des interruptions ...................................................................................................26
III.6.6 Instruction de boucles LOOP ....................................................................................................26
III.7 Les instructions de manipulation de chaines ...........................................................................26
Chapitre 4 : Interfaçage du microprocesseur 8086 .....................................................................................28
IV.1 Microprocesseur 8086 (Minimum Mode).................................................................................28
IV.2 Générateur d’horloge.................................................................................................................28
IV.3 Bus système (Demultiplexed and Buffered) .............................................................................28
IV.4 Mémoire système (ROM & RAM) ............................................................................................30
IV.5 E/S système (Switches and LEDs) .............................................................................................32
IV.5.1 Adresse cartographique .............................................................................................................32
IV.5.2 Adressage indépendant ..............................................................................................................32
Chapitre 5 : Les interfaces d’entrées/sorties................................................................................................34
V.1 Définition.....................................................................................................................................34
V.2 L’interface parallèle 8255 .........................................................................................................34
V.2.1 Interfaçage de 8086 avec le 8255 ...............................................................................................37
V.3 Le 8279........................................................................................................................................37
V.4 L’interface série 8250 .................................................................................................................38
V.4.1 Structure de l’UART..................................................................................................................39
V.4.2 Les registres du 8250..................................................................................................................40
Chapitre 6 : Les interruptions......................................................................................................................41
VI.1 Définition d’une interruption ....................................................................................................41
VI.2 Le contrôleur programmable d’interruptions 8259 ................................................................42
VI.3 Le temporisateur programmable 8253/8254...........................................................................44
VI.4 DMA (Accès Direct à la Mémoire)............................................................................................48
VI.5 Le 8237.........................................................................................................................................48
Bibliographie...................................................................................................................................................50

3
Chapitre 1 : Introduction aux microprocesseurs

I.1 Introduction
Dans les années 70 les technologies des
ordinateurs numériques et celles des circuits intégrés
sont fondues pour donner naissance au
microprocesseur.
Le microprocesseur possède une architecture
semblable à l’ordinateur en plus tous les deux
effectuent des calculs sous le contrôle d’un
programme.
La plupart des systèmes informatiques
d'aujourd'hui sont basés sur un principe de conception
proposée par le Dr John Von Neumann (1946).

I.2 Architecture d'un système à microprocesseur


Dans un système à microprocesseur (Architecture de Von Neumann), on retrouve au
minimum : (1) Un microprocesseur, (2) Une mémoire morte (ROM) + Une mémoire vive (RAM),
(3) Une interface entrées/sorties
Tous ces organes sont reliés entre eux avec 3 bus : Bus de données bidirectionnel, Bus d'adresse,
Bus de commande

Figure I.1 : Système à microprocesseur

I.2.1 Le microprocesseur
C’est le cœur du système. C’est lui qui a la charge des fonctions suivantes :
- Fournit les signaux de synchronisation et de commande à tous les éléments du système
- Prend en charge les instructions et les données dans la mémoire
- Transfère les données entre la mémoire et les dispositifs d’I/O et vice versa
- Décode les instructions
- Effectue les opérations arithmétiques et logiques commandées par les instructions
- Réagit aux signaux de commande produits par les entrées/sorties comme le signal RESET et
les INTERRUPTIONS

4
I.2.2 La mémoire
La mémoire a pour rôle de conserver des groupes de chiffres binaires (mots) qui sont soit
des instructions formant un programme, soit des données dont le programme a besoin.
Elle se décompose souvent en :

a/ une mémoire morte (ROM = Read Only Memory) chargée de stocker le programme. C’est une
mémoire à lecture seule.
• ROM : Read Only Memory. Mémoire à lecture seule, sans écriture. Son contenu est programmé
une fois pour toutes par le constructeur. Avantage : faible coût.
Inconvénient : nécessite une production en très grande quantité.
• PROM: Programmable Read Only Memory. ROM programmable une seule fois par l’utilisateur.
• EPROM : Erasable PROM, appelée aussi UVPROM. ROM programmable électriquement avec
un programmateur et effaçable par exposition à un rayonnement ultraviolet.
• EEPROM : Electrically Erasable PROM. ROM programmable et effaçable électriquement.
Les EEPROM contiennent des données qui peuvent être modifiées.
b/ une mémoire vive (RAM = Random Access Memory) chargée de stocker les données
intermédiaires ou les résultats de calculs. On peut lire ou écrire des données dedans, ces données
sont perdues à la mise hors tension.
• SRAM: Static Random Access Memory. Mémoire statique à accès aléatoire, à base de bascules à
semi-conducteurs à deux états (bascules RS).
• DRAM : Dynamic RAM. Basée sur la charge de condensateurs : condensateur chargé = 1,
condensateur déchargé = 0.
Remarque :
Les disques durs, disquettes, CDROM, etc… sont des périphériques de stockage et sont considérés
comme des mémoires secondaires.
On peut donc schématiser un circuit mémoire par la figure suivante où l’on peut distinguer :

Figure I.2 : Schéma fonctionnel d’une mémoire

5
Les entrées d’adresses, les entrées / sorties de données, les entrées de commandes :
Entrée de sélection de lecture ou d’écriture. (R/ W), une entrée de sélection du circuit. (CS).
Le nombre de lignes d’adresses dépend de la capacité de la mémoire : n lignes d’adresses
permettent d’adresser 2n cases mémoire: 8 bits d’adresses permettent d’adresser 256 octets, 16 bits
d’adresses permettent d’adresser 65536 octets (= 64 Ko), ...
Exemple : mémoire RAM 6264, capacité = 8K×8 bits : 13 broches d’adresses A0 à A12,
213 = 8192 = 8 Ko.

I.2.3 Interface I/O


C’est un circuit intégré permettant au microprocesseur de communiquer avec
l’environnement extérieur (périphériques) : clavier, écran, imprimante, bouton poussoir, processus
industriel, actionneurs…
Les transferts E/S correspondent à des instructions de lecture et d’écriture. Le plus souvent le circuit
d’interface comporte un registre appelé « port ».
Ecriture : Le microprocesseur envoie l’ordre d’écriture et les données sont mémorisées dans le
registre de l’interface.
Lecture : le circuit se contente de présenter les informations du périphérique sur le bus de données.

I.3 Architecture de base d’un microprocesseur


Le microprocesseur est construit autour de deux éléments principaux :
Une unité de traitement et Une unité de commande

I.3.1 Unité de traitement


Elle regroupe les circuits qui assurent les traitements nécessaires à l'exécution des instructions.
Les blocs de l’unité de traitement :

UAL Registres
Bus d’adresse
Flags
Bus de données

Décodeur Séquenceur

D’instructions Bus de commande

Unité de commande
Figure I.3: Principales sections d'un microprocesseur

6
 ALU (Arithmetic and Logic Unit)
C'est l’unité qui permet d'effectuer des calculs arithmétiques simples (additions, soustractions,
décalages, etc.) et des opérations logiques (ET, OU, etc.).
 Les registres généraux
Les registres généraux participent aux opérations arithmétiques et logiques ainsi qu'à l'adressage. Le
plus important est appelé accumulateur.
 Registre d’état
C’est l’ensemble des drapeaux (flags) qui forme le registre d’état.
Les flags réagissent après certaines instructions et permettent de savoir si le résultat de l'opération
est zéro (flag Z), si il y a eu un dépassement (flag C), si le nombre de bit à 1 est pair (flag P) et le
signe (flag S).

I.3.2 Unité de commande


C’est l’ensemble séquenceur/décodeur d’instruction. Elle est composée par :
 Séquenceur
C'est le maître d'orchestre, il cadence le microprocesseur. C'est lui qui pilote le bus de
commande et les blocs internes
 Décodeur d’instruction
Il reconnaît l’instruction et la transforme en signaux internes grâce à un microcode contenu
dans une ROM interne.
 Le compteur de programme
Constitué par un registre dont le contenu est initialisé avec l'adresse de la première
instruction du programme. Il contient toujours l’adresse de l’instruction à exécuter.
 Stack Pointer
Il a pour rôle d’indiquer au microprocesseur la prochaine case disponible dans la pile.

I.4 La famille de 80x86


I.4.1 Le microprocesseur 8086 (1978)
Adresse bus 20-bit.
16 bits du bus de données internes.
16 bits du bus de données externes.
L’unité d'interface de bus (BIU) et l'unité d'exécution (EU).
Registres de 16 bits (certains registres sont découpés en deux et on peut accéder séparément
à la partie haute et à la partie basse.).
Il peut être utilisé avec un coprocesseur mathématique externe.

7
I.4.2 Le microprocesseur 8088 (1979)
Il est entièrement compatible avec le 8086, le jeu d'instruction est identique. La seule
différence réside dans la taille du bus de données, celui du 8088 fait seulement 8 bits.

I.4.3 Les microprocesseurs 80186 & 80188 (1982)


Le 80186/80188 intègre sur une seule puce un microprocesseur 8086/8088 plus un
générateur d'horloge, un temporisateur programmable, un contrôleur d'interruption
programmable, un contrôleur d'accès direct à la mémoire et un circuit pour sélectionner les
dispositifs d'E / S.

I.4.4 Le microprocesseur 80286 (1982)


Bus d'adresse de 24 bits.
16 bits du bus de données internes.
16 bits du bus de données externes.
Conçu pour être compatible avec 8086 & 80186 microprocesseurs.
Fournit deux modes de programmation:
Mode réel : le processeur fonctionne exactement comme le processeur 8086.
Mode protégé : Dans ce mode, le processeur utilise l'espace mémoire complète qui est
16MB.
Ce mode est appelé mode protégé parce que plusieurs programmes peuvent être chargés en
mémoire à la fois (chacun dans son propre segment), mais ils sont protégés l’un contre l'autre.

I.4.5 Le microprocesseur 80386 (1984)


Bus d'adresse de 32 bits.
32 bits du bus de données internes.
32 bits du bus de données externes.
Des registres de 32 bits.
Offre trois modes:
Mode réel (identique à celui de 80 286)
Le mode protégé (gère 4 Go de mémoire d'une manière similaire à celle du 80 286).
Mode virtuel (similaire au mode réel, sauf que plusieurs processeurs 8086 peuvent
fonctionner simultanément).

8
I.4.6 Le microprocesseur 80486 (1989)
Bus d'adresse de 32 bits.
Bus de données 32 bits interne et externe.
Des registres de 32 bits.
On-chip cache (stocke les instructions et les données les plus récemment utilisées)
Unité à virgule flottante intégrée (FPU)
Modes réels et protégés comme dans 80386

I.4.7 Le microprocesseur Pentium (1993)


Bus d'adresse de 32 bits.
32-bit interne
64 bits du bus de données externes.
Des registres de 32 bits.
Deux instructions pipelines
On-chip cache
FPU intégré

9
Chapitre 2 : Le Microprocesseur Intel 8086

II.1 Description physique du 8086

Le microprocesseur Intel 8086 est un microprocesseur 16 bits, apparu en 1978. C’est le


premier microprocesseur de la famille Intel 80x86 (8086, 80186, 80286, 80386, 80486, Pentium,
...). Il se présente sous la forme d’un boitier DIP (Dual In-line Package) à 40 broches :

II.2 Schéma fonctionnel du 8086

Figure II.1: Brochage et Schéma fonctionnel du 8086

Brochage et Fonctions des Pins du 8086 :


CLK : entrée du signal d’horloge qui cadence le fonctionnement du microprocesseur. Ce signal
provient d’un générateur d’horloge : le 8284.
AD0 à AD15 : Ces lignes représentent 16 bits de bus d'adresse multiplexés avec 16 bits de lignes
de données.
Pendant T1, elles représentent des lignes d'adresse A15-A0.
Pendant T2, T3, T4, elles représentent des lignes de données D0-D15.
A16/S3 à A19/S6 : Ces lignes adresse sont multiplexées avec les lignes d´état.
Pendant T1, elles représentent des lignes d'adresse A19-A16.
Pendant T2, T3, T4, elles représentent des signaux d'état S6-S3.
S0 à S7 : signaux d’état indiquant le type d’opération en cours sur le bus.

10
ALE (Address Latch Enable ): Ce signal est une impulsion active pendant T1, elle indique que
l’information qui circule dans bus A/D est une adresse.
Elle est fournie par le Cpu pour verrouiller les lignes d'adresse au cours des cycles T2, T3, T4.
RD : Read, signal de lecture d’une donnée.
WR : Write, signal d´écriture d’une donnée.
M/IO : Memory/Input-Output, indique si le CPU adresse la mémoire (M/IO = 1) ou les
entrées/sorties (M/IO = 0).
DEN : Data Enable, indique que des données sont en train de circuler sur le bus A/D (équivalente
de ALE pour les données).
DT/R : Data Transmit/Receive, indique le sens de transfert des données :
• DT/R = 1 : données émises par le microprocesseur (écriture) ;
• DT/R = 0 : données reçues par le microprocesseur (lecture).

Chronogramme de séparation de bus A/D

11
Chronogramme de sens de transfert de données sur le bus de données

READY : Entrée de synchronisation avec la mémoire.


TEST : Entrée de mise en attente du microprocesseur d’un évènement extérieur.
RESET : Entrée de remise à zéro du microprocesseur.
MN/MX : indique dans quel mode le processeur doit fonctionner
HIGH  minimum mode.
LOW  maximum mode.
NMI et INTR : Entrées de demande d’interruption.
INTR : interruption normale,
NMI (Non Maskable Interrupt) : interruption prioritaire.
INTA : Interrupt Acknowledge, indique que le microprocesseur accepte l’interruption.
HOLD et HLDA : Signaux de demande d’accord d’accès direct à la mémoire (DMA).
BHE : Bus High Enable, signal de lecture de l’octet de poids fort du bus de données.
Il est utilisé avec A0 pour sélectionner le mot entier, octet fort, octet faible ou aucun.

BHE A0 Data Selected

0 0 les deux octets (mot complet) (D15-D0)

0 1 octet fort (adresse impaire) (D15-D8)

1 0 octet faible (adresse paire) (D7-D0)

1 1 aucun octet

12
II.2.1 Connexions de base
GND: se connecter à 0V.

VCC: se connecter à 5V.

MN / MX : se connecter à 5V (mode minimum).

NMI et INTR: se connecter à 0V (pas de support pour les interruptions).

CLK: se connecter à la sortie CLK du générateur d'horloge.

HOLD: se connecter à 0V (pas d'accès direct à la mémoire).

TEST : se connecter à 0V (pas d'attente pour les co-processeur).

READY: se connecter à 5V (pas de cycles d'attente pour les périphériques lents).

RESET: se connecter à zéro de la sortie du générateur d'horloge.

Remarque :
Un système à microprocesseur très simple est composé des parties suivantes:

(1) 8284A Clock Generator (15 MHz Crystal)

(2) 8086 Microprocessor (Minimum Mode)

(3) Bus System (Demultiplexed and Buffered)

(4) Memory System (ROM & RAM Modules)

(5) I/O System (Switches and LEDs)

II.3 Organisation interne du 8086


Le 8086 est constitué de deux unités internes distinctes:

• l’unité d’exécution (EU : Execution Unit) ;


• l’unité d’interface de bus (BIU : Bus Interface Unit).
Le rôle de la BIU est de récupérer et stocker les informations à traiter, et d'établir les
transmissions avec les bus du système. L'EU exécute les instructions qui lui sont transmises par la
BIU.
Pendant que l'EU du 8086/8088 exécute les informations qui
lui sont transmises, l'instruction suivante est chargée dans la BIU. Les instructions qui
suivront sont placées dans une file d'attente. Lorsque l'EU a fini de traiter une instruction la BIU lui
transmet instantanément l'instruction suivante, et charge la troisième instruction en vue de la
transmettre à l'EU. De cette façon, l'EU est continuellement en activité.

13
Figure II.2 : architecture du microprocesseur 8086

Le microprocesseur 8086 contient 14 registres répartis en 4 groupes :


1) Registres de travails : 4 registres sur 16 bits AX, BX, CX et DX.
Chacun de ces registres est de 16-bits de large, mais Ils peuvent être également considérés
comme 8 registres sur 8 bits.
Registre AX : (Accumulateur) : registre de travail principal.
Registre BX : (registre de base) : Il est utilisé pour l'adressage.
Registre CX : (Le compteur) : le registre CX a été fait pour servir comme compteur
lors des instructions de boucle.
Registre DX : On utilise le registre DX pour les opérations de multiplication et de division
et pour contenir le numéro d'un port d'entrée/sortie pour adresser les
interfaces d'E/S.

2) Registres de segments : 4 registres sur 16 bits.


Ils sont employés par la CPU pour déterminer les adresses de segment de mémoire.
Le registre CS (code segment) : Il pointe sur le segment qui contient les codes des
instructions du programme exécutable.
Le registre DS (Data segment) : Le registre segment de données pointe sur la zone
mémoire de données.
Le registre ES (Extra segment) : segment auxiliaire pour données.
Le segment SS (Stack segment) : Le registre SS pointe sur la pile.

14
Remarque : la pile est une zone mémoire ou on peut sauvegarder le contenu des registres, les
adresses ou les données pour les récupérer après l'exécution d'un sous-programme ou l'exécution
d'un programme d'interruption.

3) Registres de pointeurs et d’index : 4 registres sur 16 bits.


Ce sont des registres de 16 bits ils sont utilisés comme pointeurs de mémoire.
L'index SI : (source indexe) : Il est associé au registre DS, il sert aussi pour les instructions
de chaîne de caractères, en effet il pointe sur le caractère source.
L'index DI : (Destination indexe) : Il est associé aux registres (DS ou ES), il sert aussi pour
les instructions de chaîne de caractères, il pointe alors sur la destination.
Les pointeurs SP et BP : ( Stack pointer et base pointer ) :
Ils sont associés au registre SS, Ils pointent sur la zone pile. Pour le registre
BP a un rôle proche de celui de BX, le registre SP Pointe sur la tête de la pile.
Le pointeur IP : Associé au registre CS, il a seulement une fonction qui est d'indiquer la
prochaine instruction à exécuter par le CPU.
4) le registre FLAG : La plupart des instructions arithmétiques et logiques affectent le
registre d'état du processeur (ou registre de FLAG).
C’est un registre de 16 bits. Six des drapeaux sont des indicateurs d'état reflétant les
propriétés du résultat de la dernière instruction arithmétique ou logique.
Trois des indicateurs peuvent être activés ou remis à zéro par le programmeur: (TF, IF, DF).
Flags :

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

CF : indicateur de retenue (carry) ;


PF : indicateur de parité;
AF : indicateur de retenue auxiliaire ;
ZF : indicateur de zéro ;
SF : indicateur de signe ;
TF : indicateur d’exécution pas à pas (trap) ;
IF : indicateur d’autorisation d’interruption ;
DF : indicateur de décrémentation ;
OF : indicateur de dépassement (overflow).

II.4 La segmentation de la mémoire


Le processeur 8086 a un bus d'adresses du bit 20, Ceci permet au processeur d'adresser 220
ou 1,048,576 emplacements mémoire différents (1 Mo).
Puisque les registres du 8086 ne font que 16 bits et avec 16 bits en peut adresser que 64 ko
alors INTEL a proposé de fractionner la mémoire totale adressable de 1 Mo en bloc de 64 ko
appelés segments. On utilise alors deux registres pour adresser une case mémoire (registre de
segment combiné au registre d’offset), on appelle donc une adresse logique :
le couple : segment : offset.
On appelle adresse physique : L’adresse d’une case mémoire donnée sous la forme d’une
quantité sur 20 bits.
Adresse physique = segment x 16+ offset
Exemple : CS : IP = 3F51 : 0021 donc Adresse physique = 3F510 + 0021 = 3F530h.

15
Chapitre 3 : La programmation du microprocesseur 8086

III.1 Généralités
Le programme est une suite d'instructions. Une instruction est un mot binaire décrivant
l'action que doit exécuter le microprocesseur,
Une instruction est définie par son code opératoire, qu’on écrit généralement en hexa, mais
pour une plus grande facilité on les désignera par leurs mnémoniques. Le mnémonique est une
abréviation en caractère latin.
La programmation en assembleur utilise un ensemble d’instructions appelé jeu
d’instructions. Chaque microprocesseur à son propre jeu d’instructions.
Pour les microprocesseurs classiques, le nombre d’instructions reconnues varie entre 75 et
150 (microprocesseurs CISC : Complex Instruction Set Computer). Il existe aussi des
microprocesseurs dont le nombre d’instructions est très réduit (microprocesseurs RISC : Reduced
Instruction Set Computer) : entre 10 et 30 instructions, permettant d’améliorer le temps
d’exécution des programmes.
Les instructions peuvent être classées en groupes :
• instructions de transfert de données ;
• instructions arithmétiques ;
• instructions logiques ;
• instructions de branchement ...

III.2 Les modes d'adressage


La structure la plus générale d’une instruction est la suivante :

Opération à effectuer opérande destination, opérande source

L’opération est réalisée entre les 2 opérandes et le résultat est toujours récupéré dans
l’opérande de gauche.
Il y a aussi des instructions qui agissent sur un seul opérande.
Les opérandes peuvent être des registres, des constantes ou le contenu de cases mémoire, on
appelle ça le mode d’adressage
Les modes d'adressage définissent comment identifier l'opérande de chaque instruction.
Un mode d'adressage spécifie comment calculer l'adresse de la mémoire d'un opérande en
utilisant les informations contenues dans les registres et / ou Les constantes contenues dans
l’instruction.
Il y a plusieurs modes d'adressage dans le 8086:

16
III.2.1 Adressage registre
Ce mode utilise les registres internes de CPU, dans ce mode le CPU transfert d'une copie
d'un octet (8 bits) ou un mot (16 bits) d'un registre (source) vers un autre registre (destination).
Exemples : MOV AX, BX : Copier le contenu de BX dans AX
Notez que le transfert d'un registre 8 bits avec un registre 16 bits est une erreur.

III.2.2 Adressage immédiat


L'adressage immédiat transfère la source, un octet immédiat ou le mot, dans le registre de
destination ou l'emplacement mémoire.
Exemples : ADD AX, 177h : Additionner le registre AX avec le nombre hexadécimal 177.
MOV AX, 'ab': Charger AH par le code ASCII du caractère 'a' et AL par le
code ASCII du caractère 'b'.

III.2.3 Adressage direct


L'adressage direct déménage un octet ou un mot entre un emplacement mémoire et un
registre. L’adresse de la case mémoire ou plus précisément son [Rseg : Offset] est précisé
directement dans l’instruction.
Exemples : MOV AL, [1234H] : Copier le contenu de la mémoire d'adresse DS:1234 dans AL.

III.2.4 Adressage indirect par registre


L'adressage indirect de registre transfère un octet ou un mot entre un registre et un
emplacement mémoire adressés par un intermédiaire (un des 4 registres d’offset BX, BP, SI ou DI).
Exemple : MOV AX, [BX] : transfert de contenu de la case mémoire 16 bits pointé par
DS:BX.
MOV AX, [ES:BP] : Charger AX par le contenu de la mémoire d'adresse ES:BP.
Remarque :
L’adressage indirect est divisé en 3 catégories (l’adressage Basé, l’adressage indexé et
l’adressage basé indexé) selon le registre d’offset utilisé.

III.2.5 Adressage basé


Il utilise les registres de base (BX, BP) comme pointeur. On peut ajouter un déplacement de
registre offset pour déterminer l’offset,
Exemple : MOV AX, [BX] : Charger AX par le contenu de la mémoire d'adresse DS:BX
MOV AX, [BX+1000H] : Charger AX par le contenu de la mémoire d'adresse
DS:BX+1000

III.2.6 Adressage indexé


Le même mode que le basé, mais il utilise les registres d’indexes (SI, DI) comme pointeur.
On peut ajouter un déplacement de registre offset pour déterminer l’offset
Exemple : MOV AX, [SI] : Charger AX par le contenu de la mémoire d'adresse DS:SI
MOV AX, [SI+100] : Charger AX par la mémoire d'adresse DS:SI+100.

17
III.2.7 Adressage basé indexé
C’est un mode combine entre de modes d’adressage comme l’indique son nom.
Exemple : MOV AX, [BP+SI-8] : AX est chargé par la mémoire d'adresse SS:BP+SI-8
MOV AX, [BX+DI+4] : AX est chargé par la mémoire d'adresse DS:BX+DI+4

III.3 Les instructions de transfert


Elles permettent de déplacer des données d’une source vers une destination :
• registre vers mémoire ;
• registre vers registre ;
• mémoire vers registre.
Remarque : le microprocesseur 8086 n’autorise pas les transferts de mémoire vers mémoire (pour
ce faire, il faut passer par un registre intermédiaire).

III.3.1 Instruction MOV


Le format général d'une instruction MOV est : MOV Destination, Source
(MOV Op1, Op2).
L'instruction MOV copie le contenu de l'opérande source dans l'opérande de destination.
La source peut être : Registre, mémoire, valeur immédiate (latérale).
La destination peut être : Registre, mémoire.
Toutes les combinaisons autorisées des deux opérandes sont énumérées ci-dessous:

MOV AX, BX copier un registre dans un autre.


MOV M, AX copier le contenu d’une case mémoire dans un registre.
MOV AX, M copier un registre dans une case mémoire.

MOV AX, 4 copier une constante dans un registre.


MOV taille M, 4 copier une constante dans une case mémoire.
(taille = BYTE ou WORD)

Les actions suivantes ne sont pas autorisées avec l'instruction MOV:


1- Interdit d’utiliser le registre (CS) comme destination.
2- Interdit de lire ou écrire dans le registre (IP).
3- Interdit de copier la valeur d’un registre de segment vers un autre registre de segment, il
faut passer par une case mémoire ou par un registre interne de 16 bits.
4- Interdit de copier une valeur immédiate vers un registre de segment, il faut passer par un
registre interne ou une case mémoire de 16 bits.
5- Interdit de transférer le contenu d’une case mémoire vers une autre, il faut passer par un
registre interne de même taille.

18
III.3.2 Instruction de pile
Les instructions de pile sont des instructions importantes qui stockHQW et récupérHQW des
données à partir de la pile mémoire selon le protocole LIFO (dernier entré, premier sorti).
Le processeur 8086 prend en charge 4 instructions de pile:
PUSH
POP
PUSF (Push Drapeau enregistrer)
POPF (Pop Drapeau enregistrer)

a/ PUSH
Le format général d'une instruction de PUSH est : PUSH opérande
- L'instruction PUSH stocke le contenu de l’opérande Op (16 bits) dans le sommet de Pile
- Décrémente SP de 2

Les opérandes admis de l'instruction PUSH sont:


PUSH AX registre
PUSH word [@] une case mémoire de 16 bits.

Figure III.1 : Fonctionnement de l'instruction PUSH

La figure III.1 montre le fonctionnement de l'instruction PUSH AXDSUpVH[pFXWLRQ.


PUSHF : Empilement de registre FLAG vers le sommet de la PILE.

b/ POP
Le format général d'une instruction POP est : POP opérande.
- L'instruction POP Dépile une valeur de 16 bits depuis le sommet de la Pile (STACK
SEGMENT) et la stocke dans les opérandes (16 bits).
- ,Qcrémente SP de 2

- Les opérandes admis de l'instruction POP sont:


POP AX registre
POP word [@] une case mémoire de 16 bits.

Figure III.2 montre le fonctionnement de l'instruction POP BXDSUpVH[pFXWLRQ.

19
Figure III.2 : Fonctionnement de l'instruction POP

POPF : Dépilement de registre FLAG depuis le sommet de la Pile (STACK SEGMENT).

III.3.3 Instruction XCHG


Le format général de l’instruction XCHG est : XCHG Op1, Op2.
Echange l'opérande Source Op2 avec l'opérande Destination Op1. Impossible sur segment.
XCHG AL, AH
XCHG [@], AH
XCHG AH, [@]

III.4 Les instructions arithmétiques


Avec le 8086 on a les instructions arithmétiques de base : l’addition, la soustraction, la
multiplication et la division. Qui incluent diverses variantes. Plusieurs modes d’adressage sont
possibles. Les opérations peuvent s'effectuer sur des nombres de 8 bits ou de 16 bits signés ou
non signés.

III.4.1 Instruction ADD


La forme générale de l'instruction ADD est : ADD destination, source.
L'instruction ADD Additionne l'opérande source et l'opérande destination avec résultat dans
l'opérande destination, Destination destination + source.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, valeur immédiate.
Toutes les combinaisons autorisées des deux opérandes sont énumérées ci-dessous:
Les FLAGs affectés : CF ; OF; AF ; SF ; ZF ; PF.
Exemple : ADD AX, 4 ADD AX, BX ADD [@], BX ADD AX, [SI]

III.4.2 Instruction ADC


L'instruction ADC Additionne l'opérande source, l'opérande destination et le curry avec
résultat dans l'opérande destination :
ADC Destination, Source ; Destination destination + source + CF.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, valeur immédiate.
Les FLAGs affectés : CF ; OF; AF ; SF ; ZF ; PF.

20
III.4.3 Instruction INC
Incrémentation d’un opérande.
INC Destination ; Destination destination+1.
La destination peut être : registre, mémoire.
Les FLAGs affectés : OF ; AF ; SF ; ZF ; PF
CF reste inchangé
Pour incrémenter une case mémoire, il faut préciser la taille :
INC byte [ ], INC word [ ]

III.4.4 Instruction SUB


La forme générale de l'instruction SUB (Soustraction) est : SUB destination, source.
L'instruction SUB Soustrait l'opérande source et l'opérande destination et place le résultat
dans l'opérande de destination. Destination destination – source.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, valeur immédiate.
Les FLAGs affectés : CF ; OF; AF ; SF ; ZF ; PF.

III.4.5 Instruction SBB


L'instruction SBB fait la soustraction entre deux opérandes avec carry.
SBB Destination, Source ; Destination destination – source – CF.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, valeur immédiate.
Les FLAGs affectés : CF ; OF; AF ; SF ; ZF ; PF.

III.4.6 Instruction DEC


Décrémentation d’un opérande : DEC Destination ; Destination destination – 1.
La destination peut être : registre, mémoire.
Les FLAGs affectés : OF ; AF ; SF ; ZF ; PF.
CF reste inchangé.

III.4.7 Instruction NEG


L’instruction NEG donne le complément à 2 de l'opérande Op : remplace Op par son
négatif : NEG Destination ; Destination Cà2 (destination).
La destination peut être : registre, mémoire.
Les FLAGs affectés : CF ; OF; AF; SF ; ZF; PF.

III.4.8 Instruction CMP


L’instruction CMP fait la comparaison entre deux opérandes et positionne les drapeaux en
fonction du résultat. L’opérande Op1 n’est pas modifié.
CMP Op1, Op2 ; Résultat Op1 – Op2.
Op1 peut être : registre, mémoire.
Op2 peut être : registre, mémoire, valeur immédiate.
Les FLAGs affectés : CF ; OF ; AF ; SF ; ZF ; PF.

21
III.4.9 Instruction MUL
Cette instruction exécute la multiplication entre l’accumulateur et un opérande (non
signé) : MUL Opérande.
Si l’opérande est une valeur sur 8 bits : AX AL * Opérande.
Si l’opérande est une valeur sur 16 bits : DX : AX AX * Opérande.
L'opérande ne peut pas être une donnée, c’est soit un registre soit une position mémoire,
dans ce dernier cas, il faut préciser la taille (byte ou word)
Les FLAGs affectés : CF et OF si la partie haute du résultat est non nulle. La partie haute
est AH pour la multiplication 8 bits et DX pour la multiplication 16 bits
Exemple :
MUL BL ; AL x BL → AX
MUL CX ; AX x CX → DX:AX

III.4.10 Instruction DIV


Cette instruction exécute la Division entre l’accumulateur et un opérande (non signé):
DIV Opérande.
Si l’opérande sur 8 bits : AL AX / Opérande ; AH Reste.
Si l’opérande sur 16 bits : AX (DX : AX) / Opérande ; DX Reste.
L’opérande doit être soit un registre soit une mémoire. Dans le dernier cas il faut préciser la
taille de l’opérande, exemple : DIV byte [adresse] ou DIV word [adresse].
Les FLAGs : CF ; OF ; ZF ; SF ; PF ; et AF sont inconnus (X).

III.4.11 Instructions IMUL et IDIV


La multiplication et la division de l’accumulateur avec un opérande (signé).
Les mêmes syntaxes que MUL et DIV.

III.5 Les instructions logiques


Ce sont des instructions qui permettent de manipuler des données au niveau des bits. Les
opérations logiques de base sont : ET ; OU ; OU exclusif ; décalages et rotations.

III.5.1 Instruction AND


ET logique entre deux opérandes bit à bit : AND Destination, Source ;
Destination destination (ET) source.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, immédiate.
Les FLAGs affectés : ZF ; SF ; PF

III.5.2 Instruction OR
OU logique entre deux opérandes bit à bit : OR Destination, Source ;
Destination destination (OU) source.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, immédiate.
Les FLAGs affectés : ZF ; SF ; PF

22
III.5.3 Instruction XOR
OU Exclusif entre deux opérandes bit à bit : XOR Destination, Source ;
Destination destination (ou exclusif) source.
La destination peut être : registre, mémoire.
La source peut être : registre, mémoire, immédiate.
Les FLAGs affectés : ZF ; SF ; PF
Remarque : Astuces sur les instructions logiques (OR, XOR, AND) :
1. Forçage à 1 : c’est le OR avec un « 1 ».
2. Masquage à 0 : c’est le AND avec un « 0 ».
3. Inverser un bit : c’est le XOR avec un « 1 ».

III.5.4 Instruction TEST


L'instruction TEST effectue l'opération ET.
La différence est que l'instruction AND change l'opérande de destination, alors que
l'instruction TEST positionne uniquement les FLAG.
TEST Op1, Op2 ; Résultat Op1 (ET) Op2.
Op1 peut être : registre, mémoire.
Op2 peut être : registre, mémoire, immédiate.
Les FLAGs affectés : ZF ; SF ; PF

III.5.5 Instruction NOT


Complément à 1 de l’opérande : NOT Destination.
La destination peut être : registre, mémoire.

III.5.6 Instructions de Décalages


Ces instructions déplacent d’un certain nombre de positions les bits d’un mot vers la gauche
ou vers la droite.
Dans les décalages, les bits qui sont déplacés sont remplacés par des zéros. Il y a les
décalages logiques (opérations non signées) et les décalages arithmétiques (opérations
signées).
Le 8086 prend en charge quatre instructions de décalage différentes :

Shift Left

Shift Arithmetic
Left

Shift Right

Shift Arithmetic

Figure III.3 Les instructions de décalage

23
Remarque : Les décalages arithmétiques permettent de conserver le signe. Ils sont utilisés pour
effectuer des opérations arithmétiques comme des multiplications et des divisions par 2.
La forme générale des instructions de décalage est : XXX destination, N
Où: XXX est le mnémonique de décalage (i.e., SHL, SHR, SAL, SAR),
La destination peut être : registre, mémoire et l'opérande N peut être soit une constante
(immédiat) soit le registre CL :
Exemples: SHL AX, 1
SHL AX, CL

III.5.7 Instructions de Rotations


Dans les rotations, les bits déplacés dans un sens sont réinjectés de l’autre côté du mot. Les
quatre opérations de rotation disponibles apparaissent dans la figure suivante :

Rotate Through CF
Left

Rotate Left

Rotate Through CF
Right

Rotate
Right

Figure III.4: instructions de rotation du registre ou de la mémoire indiquant la direction et


le fonctionnement de chaque rotation.

La forme générale des instructions de rotation est : XXX destination, N


Où: XXX est la mnémonique de rotation (i.e., RCL, RCR, ROL, ROR),
Exemples: ROL AX, 1
ROL AX, CL

III.6 Les instructions de branchement


Les instructions de branchement (ou saut) permettent de faire un saut dans le programme, et
exécuter une instruction beaucoup plus éloignée, ou au contraire revenir en arrière. Il existe 3
types de saut :
• saut inconditionnel ;
• sauts conditionnels ;
• appel de sous-programmes.

24
III.6.1 Instruction de saut inconditionnel
JMP label ; Provoque un saut sans condition à la ligne portant l'étiquette label.
Où label est un identificateur d'adresse de programme.

III.6.2 Instructions de sauts conditionnels


Instructions de sauts conditionnels sont conditionnées par l'état des indicateurs (drapeaux)
qui sont eux même positionnés par les instructions précédentes.
Jxxx label où: xxx décrit la condition du saut.

Tableau 1: Liste des instructions de sauts conditionnels du 8086.

Remarque :

- Les termes supérieur et inférieur (above and below) pour les nombres non signés.
- Les termes plus grand et plus petit (greater than and less than) pour les nombres signés.

III.6.3 Instruction CALL


Appel d'une procédure (sous-programme) : CALL nom_ sous-programme
Le CPU fait plusieurs choses quand une instruction CALL est exécutée:
(1) Il ajuste le contenu du registre IP comme s’il va exécuter l'instruction suivante.

25
(2) Il stocke le contenu du registre IP dans la pile de programme.
(3) On ajuste le contenu du registre d'IP de nouveau pour pointer sur la première instruction
de la procédure appelée.
L’unité centrale continue à exécuter les instructions jusqu'à ce qu'elle rencontre une
instruction RET.

III.6.4 Instruction RET


Un RET (Return) instruction de retour de sous-programme : RET
Quand le CPU rencontre une instruction RET, il effectue les actions suivantes :
(1) Il récupère le contenu du registre IP stocké dans la pile de programme par l'instruction
CALL.
(2) Il met la valeur restaurée dans le registre IP et continue l'exécution.
Le CPU revient à l’état où il était lorsque l'instruction CALL a été rencontrée.

III.6.5 Instructions des interruptions


INT n: Appel à l’interruption logicielle n° n
IRET : Cette instruction termine un sous-programme de traitement d’une
interruption.

III.6.6 Instruction de boucles LOOP


L'instruction LOOP décrémente le contenu de CX et provoque un saut relatif court si ce
dernier n’est pas nul.
La forme générale d'une instruction de boucle est : LOOP label
Où label est un identificateur d'adresse de programme.
L'instruction LOOP est équivalente au deux instructions :
DEC CX
JNZ label
La diférence entre les deux instructions ci-dessus et de l'instruction LOOP est que cette
dernière, n'affecte pas les états des flags.
Le 8086 à 4 variations de l'instruction LOOP:
LOOPZ (Loop While Zero) ou LOOPE (Loop While Equal) : si le flag ZF=1 et si CX ≠ 0.
LOOPNZ (Loop While Not Zero) ou LOOPNE (Loop While Not Equal) : si le flag ZF=0
et si CX ≠ 0.
Ces variations permettent le déroulement du programme pour deux conditions (le registre
CX et le drapeau zéro (ZF) en même temps).

III.7 Les instructions de manipulation de chaines


Dans le Cpu 8086 on a 5 instructions de manipulation de chaînes :
MOVS, LODS, STOS sont des instructions de transfert, elles peuvent être répétées à l'aide du
préfixe REP
CMPS et SCAS sont des instructions de comparaisons, elles peuvent être répétées à l'aide du
préfixe REPZ

Remarque : Chacune des instructions existe en deux versions, entre deux octets, ou entre 2
words, le préfixe REP pour les instructions de transfert MOVS LODS STOS, Ce préfixe utilise
le registre CX comme un compteur de répétition.

26
Les préfixes REPE et REPZ : Répétition des instructions de comparaisons SCAS et CMPS
tant que ZF=1 et CX≠0.
Les préfixes REPNE et REPNZ : Répétition des instructions de comparaisons SCAS et
CMPS tant que ZF=0 et CX≠0.
Ces instructions sont utilisées sans opérandes. les registres utilisés sont : pour la source
DS:SI, et pour la destination ES:DI. A chaque exécution d’une instruction de traitement de
chaîne, les registres d’indexes sont incrémentés ou décrémentés selon le flag DF de registre
d’état.
* DF = 0 : SI et DI sont incrémentés, (l’instruction CLD mit (DF = 0))
* DF = 1 : SI et DI sont décrémentés. (l’ instruction STD mit (DF = 1))
SI et DI sont incrémentés de 1 ou de 2 selon que l'opération s'effectue sur un octet
(byte) ou sur un mot de 16 bits (word).

MOVSB : Copie Le contenu d’un octet de mémoire DS: [SI] dans un octet de mémoire
ES: [DI], puis auto inc/decrémente les registres SI et DI.

MOVSW : Copie Le contenu du mot de mémoire DS: [SI] dans le mot de mémoire ES:
[DI], puis auto inc/decrémente de 2 les registres SI et DI

LODSB : Copie l'octet source DS: [SI] dans AL puis inc/décr le registre SI.

LODSW : Copie le mot source DS: [SI] dans AX puis inc/décr de 2 le registre SI.

STOSB : Copie AL dans l’octet destination ES: [DI] et inc/décr le registre DI.

STOSW : Copie AX dans le mot destination ES: [DI] et inc/décr de 2 le registre DI.

CMPSB : Compare l'octet source ES : [DI] avec l'octet destination DS: [SI], positionne
les indicateurs puis inc/décrémente les registres SI et DI.

CMPSW : Compare le mot source ES : [DI] avec mot destination DS: [SI], positionne
les indicateurs puis inc/décrémente de 2 les registres SI et DI

SCASB : Compare AL avec l'octet destination ES : [DI], positionne les indicateurs


puis inc/décr le registre DI.

SCASW : Compare AX avec le mot destination ES : [DI], positionne les indicateurs


puis inc/décr le registre DI de 2.

27
Chapitre 4 : Interfaçage du microprocesseur 8086

Un système à microprocesseur très simple est composé des parties suivantes:


(1) Microprocesseur 8086 (Minimum Mode)
(2) Générateur d’horloge 8284A (15 MHz Crystal)
(3) Bus système (Demultiplexed and Buffered)
(4) Mémoire système (ROM & RAM)
(5) I/O système (Switches and LEDs)

IV.1 Microprocesseur 8086 (Minimum Mode)


Le 8086 a Deux modes de fonctionnement :
Mode minimum (MN/MX = 1): Ce mode permet de diminuer le nombre de circuits
extérieurs pour les systèmes à processeur unique. Le processeur prend en charge la gestion des
bus.
Mode maximum (MN/MX = 0) : ces signaux de commande sont produits par un
contrôleur de bus, le 8288. Ce mode permet de réaliser des systèmes multiprocesseurs.

IV.2 Générateur d’horloge


Le 8284A est un circuit intégré conçu spécialement pour les microprocesseurs 8086/8088.
Ce circuit fournit les fonctions ou les signaux de bases suivantes: génération d'horloge, RESET,
READY.

Figure IV.1 : Interfaçage du 8284 avec le 8086

IV.3 Bus système (Demultiplexed and Buffered)


Avant d’utiliser le microprocesseur 8086 avec les mémoires ou les interfaces E /S, les pines
multiplexé (adresse /données et d'adresses/lignes d'état) doivent être démultiplexes. Il faut aussi
amplifier le courant fourni par ces lignes pour pouvoir commander d'autres composants dans le
système.
Le démultiplexage des signaux AD0 à AD15 (ouA16/S3 à A19/S6) sefait à l’aide d’un
verrou (latch), ensemble de bascules D. cet événement est indiqué par le signal ALE.
Circuit de demultiplexage A/D:
Exemples de bascules D: circuits 8282, 74373, 74573.

28
Figure IV.2 : bascules D circuits 8282

Si plus de 10 composants sont attachés aux broches de bus, l'ensemble du système 8086 doit
être amplifié. Les broches démultiplexés (adresse bus A19-A0 et BHE) sont déjà
amplifiées par les verrous (latch). Donc, il faut amplifier le bus de données D15 - D0. Le bus de
données est bidirectionnel, nous devons utiliser des tampons (buffers) bidirectionnels :
Exemples de tampons de bus : circuits transmetteurs bidirectionnels 8286 ou 74245 :

Figure IV.3 : circuits transmetteurs bidirectionnels 8286

Remarque : Les signaux de bus de contrôle (M/IO, RD et WR) les signaux de bus de
contrôle sont des signaux unidirectionnels. Par conséquent, nous avons besoin d'utiliser des
tampons unidirectionnels tels que le buffer 74LS244.
La figure suivante montre la conception de bus système de μp 8086

29
Figure IV.4 : conception de bus système de μp 8086

IV.4 Mémoire système (ROM & RAM)


Le microprocesseur 8086 à 20 bits d'adresses (A19 - A0) donc un espace mémoire D’une
capacité de 1 Mo.
Par conséquent, le micro-processeur 8086 nécessite que cet espace mémoire soit organisé en
deux banques (512 Ko chacune) appelées les banques paires et impaires.
La partie paire est connectée au bus de données D0/D7, et la partie impaire est connectée au
bus D8/D15. Ces deux banques sont sélectionnées par A0 est BHE.
Puisque le 8086 a un espace mémoire D’une capacité de 1 Mo. D’où la possibilité d’avoir
jusqu’à 8 blocs mémoire de 128Ko chacun.
Si on va utiliser deux boitiers mémoire RAM de 64 ko chacun. Donc on a 16 lignes
6 10 16
d'adresse (64K =2 x 2 = 2 ).

30
Le 8086 sera interfacé à la RAM comme suit:
Les lignes d'adresse les moins significatives A16-A1 sont utilisées pour adresser des
emplacements de mémoire dans la RAM.
Les lignes d'adresse les plus significatives A19-A17 sont utilisées pour sélectionner la plage
d'adresses nécessaires dans l'espace de mémoire de 8086 (sélectionner les deux boitiers RAM),
comme sur figure.

Décodage Adressage

Figure IV.5 : interfaçage de la mémoire.

Remarque : Le microprocesseur 8086 fournit trois signaux de commande RD, WR et M / IO qui


peuvent être décodés comme représentés sur la figure suivante : les signaux (MEMR, MEMW, IOR
et IOW).

31
Figure IV.6 : décodage signaux lecture et écriture mémoire et I/O.

IV.5 E/S système (Switches and LEDs)


Les ports d’E/S sont utilisés pour l’échange de données entre le μp et un périphérique.
Un port d’E/S est similaire à un emplacement mémoire sauf que chaque port doit avoir sa propre
adresse.
Avec les processeurs 80x86, on a 16 lignes d’adresse pour le port d’E/S avec une taille 64Ko.
Il existe deux méthodes différentes d’interface d’E/S à microprocesseur 8086:
E / S isolé (adresse cartographique) ;
E / S Mappé en mémoire (adresse cartographique).

IV.5.1 Adresse cartographique


Les adresses des ports d’E/S appartiennent au même
espace mémoire que les circuits mémoires (Les adresses des
ports d’E/S appartiennent au même espace mémoire que les
circuits mémoires (on dit que les E/S sont mappées en
mémoire)

IV.5.2 Adressage indépendant


Le microprocesseur considère deux espaces
distincts :
 L’espace d’adressage des mémoires
 L’espace d’adressage des ports d’E/S

32
Tableau IV.1: Comparaison entre Adressage cartographique et indépendant

Adresse cartographique Adressage indépendant


• l’espace d’adressage des mémoires diminue • contrairement à l’adressage
• l’adressage des ports d’E/S se fait avec une cartographique, l’espace mémoire total
adresse de même longueur que pour les cases adressable n’est pas diminué
mémoires • l’adressage des ports d’E/S peut se faire
• toutes les instructions employées avec des cases avec une adresse plus courte que les circuits
mémoires peuvent être appliquées aux ports mémoires
d’E/S. • les instructions utilisées pour l’accès à la
• Les mêmes instructions permettent de lire et mémoire ne sont plus utilisables pour
écrire dans la mémoire et les ports d’E/S, tous les l’accès aux ports d’E/S, ceux-ci disposent
modes d’adressages étant valables pour les E/S d’instructions spécifiques

Remarque : la mémoire et les ports I/O partage le même bus de données et d’adresse, c’est Le
signal M/IO qui permet de différencier l’adressage de la mémoire de l’adressage des ports E/S :
• pour un accès à la mémoire, M/IO = 1;
• pour un accès aux ports d’E/S, M/IO = 0.

Les instructions utilisées pour R/W d’un port sont « IN / OUT ». Il existe deux types
d’accès, accès direct et un autre indirect. Les registres utilisés sont l’accumulateur « AL / AX » et le
registre de données « DX ». Les instructions directes d'E / S fournissent l'adresse de port (qui doit
être un nombre compris entre 0 et FFh).
Si l’adresse du port d’E/S est sur un octet:

Lecture d’un port d’E/S Ecriture d’un port d’E/S


IN AL, @: lecture d’un port sur 8 bits OUT @, AL: écriture d’un port sur 8 bits
IN AX, @: lecture d’un port sur 16 bits OUT @, AX: écriture d’un port sur 16 bits

Pour accéder à la plage complète des ports d'E/S de 0000H à FFFFH, les instructions
indirectes d'E / S doivent être utilisées.
Pour ces instructions, le registre DX doit être préchargé avec l'adresse du port.
• si l’adresse du port d’E/S est sur deux octets:

Lecture d’un port d’E/S Ecriture d’un port d’E/S


IN AL, DX : lecture d’un port sur 8 bits OUT DX, AL : écriture d’un port sur 8 bits
IN AX, DX : lecture d’un port sur 16 bits OUT DX, AX: écriture d’un port sur16 bits

Où le registre DX contient l’adresse du port d’E/S à : lire / écrire.

33
Chapitre 5 : Les interfaces d’entrées/sorties

V.1 Définition
Une interface d'entrées/sorties est un circuit permettant au Cpu de communiquer avec
l'environnement extérieur (périphérique) : clavier, écran, imprimante, processus industriel etc...
Les interfaces d'E/S sont connectées au microprocesseur à travers les bus d'adresses de
données et de commandes.
Un circuit d’E/S possède des registres pour gérer les échanges avec les périphériques :
• Registre de configuration
• Registre de données
A chaque registre est assignée une adresse : le microprocesseur accède à un port d’E/S en
spécifiant l’adresse de l’un de ses registres.
Intel a développé plusieurs circuits intégré de contrôle de périphérique conçus pour soutenir
la famille de processeurs 80x86 tels que:
Le 8255A Programmable Peripheral Interface (PPI),
Le 8259 Programmable Interrupt Controller (PIC),
Le 8253/54 Programmable Interval Timer (PIT),
Le 8237 Programmable DMA Controller.

V.2 L’interface parallèle 8255


Le rôle d’une interface parallèle est de transférer des données du microprocesseur vers un
périphérique et l’inverse en parallèle. Le 8255 est une interface parallèle programmable, elle peut
être configurée en entrée et/ou en sortie par programme.
Le 8255 fournit 24 lignes d’E/S qui peuvent être organisées en trois ports d’E/S (A, B, et C)
de 8 bits chacun. De plus le8255 peut fonctionner selon 3 modes: mode 0, mode1 ou mode2.

Figure V.1: configuration des broches du 8255

34
Tableau V.1: Sélection des ports de 8255

Figure V.2: Schéma fonctionnel du 8255

35
Figure V.3: Structure du registre de commande

La figure précédente montre le fonctionnement du PPI 8255 :


(a) Lorsque le bit 7 = 0, mise à « 1 » ou « 0 » d’une ligne du PORTC individuellement.
(b) Lorsque le bit 7 = 1, l'un des modes 0, 1, ou 2 peuvent être programmés.

Mode 0 (E/ S de base): Ports A et B


fonctionnent comme entrées ou sorties. Le port C
est divisé en deux groupes de 4 bits qui peuvent
être configurés comme entrées ou sorties.
Mode 1 : Il est utilisé pour le dialogue avec
des périphériques nécessitant un asservissement
(contrôle).Ports A et B fonctionnent comme des
entrées ou sorties comme en mode 0. Port C est
utilisé pour le contrôle.
Mode 2: le port A est bidirectionnel (entrée
et sortie).
Port C est utilisé comme signaux du contrôle. Port
B n’est pas utilisé.
Remarque : Ces modes peuvent aussi être
mélangés. Par exemple, le port A peut être
programmé pour fonctionner en mode 2, tandis
que le port B fonctionne en mode 0.
Figure V.4 : Les trois modes de base du 8255

36
V.2.1 Interfaçage de 8086 avec le 8255
On peut connecter le bus de données du
8255 sur les lignes de données de poids faible
du 8086 (D0 - D7) ou sur celles de poids fort
(D8 - D15).
Donc l’un des deux signaux A0 ou
BHE doit être utilise pour sélectionner le 8255
alors les adresses des registres du 8255 se
trouvent à des adresses paires (validation par
A0) ou impaires (validation par BHE).
Exemple :

A15-A12 A11-A8 A7-A4 A2 A1 A0


0000 0000 0000 0 0 0
0000 0000 0000 0 1 0
0000 0000 0000 1 0 0
0000 0000 0000 1 1 0

Chip Select (CS) Sélection adresses


de port paires

V.3 Le 8279
Intel 8279 est un circuit intégré d'interface programmable clavier / l'écran :
Scans et encode jusqu'à un clavier de 64-clé.
Contrôle jusqu'à un affichage numérique de 16 chiffres.
La Section Clavier possède une mémoire tampon de 8 caractères FIFO intégrée.
L'affichage est commandé à partir d'une RAM interne 16x8 qui mémorise les informations
d'affichage codées.

Figure V.5 : (a) Schéma fonctionnel et (b) brochage du 8279.

37
Figure V.6: Interface du 8279 (Un clavier Hexa et afficheur 7 segments) avec le 8086.

V.4 L’interface série 8250


L’interface entrées/sorties permet d´échanger des données entre le microprocesseur et un
périphérique soit d’une manière parallèle (un mot de 8 bits) ou d’une maniéré série (bit par bit).
Mais sur des distances supérieures à quelques mètres, il est difficile de mettre en œuvre une
transmission en parallèle. On utilise alors une liaison série.
Le circuit intégré 8250 est le composant chargé de la gestion des transmissions séries
asynchrones il est appelé UART (Universal Asynchronous Receiver Transmitter).
Il existe deux types de transmissions séries:
• synchrone: les octets successifs sont transmis par blocs séparés par des octets de
synchronisation.
• asynchrone : chaque octet peut être émis ou reçu sans durée déterminée entre un octet et le
suivant ;

Figure V.7: Protocole de transmission de données asynchrone

• dans le protocole de transmission de données on a que deux états significatifs : 0 (ou low),

38
et 1 (ou high). Quand on ne transmet rien, la ligne est à l'état high (tension négative). Comme le
montre la figure V.7,
• Le bit de Start permettra au récepteur de savoir que des données vont être transmises;
• Les bits de données sont transmis l’un après l’autre en commençant par le bit de poids
faible. Ils peuvent être au nombre de 5, 6, 7 ou 8.
• Le bit de parité est un bit supplémentaire dont la valeur dépend du nombre de bits de
données égaux à 1. Il est utilisé pour la détection d’erreurs de transmission ;
• Les bits de stop (1, 1.5 ou 2) marquent la fin de la transmission du caractère.

V.4.1 Structure de l’UART

Figure V.8: Structure de l’UART

L'UART est conçue pour gérer les signaux en provenance d'un modem. Aussi est-il
nécessaire de donner quelles broches sont utilisées par
l'ETCD (Equipement Terminal de Communication de
Données).
signal Signification
TxD Transmit Data
RxD Receive Data
RTS Request To Send
CTS Clear To Send
DTR Data Terminal Ready
DSR Data Set Ready
DCD Data Carrier Detect
RI Ring Indicator

Figure V.9 : Brochage du 8250

Les 2 signaux TxD et RxD servent à transmettre les données. Les autres signaux sont des
signaux de contrôle de l’échange de données.

39
Figure V.10 : Bornes du circuit UART 8250.

V.4.2 Les registres du 8250


L’interface 8250 possède plus de 8 registres de 8 bits permettant de gérer la communication.
Ces registres sont lus et modifiés par le processeur par le biais des instructions IN et OUT vues plus
haut.
Comme on ne dispose que de 3 bits d’adresse :
(A0, A1 et A2), plusieurs registres doivent se partager la même adresse La solution est
d’utiliser un bit d’un registre spécial, DLAB.
En fonction de l’état de DLAB (Divisor Latch Access Bit), on a accès soit au registre
d’émission / réception, soit au diviseur d’horloge, soit au masque d’interruptions.

Dans ce cours on ne va pas étudier le fonctionnement du 8250 ni sa programmation car


d’habitude elle n’est pas utilisée d’une façon individuelle mais elle fait partie du système de
communication.

40
Chapitre 6 : Les interruptions

VI.1 Définition d’une interruption


Dans un système à microprocesseur pour dialoguer avec ces périphériques le
microprocesseur a deux façons de communiquer avec ces derniers :
- polling (scrutation périodique) : En questionnant de façon continue le périphérique
pour vérifier que des données peuvent être lues ou écrites. Cela permettra de limiter les tâches qui
pourraient être accomplies par le micro-ordinateur.
- interruption : En l'interrompant lorsqu' un périphérique est prêt à lire ou écrire des
données, avec une demande d’interruption (IRQ : Interrupt Request).
En utilisant cette technique, le processeur peut passer la plupart de son temps à d'autres
tâches, et n’exécute une lecture des ports d’E/S que lorsqu’ une donnée est disponible.
Le processeur 8086 reçoit les interruptions de trois sources différentes:
(1) interruptions processeur : c’est le processeur lui-même qui les génère, en
raison d'un défaut interne (par exemple, une tentative de diviser par zéro)
(2) L'interruption logicielle : à l'aide de l’instruction INT n (couramment utilisée
dans le PC pour accéder au BIOS et fonctions DOS),
(3) interruptions matérielles : produites par l’activation des lignes INTR et NMI
du microprocesseur.
A la suite d’une demande d’interruption par un périphérique :
• le microprocesseur termine l’exécution de l’instruction en cours ;
• il range le contenu des principaux registres sur la pile de sauvegarde : CS : IP, flags, ...
• il émet un accusé de réception de demande d’interruption (Interrupt Acknowledge)
indiquant au circuit d’E/S que la demande d’interruption est acceptée.
• il abandonne l’exécution du programme en cours et va exécuter un sous-programme de
service de l’interruption (ISR : Interrupt Service Routine) ;
• il termine l’exécution de l’ISR avec l'instruction lRET (retour d'interruption).
• les registres sont récupérés à partir de la pile et le microprocesseur reprend l’exécution du
programme qu’il avait abandonné.
Le processeur 8086 a seulement 2 broches interruption matérielle: INM ; INTR.
- NMI (interruption non masquable) : Elle ne peut pas être bloquée; le processeur doit
répondre. Pour cette raison l'entrée NMI est habituellement réservée pour les fonctions
critiques du système.
- INTR (Interruption) : Elle est masquable via le drapeau IF.
Pour (8086), l'adresse de la routine de service d'interruption est stockée dans 4
emplacements de mémoire consécutifs (un double-mot) dans une table de vecteur d'interruption
commençant à l'adresse 00000h.
Remarque : adresse vecteur d’interruption = 4 × type de l’interruption
Exemple : interruption 10H, adresse du vecteur = 4 × 10H = 40H.

41
VI.2 Le contrôleur programmable d’interruptions 8259

Le microprocesseur 8086 ne dispose que de deux lignes de demandes d’interruptions


matérielles (NMI et INTR). Pour pouvoir connecter plusieurs périphériques utilisant des
interruptions, on peut utiliser le contrôleur programmable d’interruptions.
Un contrôleur d'interruption programmable (PIC) fonctionne comme un directeur général
dans un environnement de système commandé par interruption.
Il accepte les demandes provenant de l'équipement périphérique, détermine laquelle des
demandes entrantes est de la plus haute importance (priorité), vérifie si la demande entrante a une
valeur de priorité plus élevée que le niveau en cours d’exécution et émet une interruption vers le
processeur sur la base de cette détermination.

Exemple : le rôle de PIC 8259 :


• recevoir des demandes d’interruptions des périphériques ;
• résoudre les priorités des interruptions ;
• générer le signal INTR pour le 8086 ;
• émettre le numéro de l’interruption sur le bus de données.

Le 8259A peut gérer jusqu’à 8 demandes d’interruptions matérielles. Il est programmé par le
logiciel du système comme un périphérique d'E / S.
Une sélection de modes de priorité est disponible pour le programmeur de sorte que la
manière dont les demandes sont traitées par le 8259A peut être configurée pour correspondre à ses
besoins du système.
Les modes de priorité peuvent être modifiés ou reconfigurés dynamiquement à tout moment
pendant le programme principal. Cela signifie que la structure d'interruption complète peut être
définie selon les besoins.

42
VI.3 Brochage du 8259 :

Figure VI.1 : Brochage et Schéema fonctionnel du 8259 .

Exemple : interfaçage de 8259 avec le 8086 :

Figure VI.2 : interfaçage de 8259 avec le 8086 .

Remarque : si le nombre de demandes d’interruptions est supérieur à 8, on peut placer plusieurs


8259 en cascade.

43
VI.3 Le temporisateur programmable 8253/8254
On peut facilement exécuter une boucle de temporisation mais lorsque le microprocesseur
exécute la temporisation il ne peut plus rien faire d’autre. Pour cela on fait appel à un circuit
spécialisé c’est le PROGRAMMABLE TIMER.
Le 8253 programmable interval timer/counter est spécialement conçu pour les circuits
d’Intel. Le programmeur configure le 8253 pour correspondre à ses besoins, initialise un des
compteurs du 8253 avec la quantité désirée, puis avec le mot de commande le 8253 prendra en
charge la temporisation et signalera la fin d’exécution avec une interruption du CPU.

Figure VI.3 : Schéma fonctionnel et les descriptions des broches du 8254.

Il y a trois registres de comptage de 16 bits, dont chacun peut être programmé comme un
timer ou un compteur d'événements. Plus un registre de commande qui peut ne peut-être qu’écrit.
L’accès aux registres du 8254 s’effectue de la façon suivante :
Tableau VI.1: Description des opérations de base

CS RD WR A1 A0 fonction

0 1 0 0 0 Chargement compteur 0
0 1 0 0 1 Chargement compteur 1
0 1 0 1 0 Chargement compteur 2
0 1 0 1 1 Ecriture mot de mode
0 0 1 0 0 Lecture compteur 0
0 0 1 0 1 Lecture compteur 1
0 0 1 1 0 Lecture compteur 2
0 0 1 1 1 Etat de haute impédance
1 X X X X
0 1 1 X X

44
Table VI.2: Pin description of the 8254.

La programmation du 8254 se fait par l’envoi d’un mot de commande dans le registre de
commande CR. Les bits 6 et 7 de ce mot de commande permettent de l’affecter à l’un des trois
compteurs. Le format du mot de commande est le suivant :

45
On remarque que chaque compteur peut être utilisé selon l’un des 6 modes possibles :
Mode 0 :
Il Permet au 8254 d’être utilisé comme un compteur ou temporisateur. Dans ce mode, la
sortie est au niveau logique 0 Lorsque le décomptage atteint 0, la sortie passe au niveau 1. On
notera que l'entrée GATE doit être un 1 logique pour permettre au compteur de compter. Si G
devient 0 au milieu du comptage, le compteur s’arrête jusqu'à ce que G redevient 1.

Mode 1 :
Le 8254 à la fonction comme un monostable redéclenchable. Un front montant sur la
gâchette GATE déclenche le décompte au top d’horloge qui suit. Alors la sortie passe à 0 et s’y
maintient jusqu’à ce que le décompte arrive à 0. Chaque front montant sur GATE relance le
processus à partir du compte initial (si celui- ci n’a pas été modifié).
Mode 2 :
C’est le mode diviseur par n il permet au 8254 de générer une série d'impulsions continues.
La séparation entre les impulsions est déterminée par le comptage. Par exemple, pour un compte de
10, la sortie est un état logique 1 pendant neuf périodes d'horloge et 0 pour une période d'horloge.
Ce cycle est répété jusqu'à ce que le compteur est programmé avec un nouveau comptage ou jusqu'à
ce que l’entrée G est placée à un niveau logique 0. L'entrée G doit être un 1 logique pour ce mode
pour générer une série continue d'impulsions.
Mode 3:
Ce mode est similaire au mode 2 sauf que OUT passe au niveau bas lorsque la moitié du
compte initial est atteinte, soit N/2, et reste dans cet état jusqu’à ce que le compte arrive à 0 et le
cycle recommence. Comme pour le mode 2, un niveau 1 sur GATE valide le décompte et un niveau
0 l’inhibe alors qu’un front montant le réinitialise. De ce fait, une valeur impaire amène (N+l)/2
avec sorties au niveau haut et (N-1)/2 au niveau bas.
Mode 4:
Ce mode est similaire au mode 0 sauf que OUT est au niveau haut pendant le décomptage et
produit une seule impulsion négative lorsque le compte devient nul.
Mode 5:
Ce mode est similaire au mode 4. Cependant il est démarré par une impulsion de
déclenchement sur la broche G au lieu par le programme. Ce mode est également similaire au mode
1, car il est redéclenchable.

46
Figure VI.4 : Les six modes de fonctionnement pour le 8254. L'entrée de G = 0 arrête le
compteur en mode 2, 3, et 4.

47
VI.4 DMA (Accès Direct à la Mémoire)
Précédemment, nous avons discuté d'E / S de base et de traitement d’interruption.
Maintenant, nous nous tournons vers la forme finale d'E / S appelé accès direct à la mémoire
(DMA). La technique DMA offre l’accès directe à la mémoire pendant que le microprocesseur est
temporairement désactivé. Ceci permet aux données d'être transférées entre la mémoire et le
dispositif d'E / S à une vitesse qui est limitée uniquement par la vitesse des composants de
mémoire dans le système ou le dispositif de commande DMA. Les transferts DMA sont utilisés à de
nombreuses fins, mais plus fréquents comme pour, transfert de données entre la mémoire et le
disque dur, transfert de données vers la carte graphique ou la carte de son, etc.
On utilise pour cela le contrôleur de DMA un circuit intégré qui gère le transfert par DMA,
lors de l’initialisation d’un transfert par DMA, le contrôleur de DMA négocie l’accès au bus de
données avec le microprocesseur via les deux broches HRQ et HLDA du microprocesseur :
– Le cycle commence avec la requête du périphérique via une entrée DREQ (pour Dma
REQuest) du DMAC.
– Le DMAC positionne alors l’entrée HOLD du 8086 à niveau haut, requérant ainsi que le
microprocesseur entre dans un état HOLD qui laisse la main au DMAC.
– Le microprocesseur répond en terminant le cycle de bus en cours (s’il y en a un) et met ses
adresses, données et la plupart des contrôles en position ouverte (haute impédance). La broche
HLDA (pour HOLD Acknowledge) est positionnée au niveau haut par le microprocesseur pour
accuser réception de la requête.
Dans un système avec des tampons de bus d’adresse, de données et de contrôle, HDLA est
utilisé pour désactiver ces tampons de façon à ce que le microprocesseur soit complétement
déconnecté de la mémoire et des entrées-sorties.
– Lorsqu’il reçoit HDLA, le DMAC applique DACK (pour Dma ACknowledge) au
périphérique requérant le service. Le DMAC contrôle alors le système, fournissant les signaux de
bus d’adresse et de contrôle comme si il était le microprocesseur (ce qu’il est réellement).
– Tant que le DMAC utilise les bus pour des transferts, le microprocesseur est inactif (et
réciproquement, lorsque le microprocesseur est actif, le DMAC est inactif). Lorsque le DMAC a
terminé son travail, il met HOLD à un niveau bas de façon à ce que le microprocesseur reprenne la
main.

VI.5 Le 8237
Intel a conçu le DMAC 8237 pour être associé au microprocesseur 8080. Il est également
utilisé pour les microprocesseurs 8085 et 8086/88. Le 8237 est en fait un microprocesseur à usage
spécial dont le travail est le transfert de données à grande vitesse entre la mémoire et les E / S. la
Figure suivante montre le brochage et le diagramme du contrôleur de DMA programmable 8237.
Le 8237 a quatre canaux pour transférer les données, c’est-à-dire qu’il peut être relié à
quatre périphériques. Bien entendu, à un instant donné, un seul périphérique peut utiliser le DMAC
pour transférer des données.
A chaque canal est associé deux signaux : DREQ et DACK. Il y a un seul signal HOLD et
un seul signal HLDA, ce qui signifie que les quatre canaux utilisent les mêmes bus système, mais le
DMAC décide quel périphérique doit prendre le contrôle à partir d’un registre des priorités qui peut
être programmé.

48
Figure VI.5 : (a) Schéma fonctionnel et (b) brochage du contrôleur DMA programmable
8237.

On ne va pas aller plus loin dans l’étude du contrôleur DMA programmable 8237 car il est
rarement utilisé d’une façon individuelle.

49
Bibliographie

[1] Brey, Barry B. The Intel microprocessors 8086/8088, 80186/80188, 80286, 80386, 80486,
Pentium, Pentium Pro processor, Pentium II, Pentium III, Pentium 4, and Core2 with 64-
bit extensions: architecture, programming, and interfacing ;8th ed; Pearson Prentice Hall ;
2009.
[2] D.a.godse A.p.godse. Microprocessors and Interfacing; first edition ; technical publications
pune ; 2009 .
[3] M.aumiaux . Les systèmes à microprocesseurs ; 2eme edition ; masson ; 1982.
[4] Intel The 8086 Family; Users Manual ; 1979.
[5] Dr J.Y. Haggége. MICROPROCESSEUR ; (cours Institut Supérieur des études
Technologiques de Radés) ; 2003
[6] A. Oumnad. MICROPROCESSEURS DE LA FAMILLE 8086.
[7] www.chipdocs.com
[8] www.datasheetcatalog.com

50
Chapitre 3 : Ports et registres Microcontrôleur AVR ATmega16 / ATmega32

Introduction

 L'AVR ATmega16/32 à 32 broches constituant quatre ports. Les ports


sont énumérés ci-dessous:

PORT A , PORT B, PORT C, PORT D.

 Chaque port a 8 broches.


 Les broches de ces quatre ports peuvent être utilisées comme
entrées / sorties à usage général.
 Ces broches peuvent être configurées en entrée ou en sortie à l'aide des trois registres
d'E / S de chaque port :

1. DDRx Register: ils sont utilisés pour décider de la direction des broches, (broches
d’entrées ou broches de sortie ).
2. PINx: Ils sont utilisés pour lire le niveau logique sur les ports.
3. PORTx registers: ils servent à définir la logique sur les broches HIGH ou LOW.
(Où x peut être A, B, C ou D en fonction des registres de ports à adresser).

 Chaque broche est également associée à une fonctionnalité spéciale.


Registres de ports E / S :
Trois registres d'E / S sont associés à chaque port :

DDRx : Registres de direction de données

 Ce sont des registres 8 bits.


 Ceux-ci sont utilisés pour configurer les broches des ports en entrée ou en sortie.
 L'écriture d'un 1 dans les bits de ce registre définit ces broches comme sortie.
 L'écriture d'un zéro sur les bits de ce registre définit ces broches comme des entrées.
 Tous les bits de ces registres peuvent être lus et écrits.
 La valeur initiale de ces bits est zéro.

Exemple :

 Définition du port D comme port de sortie: DDRD = 0xFF;

L'écriture 1 sur les bits de ce registre configure les broches correspondant à ces broches
en tant que broches de sortie.

Ici, nous avons configuré les 8 broches du port D en tant que broches de sortie en
écrivant 1 sur chacune d’elles. (0xFF = 0b11111111).

 Définition du port D comme port d’entrée: DDRD = 0x00;


L'écriture de 0 sur les bits de ce registre configure les broches correspondant à ces
broches en tant que broches de sortie.
Ici, nous avons configuré les 8 broches du port D en tant que broches d’entrée en écrivant
0 sur chacune d’elles. (0x00 = 0b00000000).

PORTx : registres de données

 Ce sont des registres 8 bits.


 Ceux-ci sont utilisés pour placer les broches des ports dans l'état logique haut ou bas.
 Écrire un 1 dans ce registre met une logique HIGH (5V) sur ces broches.
 Tandis que l'écriture d'un zéro dans les bits de ce registre place une logique BASSE (0V)
sur ces broches.
 Tous les bits de ces registres peuvent être lus et écrits.
 La valeur initiale de ces bits est zéro.

Exemple:

Nous allons utiliser le registre PORTx du port D pour écrire une valeur 0x55 sur le port D.
PORTD = 0x55;
PINx: Registres d'adresses des broches d' entrée

 Ce sont des registres 8 bits.


 Ils sont utilisés pour lire les valeurs sur les broches spécifiques du port.
 Ces bits sont en lecture seule et ne peuvent pas être écrits.

Exemple:

Nous lirons la valeur sur le port D dans une variable de 8 bits nommée 'valeur_port'.
valeur_port = PIND;

Gestion des entrées / sorties digitales par ARDUINO :

pinMode(pin,mode) : pin = numero sur connecteur, mode = INPUT / OUTPUT /


INPUT_PULLUP.

digitalWrite(pin,value) : pin = numero sur connecteur, value = HIGH/LOW.


int digitalRead(pin) : pin = numero sur connecteur, retourne la valeur.

L'exemple le plus simple, fourni par ARDUINO, consiste à faire clignoter la LED raccordée à la

broche PB5 du microcontrôleur, broche également disponible sur les connecteurs de la carte et

portant le numéro 13.

Exemple ARDUINO UNO Faire clignoter la LED (PB5) sans utiliser les
fonctions ARDUINO
void setup() // LED <- PB5 : LED allumée quand PB5=1
{ void setup() {
pinMode(13, OUTPUT); //broche PB5 en sortie // configurer broche PB5 en sortie
} DDRB |= B100000; // B100000 représente la
void loop() constante 0x20
{ // OU DDRB|=0x20; // équivalent
digitalWrite(13,HIGH); // set PB5 // OU DDRB |= 32; // équivalent quoique moins clair
delay(200); // délai 200 ms PORTB &= ~(1<<PORTB5); // PORTB.5 <- 0
digitalWrite(13,LOW); // clear PB5 }
delay(1000); // délai 1 s void loop() {
PORTB |= (1<<PORTB5); // PORTB.5 <- 1
delay(200); // 200 ms
} PORTB &= ~(1<<PORTB5); // PORTB.5 <- 0
delay(1000); // 1s

Exemple 1

Écrivons un code pour programmer la broche 3 du port D en tant que broche de sortie et l’utiliser
pour piloter une LED. Nous allons basculer la LED avec un peu de retard.

Schéma de circuit de l'exemple 1

(Source de l'image: www.electronicwings.com)


Comme indiqué dans la figure ci-dessus, la DEL est connectée à la broche 3 du port D. L'anode
de la DEL est connectée à 5V.

La plupart des LED nécessitent environ 10 mA de courant pour briller correctement.

Si un courant supérieur au courant nominal maximum de la LED la traverse, la LED sera


définitivement endommagée.

Le courant nominal maximum pour les LED est généralement compris entre 20 et

30 mA.

Afin de limiter le courant traversant la LED, nous connectons une résistance en série avec elle.

En supposant que la LED présente une chute de tension directe de 0,7 V et qu'un courant de

10 mA soit suffisant pour qu'elle s'allume correctement, la valeur de la résistance requise peut
être calculée comme suit :

Donc,

La valeur standard la plus proche de la résistance disponible est 470Ω. Donc, cette valeur est
utilisée dans le circuit.

/*

Output Pin Programming to Drive LED

www.electronicwings.com
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{

DDRD = 0xFF; /* Making all 8 pins of Port D as output pins */

/*

In order to make only PD3 as output while keeping direction of other pins as it is, do the following

DDRD = DDRD | (1<<3);


This is equivalent to writing one to only PD3 while keeping the other pins unchanged
*/
while(1)
{

PORTD = PORTD | (1<<3); /* Making PD3 high. This will make LED ON */
_delay_ms(100);

PORTD = PORTD & (~(1<<3)); /* Making PD3 low. This will make LED OFF */
_delay_ms(100);

/* Do not keep very small delay values. Very small delay will lead to LED appearing continuousl
y ON due to persistence of vision */
}

return 0;
}

Exemple 2

Écrivons un code pour lire le statut de la broche en entrée. Nous indiquerons cet état sur LED.

Schéma de circuit de l'exemple 2

(Source de l'image: www.electronicwings.com)

Dans cet exemple,

 Nous utilisons switch comme entrée. Le commutateur est connecté à PD2 du contrôleur.
 Nous utilisons des voyants comme indicateur de l’état de la broche PD2. La LED est
connectée à PD3.
Remarque :

Dans ce code, nous allons montrer l'état de la broche sur la LED. Nous ne montrerons
pas l'état de l'interrupteur sur la LED.
Lorsque le commutateur est ouvert, la broche est HAUTE, le voyant est allumé.
Lorsque l’interrupteur est enfoncé, la broche est BAS, le voyant est éteint.

/*

Input Pin Programming

www.electronicwings.com
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{

DDRD = DDRD | (1<<3); /* Make PD3 as output pin */


DDRD = DDRD & (~(1<<2)); /* Make PD2 as input pin */
PORTD = PORTD | (1<<2); /* Enable pull-up on PD2 by writing 1 to it */
int pin_status;
while(1)
{

pin_status = PIND & (1<<2); /*Read status of pin PD2 */


if(pin_status) /* Transmit status of pin PD2 on to pin PD3 to drive LED
. */
{

PORTD = PORTD | (1<<3); /* Switch is open, pin_status = 1, LED is ON */


}

else
{

PORTD = PORTD & (~(1<<3)); /* Switch is closed, pin_status = 0, LED is OFF */


}
}

return 0;

}
Comprendre les broches d'E / S

Toutes les broches du port ont des résistances de tirage sélectionnables individuellement avec
une résistance indépendante de la tension d'alimentation. Toutes les broches ont des diodes de
protection sur VCC et sur la terre.

États Pin

 Une broche de port peut avoir quatre états différents en fonction de l'état des bits
correspondant à cette broche dans le registre de direction des données (DDRx) et le
registre de données (PORTx) de ce port spécifique.

DDxn PORTxn E/S Pull-up Commentaire

0 0 E Non État (Z )

Pxn sera source de


0 1 E Oui
courant Pull-up

1 0 S Non Sortie basse (évier)

Sortie haute
1 1 S Non
(Source)

x est un port et peut être A, B, C ou D

n est le numéro d'identification personnel du port et peut être 0, 1, 2, 3, 4, 5, 6 ou 7

 Comme indiqué dans le schéma équivalent des broches d'E / S, chaque broche de port
possède une résistance de tirage interne. Cette résistance interne à toutes les broches
peut être désactivée en écrivant 1 dans le bit PUD du registre SFIOR. Lorsque cela est
fait, les broches sont à (états à haute impédance) si DDRxn = 0 et PORTxn = 1.

Précautions à prendre lors de la configuration des E / S

 Lors de la configuration de broches en tant que broches de sortie avec la logique HIGH,
assurez-vous que la broche n'est pas directement connectée à la terre.
 Lors de la configuration de broches en tant que broches de sortie avec une logique LOW,
assurez-vous que la broche n'est pas directement connectée à Vcc.
 Lors de la configuration des broches en tant que broches d'entrée, il faut garder à l'esprit
la structure de tension interne et effectuer les connexions en conséquence.
Chapitre 4 : ADC dans AVR ATmega16 / ATmega32

Introduction

Le convertisseur analogique-numérique (ADC) est l’appareil le plus largement utilisé dans les
systèmes intégrés spécialement conçu pour l’acquisition de données. Dans la série AVR
ATmega, un contrôleur ADC 10 bits est normalement intégré au microcontrôleur.

ATmega16 / 32 prend en charge huit canaux ADC, ce qui signifie que nous pouvons connecter
huit entrées analogiques à la fois. Les canaux ADC 0 à 7 sont présents sur PORTA. c'est-à-dire
les broches n ° 33 à 40.

ADC Broches de ATmega 16/32

(Source de l'image: www.electronicwings.com)


Le microcontrôleur dispose d’un convertisseur analogique-numérique 10 bits, ce qui signifie que
nous aurons une sortie numérique comprise entre 0 et 1023.

C'est-à-dire que lorsque l'entrée est 0V, la sortie numérique sera 0V et quand l'entrée sera 5V
(Vref = 5V), nous obtiendrons la sortie numérique la plus élevée correspondant à 1023 pas, ce
qui correspond à 5V.

Donc,

Si Vref = 5V alors 5/1023 = 4,88 mV.

Si Vref = 2,56 alors 2,56 / 1023 = 2,5 mV.

La sortie de données numériques sera donc Vout = Vin / taille du pas.

ATmega16 / 32 ADC

 C'est ADC 10 bits


 Les données binaires de sortie converties sont conservées dans les registres ADCL
(result Low) et ADCH (result High).
 ADC fournit une sortie 10 bits, donc (ADCH: ADCL), seuls 10 bits sont utiles sur 16 bits.
 Nous avons des options pour utiliser ces 10 bits comme bits supérieurs ou inférieurs.
 Nous avons également trois options pour Vref. 1. AVcc (Vcc analogique), 2. Interne 2.56 v
3. Externe A ref . .
 Le temps de conversion total dépend de la fréquence de l’horloge et de ADPS 0 : 2
(diviseur de fréquence).
 Si vous avez décidé d'utiliser la broche AVcc ou Vref comme référence de tension ADC,
vous pouvez la rendre plus stable et augmenter la précision de l'ADC en branchant un
condensateur entre cette broche et GND .

Registre ADC

Dans AVR ADC, nous devons comprendre quatre registres principaux -

1. ADCH: contient un octet plus élevé de données converties numériques


2. ADCL : contient l'octet inférieur de données converties numériques
3. ADMUX: registre de sélection du multiplexeur ADC
4. ADCSRA: registre de contrôle et d'état ADC

Registre : ADCL, ADCH

Les deux premiers registres contiennent les données numériques converties, sur 10 bits.
ADMUX Inscrivez-vous

Bit 7: 6 - REFS1: 0: Bits de sélection de référence

Sélection de tension de référence pour ADC

REFS1 REFS0 Vref à ADC

0 0 Broche AREF

0 1 AVCC pin ie Vcc 5 V

1 0 Réservé

1 1 Interne 2.56v

Bit 5 - ADLAR: résultat de réglage gauche ADC


Utilisez la sortie 10 bits en tant que bits supérieurs ou inférieurs dans ADCH & ADCL.

Bits 4: 0 - MUX4: 0: Bits de sélection de canal analogique

Nous pouvons sélectionner le canal d'entrée ADC0 à ADC7 en utilisant ces bits. Ces bits sont
également utilisés pour sélectionner des entrées de comparateur (intégrées dans AVR) avec un
gain différent. Nous couvrirons ces opérations de comparaison dans une autre partie.

La sélection du canal est très facile, il suffit de mettre le numéro du canal dans MUX4: 0.

Supposons que vous connectiez une entrée au canal ADC 2, alors mettez 00010 dans MUX4: 0.

Supposons que vous connectiez une entrée au canal ADC 5, alors insérez 00101 dans MUX4: 0.

Registre ADCSRA:
 Bit 7 - ADEN: Activer ADC

L'écriture de 1 sur ce bit active le CAN. En l'écrivant à zéro, le CAN est désactivé. La mise hors
tension de l’ADC pendant qu’une conversion est en cours met fin à cette conversion.

 Bit 6 - ADSC: démarrage de la Conversion de l’ ADC

L'écriture de 1 sur ce bit commence la conversion.

 Bit 5 - ADATE: Activation automatique du déclencheur ADC

En écrivant 1 de ce bit, le déclenchement automatique de l’ADC est activé.

 Bit 4 - ADIF: indicateur d'interruption ADC

Ce bit est activé lorsqu'une conversion ADC est terminée et que les registres de données sont
mis à jour.

 Bit 3 - ADIE: Activer l'interruption ADC

En écrivant 1 sur ce bit, l’interruption de conversion complète du convertisseur analogique-


numérique est activée.

 Bits 2: 0 - ADPS2: 0: Bits ADC Prescaler Select

Ces bits déterminent le facteur de division entre la fréquence XTAL et l’horloge d’entrée du CAN.

Pour notre AVR, Nous devons toujours veiller à ne pas dépasser la fréquence ADC supérieure à
200 KHz. Supposons que votre fréquence d'horloge de l'AVR soit de 8 MHz, alors nous devons
utiliser le scrutateur 64 ou 128. Parce que cela donne 8 MHz / 64 = 125 KHz, ce qui est inférieur
à 200 KHz.
Schéma

LCD16x2 est utilisé pour afficher la valeur convertie numérique du canal 0.

Schéma de circuit pour l'utilisation de ADC0 d'ATmega 16/32

(Source de l’image : www.electronicwings.com)


Étapes pour programmer ADC
1. Activer ADC avec l'écriture de 1 sur ADEN dans ADCSRA.

2. Créez une broche de canal ADC comme entrée.


3. Définissez le bit d'activation ADC dans ADCSRA, sélectionnez la vitesse de conversion à
l'aide de ADPS2 : 0. Par exemple, nous allons sélectionner le diviseur 128.
4. Sélectionnez la tension de référence ADC en utilisant REFS1: REFS0 dans le registre
ADMUX. Par exemple, nous utiliserons AVcc comme tension de référence.
5. Sélectionnez le canal d'entrée ADC à l'aide de MUX4: 0 dans ADMUX, par exemple, nous
utiliserons le canal 0. Donc, notre valeur dans le registre ADCSRA = 0x87 et ADMUX =
0x40.
6. Commencez la conversion en définissant le bit ADSC dans ADCSRA.
7. Attendez la fin de la conversion en interrogeant le bit ADIF dans le registre ADCSRA.
8. Une fois que le bit ADIF est devenu HIGH, lisez les registres ADCL et ADCH pour obtenir
une sortie numérique.

Programme

#define F_CPU 8000000UL


#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include "LCD_16x2_H.h"
ADC_Init()
{
DDRA=0x0; /* Make ADC port as input */
ADCSRA = 0x87; /* Enable ADC, fr/128 */
ADMUX = 0x40; /* Vref: Avcc, ADC channel: 0 */

}
ADC_Read(char channel)
{
int Ain,AinLow;

ADMUX=ADMUX|(channel & 0x0f); /* Set input channel to read */

ADCSRA |= (1<<ADSC); /* Start conversion */


while((ADCSRA&(1<<ADIF))==0); /* Monitor end of conversion interrupt */
_delay_us(10);
AinLow = (int)ADCL; /* Read lower byte*/
Ain = (int)ADCH*256; /* Read higher 2 bits and
Multiply with weight */
Ain = Ain + AinLow;
return(Ain); /* Return digital value*/
}

int main()
{
char String[5];
char String[5];
int value;

ADC_Init();
LCD_Init(); /* Initialization of LCD */
LCD_String("ADC value"); /* Write string on 1st line of LCD */

while(1)
{

LCD_Command(0xc4); /* LCD16x2 cursor position */


value=ADC_Read(0); /* Read ADC channel 0 */
itoa(value,String,10); /* Integer to string conversion */
LCD_String(String);
LCD_String(" ");
}
return 0;
}

PROGRAMMATION DE L'ADC À L'AIDE DE L'ARDUINO

1- la fonction analogRead(pin) va nous permettre de lire la valeur lue sur une


entrée analogique de l'Arduino.
2- on a une valeur retournée par la fonction comprise entre 0 et 1023.
Référencées :

1/ Fiche technique ATmega16 et ATmega32

2/ www.electronicwings.com

3/
CHAPITRE 5 :

Les interruptions exploitables sur ATMega328 (carte Arduino UNO)


Interruption (IT) est la suspension du programme en cours pour exécuter une routine d'interruption
(Interruption Service Routine ISR).

ATmega328 est équipé d’un complément puissant et flexible de 26 sources d’interruption. Deux des
interruptions proviennent de sources d'interruption externes, tandis que les 24 autres interruptions prennent
en charge le fonctionnement des périphériques embarqués sur le microcontrôleur.
Les sources d'interruption ATmega328 sont illustrées à la figure 1.
Le RESET a la priorité la plus élevée, suivi des broches externe INT0 (pin4) et INT1 (pin5). Les sources
d'interruption restantes sont internes à l'ATmega328.
Quand une interruption se produit, le microcontrôleur termine l’instruction en cours, stocke l’adresse de la
prochaine instruction sur la pile et commence à exécuter les instructions dans le répertoire désigné le
programme de service d’interruption (ISR) correspondant à la source d’interruption particulière.
Le système d’interruption empêche d’autres interruptions en cours. L'exécution du L’ISR est exécuté en
chargeant l’adresse de début de la routine de service d’interruption spécifique à cet événement.

Figure 5.1 : Les sources d'interruption ATmega328.


Programmation des interruptions :
Les interruptions externes :
Les interruptions INT0 et INT1 peuvent être déclenchées avec un front descendant ou montant
(falling/rising edge), un signal de niveau bas (low level) ou un changement d'etat quelconque (any
logical change). Les paramètres spécifiques à chaque interruption sont fournis à la figure 5.2.
Il y a trois registres dans le processeur pour gérer les deux pins d'interruption INT0 (pin 4) and
INT1 (pin 5).
Le registre EICRA "External Interrupt Control Register" ne contient que 2 fois 2 bits qui pour
chaque pin codent le mode vu plus haut.
Le registre EIMSK "External Interrupt Mask Register" contient les 2 bits INT0, INT1 qui
autorisent les interruptions 0 et 1.
Le registre EIFR "External Interrupt Flag Register" contient les 2 bits INTF0, INTF1qui sont
activés par les interruptions 0 et 1.

Figure 5.2: Interrupt INT0 and INT1 Registers.

Après avoir déterminé les pins d’interruption Il faut encore savoir le nom de la fonction
d’interruption associée à une cause d'IT,( associer au vecteur d'interruption: ISR(INT0_vect) {
nos instructions }) Figure 5.1 .
Exemple :
Chaque fois que le bouton poussoir fait passer le niveau de 1 a 0 sur l'entree INT0(PD2),la fonction
d''interruption associee a INT0 est executee. Cette action a pour effet d'inverser l'etat de la LED et
de revenir au programme principal. Il est important de comprendre que l'interruption ne dure que
quelques microsecondes. En dehors de ces interruptions, le programme principal (fonction loop())
envoie chaque seconde la valeur de la variable cpt.
Exemple : exploitation IT Externe 0

// Exemple : exploitation IT Externe 0


ISR(INT0_vect) // ISR INT0 = traitement si interruption INT0
{
PORTB ^= 0x20; // bascule PORTB.5
}
void setup(){ // configuration pour exploiter IT INT0
cli();
Serial.begin(9600);
DDRB |= 0x20; // PB5 en sortie
PORTB &= ~0x20; // PORTB.5 <-0 (sortie PB5 à 0)
DDRD &= ~0x04; // PD2 en entrée
PORTD |= 0x04; // PORTD.2=1 <-> activer pull-up
EICRA = 0x02; // IT si front sur INT0 (table 12-2)
EIMSK |= 1; // source INT0 activée
sei(); // active les IT en général
}
int cpt=0; // variable globale (hors fonction)
void loop() { // ce traitement peut être interrompu pour INT0
Serial.println(cpt,DEC);
cpt++;
delay(1000);
}

Le microcontrôleur ATmega328 accepte des interruptions possibles sur toute entrée TOR (Interruptions
"Pin Change")
Chaque front, montant ou descendant, conduit à une interruption Pin Change (PCINT0_vect, PCINT1_vect,
PCINT2_vect) permettent d'associer une fonction (ISR) à un changement d'état d'une entrée.
Donc les broches PCINT0 à PCINT23 sont configurables pour déclencher des interruptions suite à des
changements d'état ("Pin Change") Les broches sont séparées en 3 sous-groupes, il y a une source
d'interruption par sous-groupe, et pour chaque broche on peut activer ou non le système "Pin Change
Interrupt"
PCINT0 – PCINT7 <-> broches PB0 à PB7 groupe lié à IT PCINT0_vect
PCINT8 – PCINT15 <-> broches PC0 à PC7 groupe lié à IT PCINT1_vect
PCINT16 – PCINT23<-> broches PD0 à PD7 groupe lié à IT PCINT2_vect
Les registres PCMSK0, PCMSK1 et PCMSK2 contrôlent, pour chacun de ces groupes (donc pour chaque
port B, C D), quelle(s) broche(s) peut(vent) conduire (ou non) à une interruption de type "pin change".

Activation des interruptions PCINT0 à PCINT23 si bit SREG.7=1 et mise à 1 de PCIEx


Registre PCICR : activation des IT Pin Change pour un groupe
PCICR.0 : activation des IT Pin Change pour les broches du port B (PB0 a PB7)
PCICR.1 : activation des IT Pin Change pour les broches du port C (PC0 a PC6)
PCICR.2 : activation des IT Pin Change pour les broches du port D (PD0 a PD7)
Activation à l'intérieur d'un groupe : le registre PCMSKx détermine quelles broches du groupe sont
prises en compte pour l'interruption "pin change"

Flags internes pour les IT "Pin Change"

Exemple : mise en oeuvre IT Pin Change sur Port B et Port D

// Config pour IT Pin Change


void setup()
{
// aucune IT possible (SREG.7<-0)
cli();
// Pin Change actif sur port D et port B
PCICR |= 0x05;
// PB1 et PB0 en entrée
DDRB&=~0x03; PD7 et PD5 en entrée
DDRD&=~0x0A; // Change
Pin pour broches PB0 et PB1
PCMSK0=0x03; // Pin Change pour broches PD7 et PD5
PCMSK2=0xA0; IT possibles SREG.7<-1
//
sei();
}

ISR(PCINT0_vect){ ... } // appelée si changement sur PB1 ou PB0


ISR(PCINT2_vect){ ... } // appelée si changement sur PD7 ou PD5

Programmation d'interruption interne :

Pour les autre type d’interruption comme les timers on va les exploiter dans les prochaines sections.
Les interruptions arduino :

L'environnement de développement Arduino comporte quatre fonctions intégrées permettant de prendre en


charge les interruptions externes INT0 et INT1.

1/ interrupts(). This function enables interrupts.

2/ noInterrupts(). This function disables interrupts.

3/ attachInterrupt(interrupt, function, mode). This function links the interrupt to the appropriate

interrupt service routine :

• interrupt. Interrupt specifies the INT interrupt number: either 0 or 1.

• function. Function specifies the name of the interrupt service routine.

• mode. Mode specifies what activity on the interrupt pin will initiate the interrupt:LOW level

on pin, CHANGE in pin level, RISING edge, or FALLING edge.

4/ detachInterrupt(interrupt). This function turns off the specified interrupt.

Exemple : exploitation IT Externe 0

void setup()
{
attachInterrupt(0, int0_ISR, RISING);
}
void loop()
{
//wait for interrupts
}
//*************************************************************************
//int0_ISR: interrupt service routine for INT0
//*************************************************************************
void int0_ISR(void)
{
//Insert interrupt specific actions here.
}

Référencées :
1/ Fiche technique ATmega16 et ATmega32

2/ www.arduino.cc

3/ B. Cottenceau : Carte ARDUINO UNO Microcontrôleur ATMega328 - 2016-2017.


CHAPITRE 6:

Les Timers / Counters

Généralement, nous utilisons les Timer/Counter pour générer des retards, des formes d’onde, pour
compter les événements ou pour la génération PWM, etc.

Dans AVR ATmega16 / ATmega32, il y a trois Timer/Counter:

 Timer 0 : minuterie 8 bits


 Timer1 : minuterie 16 bits
 Timer2 : minuterie 8 bits

Timer 0 Timer 1 Timer 2


- 8-bit timer/counter - 16-bit timer/counter - 8-bit timer/counter
- 10-bit clock prescaler - 10-bit clock prescaler - 10-bit clock prescaler
- Functions: - Functions: - Functions:
-- Pulse width modulation -- Pulse width modulation -- Pulse width modulation
-- Frequency generation -- Frequency generation -- Frequency generation
-- Event counter -- Event counter -- Event counter
-- Output compare -- 2 ch -- Output compare -- 2 ch -- Output compare -- 2 ch
- Modes of operation: -- Input capture - Modes of operation:
-- Normal - Modes of operation: -- Normal
-- Clear timer on -- Normal -- Clear timer on
compare match (CTC) -- Clear timer on compare match (CTC)
-- Fast PWM compare match (CTC) -- Fast PWM
-- Phase correct PWM -- Fast PWM -- Phase correct PWM
-- Phase correct PWM

Registres de base et drapeaux des timers


TCNTn: registre Timer/Counter

- Il compte à chaque impulsion d'horloge.


- lors de la réinitialisation TCNTn = 0.
- Nous pouvons lire / écrire une valeur dans ce registre.

TOVn: indicateur de débordement de Timer/Counter

Chaque Timer/Counter a un indicateur de dépassement. Lorsqu’il y a un débordement, cet


indicateur est activé.

TCCRn: Registre de contrôle du Timer/Counter

Ce registre est utilisé pour régler les modes de Timer/Counter.

OCRn: registre de comparaison de sortie

La valeur de ce registre est comparée au contenu du registre TCNTn. Quand ils sont égaux, le
drapeau OCFn sera activé.
Configuration du Timer/Counter 0

Figure 6.1: Timer 0

Les registres du Timer/Counter 0

1. TCNT0: C'est un registre de 8 bits. Il compte à chaque impulsion d’horloge.

2 . TCCR0: Registre de contrôle de Timer/Counter 0

Il s’agit d’un registre de 8 bits utilisé pour le mode de fonctionnement et la sélection de la


source d’horloge.

3. TIFR: registre d'indicateurs d'interruption de Timer/Counter 0


Figure 6.2: Timer 0 registers.

Modes de fonctionnement en mode temporisateur :

Normal : le registre TCNT0 est incremente de 1 a chaque evenement de comptage. Le registre ne

revient a 0 qu'apres un debordement (passage de 0xFF a 0x00).

CTC (Clear Timer on Compare) : le registre TCNT0 s'incremente a chaque evenement de

comptage mais est remis a 0 si TCNT0=OCR0A.

D'autres modes non detailles, notamment pour la gestion des PWM.

Le choix du mode se fait via les bits WGM02:00 (bits TCR0A et TCR0B)
Clear Timer on Compare Match (CTC) Mode :

En mode CTC (WGM02:0 = 2), le registre OCR0A regle la resolution. Le compteur TCTN0 est

remis a zero apres l'egalite (match) TCTN0=OCR0A. Le registre OCR0A definit la valeur

maximale pour le compteur, et donc sa resolution.

Prescaler : en fonction temporisateur, le registre de comptage TCNT0 est incremente en fonction des
cycles horloge. L'increment peut etre a chaque cycle horloge (pas de prescaler) ou bien a une frequence
moindre. Rappelons que le cycle horologe est de 1/16 micro-secondes.

Remarque : pour les Timers 1 et 2, les configurations sont similaires.

Exemple :

Pour le Timer 0, a chaque debordement de TCNT0 (passage de 0xFF a 0x00) une interruption

TIMER0_OVF_vect peut etre exploitee. Il faut donc activer ce mecanisme

TIMSK2=0x01; // IT Timer0 Over Flow Active

Fournir la routine d'IT :

ISR(TIMER0_OVF_vect){ ... } //ISR de l'IT débordement Timer0

et configurer le Timer 0.

// ARDUINO UNO - IT Timer0 Overflow

volatile unsigned char cpt=0; // compteur d'IT

// Fonction de traitement IT Timer 0 OverFlow


ISR(TIMER0_OVF_vect){
cpt++; if(cpt==61) {
PORTB ^=0x20;

cpt=0;

}}

void setup(){
//Configuration PORTB.5
DDRB |= 0x20; // PB5 en sortie
PORTB &= ~0x20; // PORTB.5 <-0
cli();
// Configuration Timer 0
TCCR0A=0; // Mode Normal (pas PWM)
TCCR0B=0x07; // Prescaler 1024 (Clock/1024)
TIMSK0=0x01; // IT Timer0 Over Flow Active
sei(); // activation des IT (SREG.7=1)
}

void loop() { /* aucun traitement*/ }


Principe : apres la fonction setup(), le registre TCNT0 (8bits) est incremente a chaque tick du signal
periodique clock/1024. chaque debordement du registre TCNT0, declenche une interruption : "Timer0
Over Flow". Tous les 60 appels de cette fonction, la broche PB5 (LED) change d'etat.

Quelle fréquence de clignotement ?

Clock = signal periodique de 16MegaHz (16000000 de cycles par seconde)

Prescaler = 1024 -> la frequence d'increment de TCNT0 = (16/1024) MegaHz

Fréquence de débordement : TCNT0 ne deborde que tous les 256 increments

c'est-a-dire a la frequence de 16/(1024*256) MegaHZ ≈ 61 Hz

Il y a 1 interruption Timer0 Over Flow tous les 1/61 secondes.

Il faut 61 Interruptions pour que la LED change d'etat

La LED change d'état (0->1 1->0) à intervalles de environ 1 second


Figure 6.3
Figure 6.4 : Timer 2 registers.
Timer/Counter 1 (comptage 16 bits)
Le registre de comptage TCNT1, ainsi que les registres de comparaison OCR1A et OCR1B, sont

Cette fois-ci sur 16 bits.

Figure 6.5 : Timer 1 .


Figure 6.6 : Timer 1 registers.
PWM dans AVR ATmega16 / ATmega32

Introduction :
La modulation de largeur d'impulsion (PWM) est une technique qui permet de faire varier la largeur
d'une impulsion tout en maintenant la fréquence constante.

Pourquoi avons-nous besoin de faire ça ? Prenons un exemple de contrôle de la vitesse du moteur à


courant continu, plus la largeur d'impulsion est grande, plus la vitesse. Il existe également des
applications telles que le contrôle de l'intensité lumineuse par PWM.

Une période d'impulsion comprend un cycle ON (5V) et un cycle OFF (0V). La fraction pour laquelle
le signal est activé sur une période est appelée cycle de travail.

Cycle de service (en%) =

Par exemple, considérons une impulsion avec une période de 10 ms qui reste activée (haute) pendant
2 ms. Le cycle de service de cette impulsion sera

D = 2ms / 10ms = 20%

Grâce à la technique PWM, nous pouvons contrôler la puissance fournie à la charge en utilisant le
signal ON-OFF.

Les signaux modulés en largeur d'impulsion avec différents rapports cycliques sont indiqués ci-dessous

Formes d'onde du cycle de service PWM :


ATmega a une unité PWM intégrée. Comme nous le savons, ATmega dispose de 3 temporisations T0,
T1 et T2 pouvant être utilisées pour la génération de PWM. Il existe principalement deux modes dans
PWM.
1. PWM rapide

2. Phase correcte PWM

Nous devons configurer le registre du timer pour générer des PWM. La sortie PWM sera générée sur
la broche de comparaison de sortie du programmateur (OCx) correspondante.

La sortie PWM est en quelque sorte proche de la sortie analogique. Nous pouvons l'utiliser comme
sortie analogique pour générer une onde sinusoïdale, des signaux audio, etc.
Référencées :
1/ Fiche technique ATmega16 et ATmega32

2/ www.arduino.cc
3/ B. Cottenceau : Carte ARDUINO UNO Microcontrôleur ATMega328 - 2016-2017.

4/ http://www.electronicwings.com
CHAPITRE 7 EEPROM dans AVR ATmega16 / ATmega32

Introduction
L'EEPROM est une mémoire à lecture seule programmable effaçable électriquement. Il s'agit
d'une mémoire de type non volatile car elle contient les données même lorsque l'ordinateur est
hors tension.
Le principal avantage de cette mémoire est que le contrôleur peut lire, modifier / écrire cette
mémoire dans une application d'exécution. Ainsi, la mémoire EEPROM peut être utilisée pour
stocker des valeurs de capteur, des paramètres importants, etc. sans craindre de perte, même
en cas de panne de courant.
L'ATMEGA32 contient 1024 octets de données dans la mémoire EEPROM. Elle est
organisée comme un espace de donné séparé, dans lequel des octets simples peuvent être lus
et écrits. L'EEPROM a une endurance d'au moins 100,000 cycles d’écriture/effacement. Il est
organisé comme un espace de données séparé dans lequel un seul octet peut être lu et écrit.

L'accès via la mémoire EEPROM s'effectue via trois registres.

 EEAR (registre d'adresses EEPROM).


 EEDR (registre de données EEPROM).
 EECR (registre de contrôle EEPROM).

Registre d'adresses EEPROM (EEAR)


Atmega32 a un registre EEAR 16 bits qui est utilisé pour adresser l'emplacement de la
mémoire EEPROM.
Dans EEAR, les 10 bits les plus bas sont utilisés pour spécifier l'adresse. Les autres sont
réservés et seront toujours lus à zéro.
Il possède deux registres de 8 bits, EEARH et EEARL. EEARL contient le premier bit
d'adresse 8 et EEARH contient le dernier bit 10 d'adresse, comme indiqué sur la figure.

EEAR doit être écrit correctement avant l'accès à la mémoire.


Registre de données EEPROM (EEDR)

L'EEDR contient des données à écrire / lire à l'emplacement adressé par EEAR lors d'une
opération d'écriture / lecture.

Registre de contrôle EEPROM (EECR )

EECR contient des bits de contrôle permettant d’avoir accès via EEPROM.

Bit 7: 4:
Ces bits sont réservés et toujours lus à zéro.

Bit 3 - EERIE: EERIE: EEPROM Ready Interrupt Enable.

1 = l' écriture 1 active EERIE si le bit I dans SREG est activé.

0 = l' écriture zéro désactive EERIE

Il génère une interruption constante lorsque EEWE est effacé

Bit 2 - EEMWE: EEPROM Master Write Enable

Ce bit est activé par le maître pour l'opération d'écriture.


1 = configurer EEWE dans un délai de quatre cycles d'horloge écrira des données sur
l'EEPROM

0 = Le réglage de EEWE n'aura aucun effet.


Lorsque EEMWE a été écrit dans un logiciel par un programme, le matériel remet le bit à zéro
après quatre cycles d'horloge. Il est donc indispensable de définir le bit EEWE dans les quatre
cycles d'horloge après le paramétrage d'EEMWE pour effectuer l'opération d'écriture avec
succès.

Bit 1 - EEWE : EEPROM Write Enable

1 = autorisation d'écriture.

0 = écriture désactivée.
Si vous définissez EEWE alors que EEAR et EEDR contiennent l'adresse et les données
correctes et que le bit EEMWE est activé, effectuez une opération d'écriture.

Bit 0 - EERE: EEPROM Read Enable

1 = autorisation de lecture.
0 = lecture désactivée.
Le réglage de EERE alors que EEAR contient l’adresse appropriée permet la lecture.

Séquence d'écriture EEPROM

1. Attendez que EEWE devienne nul.


2. Attendez que SPMEN (Mémoire programme activé) dans SPMCR devienne nul.
3. Écrivez l'adresse EEPROM dans EEAR.
4. Ecrire des données EEPROM à EEDR.
5. Ecrivez un 1 logique dans le bit EEMWE en écrivant un zéro dans EEWE dans EECR.
6. Dans les quatre cycles d'horloge suivant le réglage de EEMWE, écrivez 1 logique dans
EEWE.

Séquence de lecture EEPROM

1. Attendez que EEWE devienne nul.


2. Écrivez l'adresse EEPROM dans EEAR.
3. Ecrivez-en un sur EERE pour activer l'opération de lecture à partir de l'adresse
spécifiée.
4. Lire le registre EEDR.

Pour éviter les écritures EEPROM non intentionnelles, vous devez suivre cette procédure, car
EEWE doit être écrit dans l'un au cours du prochain cycle, après la définition de EEMWE sur
1

Utilisation de la fonction de bibliothèque EEPROM avr-libc


Le studio Atmel avec le compilateur GCC fournit ses bibliothèques intégrées apr-libc pour un
accès EEPROM.
Nous avons juste besoin d'inclure le fichier d'en-tête de l'EEPROM dans le fichier du
programme principal, par exemple

#include <avr/eeprom.h> /* Include AVR EEPROM header file */

Le fichier d’en-tête contient toutes les fonctions d’accès EEPROM indiquées ci-dessous,

uint8_t eeprom_read_byte (const uint8_t *__p); /* Read one byte from EEPROM address */

uint16_t eeprom_read_word (const uint16_t *__p); /* Read one 16-bit word from EEPROM address */

uint32_t eeprom_read_dword (const uint32_t *__p); /* Read one 32-bit double word from EEPROM address*/

float eeprom_read_float (const float *__p); /* Read one float value from EEPROM address */

void eeprom_read_block (void *__dst, const void *__src, size_t __n);/* Read a block of n bytes from EEPROM address
to SRAM */

void eeprom_write_byte (uint8_t *__p, uint8_t __value); /* Write a byte value to EEPROM address */

void eeprom_write_word (uint16_t *__p, uint16_t __value);/* Write a word to EEPROM address */

void eeprom_write_dword (uint32_t *__p, uint32_t __value);/* Write a 32-bit double word to EEPROM address */

void eeprom_write_float (float *__p, float __value); /* Write float value to EEPROM address */

void eeprom_write_block (const void *__src, void *__dst, size_t __n);/* Write a block of bytes to EEPROM address */

void eeprom_update_byte (uint8_t *__p, uint8_t __value);/* Update byte value to EEPROM address */
void eeprom_update_word (uint16_t *__p, uint16_t __value);/* Update word val to EEPROM address */

void eeprom_update_dword (uint32_t *__p, uint32_t __value);/* Update a 32-bit double word value to EEPROM address */

void eeprom_update_float (float *__p, float __value); /* Update float value to EEPROM address */

void eeprom_update_block (const void *__src, void *__dst, size_t __n);/* Up- date a block of bytes to EEPROM address */

Les fonctions ci-dessus sont utilisées pour écrire / lire une EEPROM. Il existe également une
prise en charge des opérations de données 8, 16 et 32 bits avec différents types de données
tels que integer, float, double.
La fonction de mise à jour est principalement recommandée pour l'écriture (mise à jour) de
l'EEPROM,

Différence entre la fonction write et la fonction update


La fonction de mise à jour permet de vérifier si le nouveau contenu de données est différent
de l'ancien contenu de données conservé à cette adresse. S'il diffère, alors il écrit uniquement
le nouveau contenu de données à cette adresse. Cela évite les cycles d'écriture dans le cas d'un
contenu de données identique, ce qui aide à maintenir la durée de vie de l'EEPROM.

EEPROM carte Arduino


Pour manipuler des données en mémoire EEPROM, il est nécessaire d'utiliser la bibliothèque
EEPROM disponible de base avec le logiciel de développement Arduino.
Pour utiliser la bibliothèque EEPROM dans un programme Arduino, il suffit d'ajouter cette
ligne en début de programme :

#include <EEPROM.h>
1
Écrire dans la mémoire EEPROM
Écrire un octet en mémoire ce fait au moyen de la fonction EEPROM.write().

EEPROM.write(int adresse, byte valeur)


1

La fonction EEPROM.write() accepte deux paramètres obligatoires : l'adresse mémoire de


l'octet à écrire (débutant à 0) et la valeur de l'octet en question (entre 0 et 255). La fonction ne
retourne aucune valeur.

Lire depuis la mémoire EEPROM


Lire un octet en mémoire ce fait au moyen de la fonction EEPROM.read().

byte EEPROM.read (int adresse)


1

La fonction EEPROM.read() accepte un paramètre obligatoire : l'adresse mémoire de l'octet à


lire (débutant à 0). La fonction retourne la valeur de l'octet à l'adresse en question (entre 0 et
255).
PS : Vous pouvez lire une mémoire EEPROM autant de fois que vous le souhaitez, seule
l'écriture réduit sa durée de vie.
Par exemple, voici comment lire le contenu des 256 premiers octets de mémoire :

1#include <EEPROM.h>
2
3void setup() {
4 Serial.begin(9600);
5
6 for (int i = 0; i < 256; i++) {
7 byte valeur = EEPROM.read(i);
8 Serial.print(i);
9 Serial.print(" = ");
10 Serial.println(valeur);
11 }
12}
13void loop() {
14}
Mettre à jour les données efficacement
Imaginons que la mémoire EEPROM de votre carte Arduino contient la suite d'octets suivante
: 1 2 3 4 5 6.
Le temps passe et vous voulez maintenant changer ces valeurs par 1 2 3 7 8 9, comme vous
pouvez le remarquer, certaines valeurs sont identiques, il serait donc idiot de perdre un cycle
d'écriture pour écrire une valeur identique à la précédente.
C'est pourquoi il existe la fonction EEPROM.update(). Celle-ci est identique à la
fonction EEPROM.write() mais vérifie d'abord la valeur en mémoire avant de faire une
écriture. Si la valeur est différente, l'écriture est réalisée, sinon, la fonction ne fait rien.
PS : Idéalement, cette fonction devrait toujours être utilisée, en remplacement
de EEPROM.write(), car celle-ci fonctionne de manière identique, mais évite les écritures
inutiles.

EEPROM.update (int adresse, byte valeur)


1

La fonction EEPROM.update() accepte deux paramètres obligatoires : l'adresse mémoire de


l'octet à écrire (débutant à 0) et la valeur de l'octet en question (entre 0 et 255). La fonction ne
retourne aucune valeur.

Connaitre la taille de la mémoire EEPROM depuis le programme


Cela n'est pas documenté officiellement, mais depuis Arduino 1.0.x, il est possible de
connaitre la taille de la mémoire EEPROM via la fonction : EEPROM.length().
La fonction EEPROM.length() retourne un nombre entier qui correspond à la taille de la
mémoire EEPROM.
Exemple :

1#include <EEPROM.h>
2
3void setup() {
4 Serial.begin(9600);
5
6 Serial.print("Taille EEPROM : ");
7 Serial.println(EEPROM.length());
8}
9
1 void loop() {}
Référencées :
1/ Fiche technique ATmega16 et ATmega32

2/ www.arduino.cc
3/ https://www.carnetdumaker.net/articles/stocker-des-donnees-en-memoire-eeprom-avec-une-
carte-arduino-genuino/

4/ http://www.electronicwings.com
CHAPITRE 8
USART dans AVR ATmega16 / ATmega32

Introduction
L'AVR ATmega dispose d'un système USART flexible, qui peut être utilisé pour la communication
série avec d'autres périphériques tels qu'un ordinateur, des modules série GSM, des modules GPS,
etc.

La communication série :
Lors de l’envoi / réception de données, certains bits sont ajoutés afin de connaître le début / la fin des
données, etc. La structure couramment utilisée est la suivante : 8 bits de données, 1 bit de départ (0
logique) et 1 bit d’arrêt (logique 1), comme indiqué :

Il existe également d'autres formats de trame pris en charge disponibles dans UART, tels que le bit de
parité, les bits de données variables (5 à 9 bits de données).

Vitesse (débit en bauds) :


Le débit est « Nombre de bits par seconde (bps) », également appelé Débit en bauds dans un système
binaire. Normalement, cela définit la vitesse de la ligne série. Certaines vitesses de transmission
standard sont définies, par exemple 1200, 2400, 4800, 19200, 115200 bps, etc. On utilise normalement
9600 bps lorsque la vitesse n'est pas un problème critique.

Connexion matérielle :
Normalement, dans USART, nous n’avons besoin que des fils Tx (transmission), Rx (réception) et
GND.

 AVR ATmega USART a un niveau de tension TTL qui est 0 v pour la logique 0 et 5 v pour la
logique 1.
 Dans les ordinateurs et la plupart des anciens périphériques, le protocole RS232 est utilisé pour
la communication série, où un connecteur 9 broches est normalement utilisé. La
communication série RS232 a des niveaux de tension différents de ceux de la communication
série ATmega, à savoir +3 v à +25 v pour le zéro logique et -3 v à -25 v pour la logique 1.
 Donc, pour communiquer avec le protocole RS232, nous devons utiliser un convertisseur de
niveau de tension comme le MAX232 IC.
Comme indiqué dans la fiche technique ATmega 16 USART présente les caractéristiques suivantes

 Fonctionnement en duplex intégral (registres de réception et de transmission série


indépendants)
 Opération Asynchrone ou Synchrone
 Fonctionnement synchrone synchronisé maître ou esclave
 Générateur de débit en bauds haute résolution
 Prend en charge les trames série avec 5, 6, 7, 8 ou 9 bits de données et 1 ou 2 bits d'arrêt
 Génération et vérification de parité paires ou impaires prises en charge par le matériel
 Détection de dépassement de données
 Détection d'erreur de cadrage
 Le filtrage du bruit inclut la détection des bits à démarrage erroné et le filtre passe-bas
numérique
 Trois interruptions distinctes sur TX Complete, Registre de données TX vide et Réception
complète
 Mode de communication multiprocesseur
 Mode de communication asynchrone à double vitesse

Registres de base AVR

1. UDR: registre de données USART

Il a essentiellement deux registres, l’un est Tx. Byte et autre est Rx Byte. Les deux partage le même
registre UDR. N'oubliez pas que lorsque nous écrivons au registre UDR. Le tampon Tx sera écrit et
lorsque nous lirons à partir de ce registre, le tampon Rx sera lu. Le tampon utilise un registre à décalage
FIFO pour transmettre les données.

2. UCSRA : Registre de contrôle et d'état USART A. Comme son nom l'indique, est utilisé pour
les indicateurs de contrôle et d'état. De manière similaire, il existe deux autres registres de contrôle et
de statut USART, à savoir UCSRB et UCSRC.

3. UBRR : USART Baud Rate Register, il s’agit d’un registre 16 bits utilisé pour définir le débit
en bauds.

Nous verrons ce registre en détail:

UCSRA: Registre de contrôle et d'état USART A


 Bit 7 - RXC: USART Receive Complete

Ce bit de drapeau est défini l’orsqu'il y a des données non lues dans UDR. Le drapeau RXC peut être
utilisé pour générer une interruption de réception complète.

 Bit 6 - TXC: Transmission USART terminée

Ce bit indicateur est défini lorsque la trame entière de la mémoire tampon Tx est décalée et qu’aucune
nouvelle donnée n’est actuellement présente dans la mémoire tampon de transmission (UDR). Le bit
de drapeau TXC est automatiquement effacé lorsqu’une interruption de transmission complète est
exécutée ou peut être effacé en écrivant un 1 dans son emplacement de bit. L'indicateur TXC peut
générer une interruption de transmission terminée.

 Bit 5 - UDRE: registre de données USART vide

Si UDRE est 1, le tampon est vide, ce qui indique que le tampon de transmission (UDR) est prêt à
recevoir de nouvelles données. L'indicateur UDRE peut générer une interruption vide du registre de
données. UDRE est défini après une réinitialisation pour indiquer que le transmetteur est prêt.

 Bit 4 - FE: erreur de trame


 Bit 3 - DOR: Data OverRun

Ce bit est activé si une condition de dépassement de données est détectée. Une surcharge de données
se produit lorsque le tampon de réception est plein (deux caractères) et qu'un nouveau caractère est en
attente dans le registre à décalage de réception.

 Bit 2 - PE: erreur de parité


 Bit 1 - U2X: doublez la vitesse de transmission USART
 Bit 0 - MPCM: mode de communication multiprocesseur

UCSRB: Registre de contrôle et d'état USART B

 Bit 7 - RXCIE: activation d' interruption complète RX

L'écriture de 1 sur ce bit active l'interruption sur l'indicateur RXC.

 Bit 6 - TXCIE: activation d' interruption complète de TX

L'écriture de 1 sur ce bit active l'interruption sur le drapeau TXC.


 Bit 5 - UDRIE: Activation d'interruption vide du registre de données USART

L'écriture de 1 sur ce bit active l'interruption sur le drapeau UDRE.

 Bit 4 - RXEN: Activer le récepteur

L'écriture de 1 sur ce bit active le récepteur USART.

 Bit 3 - TXEN: Activer l'émetteur

L'écriture de 1 sur ce bit active le transmetteur USART.

 Bit 2 - UCSZ2: Taille du caractère

Les bits UCSZ2 combinés avec le bit UCSZ 1: 0 dans UCSRC définissent le nombre de bits de données
(taille de caractère) dans une trame utilisée par le récepteur et l'émetteur.

 Bit 1 - RXB8: Réception de données, bit 8


 Bit 0 - TXB8: Transmission de données, bit 8

UCSRC: Registre de contrôle et d'état USART C

 Bit 7 - URSEL: sélection du registre

Ce bit sélectionne l'accès au registre UCSRC ou au registre UBRRH , car les deux registres partagent
la même adresse. L'URSEL doit être un lors de l'écriture de l'UCSRC, sinon les données seront écrites
dans le registre UBRRH.

 Bit 6 - UMSEL: Sélection du mode USART

Ce bit sélectionne le mode de fonctionnement asynchrone ou synchrone.

0 = fonctionnement asynchrone

1 = fonctionnement synchrone

 Bit 5: 4 - UPM1: 0 : Mode parité

Ces bits permettent d'activer et de définir le type de génération et de contrôle de parité. Si une non-
concordance est détectée, l'indicateur PE dans UCSRA sera défini.
UPM1 UPM0 Mode Parité

0 0 désactivé

0 1 Réservé

1 0 Activé, même parité

1 1 Activé, parité impaire

 Bit 3 - USBS : sélection du bit d'arrêt

Ce bit sélectionne le nombre de bits d'arrêt à insérer par le transmetteur. Le récepteur ignore ce
paramètre. 0 = 1 bit ; 1 = 2 bits

 Bit 2: 1 - UCSZ1: 0 : Taille du caractère

Les bits UCSZ1: 0 combinés avec le bit UCSZ2 dans UCSRB définissent le nombre de bits de données
(taille de caractère) dans une trame utilisée par le récepteur et l'émetteur.

UCSZ2 UCSZ1 UCSZ0 Taille du personnage

0 0 0 5 bits

0 0 1 6 bits

0 1 0 7 bits

0 1 1 8 bits

1 0 0 Réservé

1 0 1 Réservé

1 1 0 Réservé

1 1 1 9 bits

 Bit 0 - UCPOL: Polarité d'horloge

Ce bit est utilisé uniquement pour le mode synchrone. Ecrivez ce bit à zéro lorsque le mode asynchrone
est utilisé.

UBRRL et UBRRH: Registres de vitesse de transmission USART


 Bit 15 - URSEL: Sélection du registre

Ce bit sélectionne l'accès au registre UCSRC ou au registre UBRRH , car les deux registres partagent
la même adresse. L'URSEL doit être un lors de l'écriture de l'UCSRC, sinon les données seront écrites
dans le registre UBRRH.

 Bit 11: 0 - UBRR11: 0: registre de débit en baud USART.

Utilisé pour définir le débit en bauds

Exemple: supposons que Fosc = 8 MHz et le débit en bauds requis = 9600 bps.

Alors valeur de UBRR = 51.088 soit 51.

Nous pouvons également définir cette valeur avec du code c en utilisant une macro pré-processeur
comme suit.

#define F_CPU 8000000UL /* Define frequency here its 8MHz */


#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

BAUD_PRESCALE est la valeur que nous devons charger dans le registre UBRR pour définir le débit
en bauds défini.

Étapes de programmation
Initialisation de USART

1. Activer la transmission et la réception en utilisant le registre UCSRB.


2. Définissez la taille du bit de données sur 8 bits à l'aide du registre UCSRC.
3. Définissez le débit en bauds à l'aide du registre UBRR.

void UART_init(long USART_BAUDRATE)


{

UCSRB |= (1 << RXEN) | (1 << TXEN); /* Turn on transmission and reception */


UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);/* Use 8-bit char size */

UBRRL = BAUD_PRESCALE; /* Load lower 8-bits of the baud rate */


UBRRH = (BAUD_PRESCALE >> 8); /* Load upper 8-bits*/
}
Arduino - Série

Arduino prend en charge la communication série (UART). Avec cela, on peut communiquer avec un
PC ou avec d'autres modules Arduino prenant en charge l'interface de communication série.

Avec la carte Arduino, vous pouvez envoyer toutes les données du PC à la carte Arduino ou de la carte
Arduino au PC en utilisant la communication série. Mais vous n'avez pas besoin de port serila séparé
(par exemple, port RS 232) pour cette communication. Vous pouvez utiliser le port USB que vous
utilisez pour programmer Arduino afin d’effectuer une communication série comme indiqué ci-
dessous.

En termes de logiciel, la communication série va comme ci-dessous. Comme vous le savez, si vous
téléchargez le programme, celui-ci est exécuté sur un chipset Arduino. Lorsque le programme exécute
la bibliothèque Serial, il communique avec le programme Arudio Serial Monitor comme indiqué ci-
dessous.

Lorsque la fonction Serial.read () est exécutée, elle reçoit les données envoyées par Arduino Serial
Monitor. Lorsque la fonction Serial.pring () est exécutée, la carte Arduino envoie les données au port
série du PC et est éventuellement acheminée au moniteur série Arduino.

Arduino Development Environment built-in USART commands [www.Arduino.cc]


Notes:
- Arduino UNO R3: omit the “n” from the command
- Arduino Mega 2560: insert the US ART channel in use (1, 2, or 3) for “n”

Command Description

Serialn.begin() Sets Baud rate

Serialn.end() Disables serial communication. Allows Digital 1(TX) and Digital (0) RX
to be used for digital input and output.

Serialn.available() Determines how many bytes have already been received and stored in the
128 byte buffer.

Serialn.read() Reads incoming serial data.

Serialn.flush() Flushes the serial receive buffer of data.

Serialn.print() Prints data to the serial port as ASCII text. An optional second parameter
specifies the format for printing (BYTE, BIN, OCT, DEC, HEX).

Serialn.println() Prints data to the serial port as ASCII text followed by a carriage return.

Serialn.write() Writes binary data to the serial port. A single byte, a series of bytes, or an
array of bytes may be sent.
SPI dans AVR ATmega16 / ATmega32
Introduction
L'interface de périphérique série (SPI) est un protocole de connexion d'interface de bus lancé à l'origine
par Motorola Corp. Il utilise quatre broches pour la communication.

 SDI (entrée de données série)


 SDO (sortie de données série)
 SCLK (horloge série)
 CS (Chip Select)

Il possède deux broches pour le transfert de données appelées SDI (entrée de données série) et SDO
(sortie de données série). La broche SCLK (horloge série) est utilisée pour synchroniser le transfert de
données et le maître fournit cette horloge. La broche CS (Chip Select) est utilisée par le maître pour
sélectionner un périphérique esclave.

Les périphériques SPI ont des registres à décalage de 8 bits pour envoyer et recevoir des
données. Chaque fois que le maître doit envoyer des données, il place les données dans un registre à
décalage et génère l'horloge requise. Chaque fois que le maître veut lire des données, l'esclave place
les données dans un registre à décalage et le maître génère l'horloge requise. Notez que SPI est un
protocole de communication en duplex intégral, c’est-à-dire que les données des registres à décalage
maître et esclave sont échangées en même temps.

ATmega32 SPI Communication


ATmega32 a un module SPI intégré. Il peut agir en tant que périphérique SPI maître et esclave. Les
broches de communication SPI dans AVR ATmega sont les suivantes :

 MISO (Master In Slave Out)

Le maître reçoit les données et l'esclave transmet les données via cette broche.

 MOSI (Master Out Slave In)

Le maître transmet les données et l'esclave reçoit les données via cette broche.

 SCK (horloge de décalage)


Le maître génère cette horloge pour la communication, qui est utilisée par l'esclave.

Seul le maître peut initier une horloge série.

 SS (Slave Select)

Le maître peut sélectionner esclave via cette broche.

L'interconnexion entre maître et esclave à l'aide de SPI est illustrée dans la figure ci-dessous.

AVR ATmega32 utilise trois registres pour configurer la communication SPI, à savoir Registre de
contrôle SPI, Registre d'état SPI et Registre de données SPI.

SPCR: Registre de contrôle SPI

Bit 7 - SPIE: bit d'activation d'interruption SPI

1 = Activer l'interruption SPI.

0 = Désactiver l'interruption SPI.

Bit 6 - SPE: bit d'activation SPI

1 = Activer SPI.

0 = Désactiver SPI.

Bit 5 - DORD: bit d'ordre de données

1 = LSB transmis en premier.

0 = MSB transmis en premier.

Bit 4 - MSTR: bit de sélection maître / esclave

1 = mode maître.

0 = mode esclave.

Bit 3 - CPOL: bit de sélection de polarité d'horloge

1 = l'horloge commence à partir de la logique.


0 = l'horloge démarre à partir du zéro logique.

Bit 2 - CPHA: bit de sélection de phase d'horloge

1 = échantillon de données sur le bord d'horloge de fuite.

0 = échantillon de données sur le front d'horloge.

Bit 1: 0 - SPR1: bits de sélection de fréquence d'horloge SPR0

Le tableau ci-dessous montre le réglage du bit de sélection de fréquence d'horloge SCK.

SPI2X SPR1 SPR0 Fréquence SCK

0 0 0 Fosc / 4

0 0 1 Fosc / 16

0 1 0 Fosc / 64

0 1 1 Fosc / 128

1 0 0 Fosc / 2

1 0 1 Fosc / 8

1 1 0 Fosc / 32

1 1 1 Fosc / 64

SPSR: Registre d'état SPI

Bit 7 - SPIF: bit de drapeau d'interruption SPI

 Cet indicateur est défini lorsque le transfert en série est terminé.


 Est également activé lorsque la broche SS est basse en mode maître.
 Il peut générer une interruption lorsque le bit SPIE dans SPCR et une interruption globale est
activé.

Bit 6 - WCOL: Écrire un bit d' indicateur de collision

 Ce bit est activé lors de l'écriture dans le registre de données SPI lors du transfert de données
précédent.

Bit 5: 1 - Bits réservés


Bit 0 - SPI2X: bit de vitesse SPI double

 Lorsqu'il est défini, la vitesse SPI (fréquence SCK) est doublée.

SPDR: registre de données SPI

 Registre de données SPI utilisé pour transférer des données entre le fichier de registre et le
registre à décalage SPI.
 L'écriture dans le SPDR initie la transmission de données.

Quand l'appareil est en mode maître

 Le maître écrit un octet de données dans SPDR. L'écriture sur SPDR démarre la transmission
de données.
 Les données 8 bits commencent à être décalées vers l'esclave et, après le décalage de l'octet
complet, le générateur d'horloge SPI s'arrête et le bit SPIF est activé.

Quand l'appareil est en mode esclave

 L'interface SPI esclave reste en veille tant que la broche SS est maintenue au niveau haut par
le maître.
 Il s'active uniquement lorsque la broche SS est enfoncée bas. Les données sont décalées avec
l'horloge SCK entrante depuis le maître pendant l'opération d'écriture.
 SPIF est défini après le décalage complet d'un octet.

Fonctionnalité de broche SS Mode maître

 En mode maître, la broche SS est utilisée comme broche GPIO.


 Définissez la direction de la broche SS en sortie pour sélectionner le périphérique esclave
utilisant cette broche.
 Notez que si la broche SS est configurée en entrée, elle doit être réglée sur High pour le
fonctionnement principal.
 S'il est défini comme entrée en mode maître et qu'il est piloté par un circuit externe, le système
SPI le reconnaît comme un autre maître sélectionnant SPI comme esclave en raison de son
comportement actif à l'état bas.
 Cela effacera le bit MSTR dans le registre SPCR et SPI passera en mode esclave.

Fonctionnalité de broche SS Mode esclave

 En mode esclave, la broche SS est toujours configurée comme entrée.


 Quand il est bas, le SPI s'active.
 Et lorsque la logique SPI est élevée, elle est réinitialisée et ne reçoit aucune donnée entrante.
Exemple

Faisons la communication SPI en utilisant la famille AVR ATmega16 (Master) et ATmega32


(Slave). Le Maître enverra un compte continu à Slave. Affichez les données envoyées et reçues sur un
écran LCD 16x2.

Schéma d'interface

Commençons par programmer le périphérique maître, à savoir ATmega16

Étapes d'initialisation du maître SPI

Pour initialiser ATmega16 en tant que maître, procédez comme suit.

 Définissez les directions des broches MOSI, SCK et SS en sortie.


 Définissez la direction de la broche MISO en entrée.
 Faites broche SS haute.
 Activez SPI en mode maître en définissant les bits SPE et MSTR dans le registre SPCR.
 Définissez la combinaison SPI Clock Rate Bits pour définir la fréquence SCK.

Fonction SPI_Init

void SPI_Init() /* SPI Initialize function */


{ DDRB |= (1<<MOSI)|(1<<SCK)|(1<<SS); /* Make MOSI, SCK, SS as Output pin */

DDRB &= ~(1<<MISO); /* Make MISO pin as input pin */


PORTB |= (1<<SS); /* Make high on SS pin */

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); /* Enable SPI in master mode with Fosc/16 */


SPSR &= ~(1<<SPI2X); /* Disable speed doubler */

}
Étapes d'écriture du maître SPI

 Copier les données à transmettre dans le registre SPDR.


 Attendez la fin de la transmission, c.-à-d. Que le drapeau SPIF de poll est élevé.
 Alors que l'indicateur SPIF est défini, lisez SPDR à l'aide du tampon de vidage.
 Le bit SPIF est effacé par H / W lors de l'exécution du programme ISR correspondant.
 Notez que pour effacer le bit SPIF, vous devez lire les registres SPIF et SPDR en alternance.

Fonction SPI_Write Argument d'entrée: Il a l'argument d'entrée des données à transmettre.

void SPI_Write(char data) /* SPI write data function */


{ char flush_buffer;
SPDR = data; /* Write data to SPI data register */

while(!(SPSR & (1<<SPIF))); /* Wait till transmission complete */

flush_buffer = SPDR; /* Flush received data */


/* Note: SPIF flag is cleared by first reading SPSR (with SPIF set) and then accessing SPDR hence flush buffer used here to acce
ss SPDR after SPSR read */
}

Étapes de lecture du maître SPI

 Étant donné que l'écriture dans SPDR génère un SCK pour la transmission, écrivez des données
factices dans le registre SPDR.
 Attendez la fin de la transmission, c’est-à-dire le drapeau SPIF d’enquête, jusqu’à ce qu’il
devienne élevé.
 Lorsque l'indicateur SPIF est défini, lisez les données reçues demandées dans SPDR.

Fonction SPI_Read

Valeur renvoyée: Renvoie le type de données de caractères reçu.

char SPI_Read() /* SPI read data function */


{ SPDR = 0xFF;
while(!(SPSR & (1<<SPIF))); /* Wait till reception complete */

return(SPDR); /* Return received data */


}
Programme pour périphérique maître SPI

/*

* ATmega16_Master.c

* http://www.electronicwings.com
*/
#define F_CPU 8000000UL /* Define CPU Frequency 8MHz */
#include <avr/io.h> /* Include AVR std. library file */
#include <util/delay.h> /* Include Delay header file */
#include <stdio.h> /* Include Std. i/p o/p file */
#include <string.h> /* Include String header file */
#include "LCD_16x2_H_file.h" /* Include LCD header file */
#include "SPI_Master_H_file.h" /* Include SPI master header file */

int main(void)
{
uint8_t count;
char buffer[5];
LCD_Init();
SPI_Init();
LCD_String_xy(1, 0, "Master Device");
LCD_String_xy(2, 0, "Sending Data: ");
SS_Enable;
count = 0;
while (1) /* Send Continuous count */
{
SPI_Write(count);
sprintf(buffer, "%d ", count);
LCD_String_xy(2, 13, buffer);
count++;
_delay_ms(500);
}

Programme maintenant pour un appareil esclave, par exemple ATmega32


Étapes d'initialisation de l'esclave SPI

 Définissez la direction des broches MOSI, SCK et SS du périphérique en tant qu’entrée.


 Définissez la direction des broches MISO du périphérique en sortie.
 Activez SPI en mode esclave en définissant le bit SPE et en effaçant le bit MSTR.

Fonction SPI_Init

void SPI_Init() /* SPI Initialize function */


{

DDRB &= ~((1<<MOSI)|(1<<SCK)|(1<<SS)); /* Make MOSI, SCK, SS as


input pins */

DDRB |= (1<<MISO); /* Make MISO pin as


output pin */
SPCR = (1<<SPE); /* Enable SPI in slave mode */
}

Étapes de transmission esclave SPI

Il a la même fonction et les mêmes étapes que nous utilisons SPI Write en mode Master.

Étapes de réception esclave SPI

 Attendez que SPIF devienne élevé.


 Lire les données reçues du registre SPDR.

Fonction SPI_Receive

Valeur de retour: retourne le type de données de caractères reçu.

char SPI_Receive() /* SPI Receive data function */


{
while(!(SPSR & (1<<SPIF))); /* Wait till reception complete */
return(SPDR); /* Return received data */
}

Programme pour périphérique esclave SPI


/*

* ATmega32_SPI_Slave.c

* http://www.electronicwings.com
*/
#define F_CPU 8000000UL /* Define CPU Frequency 8MHz */
#include <avr/io.h> /* Include AVR std. library file */
#include <util/delay.h> /* Include Delay header file */
#include <stdio.h> /* Include std. i/p o/p file */
#include <string.h> /* Include string header file */
#include "LCD_16x2_H_file.h" /* Include LCD header file */
#include "SPI_Slave_H_file.h" /* Include SPI slave header file */

int main(void)
{
uint8_t count;

char buffer[5];

LCD_Init();
SPI_Init();

LCD_String_xy(1, 0, "Slave Device");


LCD_String_xy(2, 0, "Receive Data: ");

while (1) /* Receive count continuous */


{
count = SPI_Receive();
sprintf(buffer, "%d ", count);

LCD_String_xy(2, 13, buffer);


}

}
Arduino SPI

L'interface série périphérique (SPI) est un protocole de données série synchrone utilisé par les
microcontrôleurs pour communiquer rapidement avec un ou plusieurs périphériques sur de courtes
distances. Il peut également être utilisé pour la communication entre deux microcontrôleurs.

Avec une connexion SPI, il y a toujours un périphérique maître (généralement un microcontrôleur)


qui contrôle les périphériques. En règle générale, il existe trois lignes communes à tous les
périphériques:

 MISO (Master In Slave Out) - La ligne Slave pour l’envoi de données au maître,
 MOSI (Master Out Slave In) - La ligne Master d’envoi de données aux périphériques,
 SCK (Serial Clock) - Les impulsions d'horloge qui synchronisent la transmission de données
générée par le maître

et une ligne spécifique à chaque appareil:

 SS (Slave Select) - la broche sur chaque périphérique que le maître peut utiliser pour activer et
désactiver des périphériques spécifiques.

Lorsque la broche Slave Select d’un périphérique est faible, il communique avec le maître. Quand
il est haut, il ignore le maître. Cela vous permet d'avoir plusieurs périphériques SPI partageant les
mêmes lignes MISO, MOSI et CLK.

Pour écrire du code pour un nouveau périphérique SPI, vous devez noter quelques points:

 Arduino utilisera automatiquement la meilleure vitesse, qui est égale ou inférieure au nombre que
vous utilisez avec SPISettings .
 Les données sont-elles décalées en premier (MSB) ou au bit le moins significatif (LSB)? Ceci est
contrôlé par le deuxième paramètre SPISettings , MSBFIRST ou LSBFIRST. La plupart des puces
SPI utilisent le premier ordre de données MSB.
 L'horloge de données est-elle inactive à l'état haut ou bas? Les échantillons sont-ils sur le front
montant ou descendant des impulsions d'horloge? Ces modes sont contrôlés par le troisième
paramètre de SPISettings .

De manière générale, il existe quatre modes de transmission. Ces modes contrôlent si les données
entrent et sortent sur le front montant ou descendant du signal d'horloge de données (appelé phase
d' horloge ) et si l'horloge est inactive à l'état haut ou bas (appelée polarité de l'horloge ). Les quatre
modes combinent la polarité et la phase en fonction de ce tableau:
Clock Polarity Clock Phase Output Data
Mode
(CPOL) (CPHA) Edge Capture
SPI_MODE0 0 0 Falling Rising
SPI_MODE1 0 1 Rising Falling
SPI_MODE2 1 0 Rising Falling
SPI_MODE3 1 1 Falling Rising

Une fois que vous avez défini vos paramètres SPI, utilisez SPI.beginTransaction () pour
commencer à utiliser le port SPI. Le port SPI sera configuré avec tous vos paramètres. Le moyen
le plus simple et le plus efficace d'utiliser SPISettings se trouve directement dans
SPI.beginTransaction ().
Par exemple:

SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));

Si d'autres bibliothèques utilisent SPI à partir d'interruptions, elles ne pourront pas accéder à SPI
jusqu'à ce que vous appeliez SPI.endTransaction(). Les paramètres SPI sont appliqués
au début de la transaction et SPI.endTransaction() ne modifient pas lesparamètres
SPI. Sauf si vous ou une bibliothèque appelez beginTransaction une seconde fois, les paramètres
sont conservés . Vous devriez essayer de minimiser le temps qui s'écoule avant
d'appeler SPI.endTransaction(), pour une meilleure compatibilité si votre programme est
utilisé avec d'autres bibliothèques qui utilisent SPI.

Avec la plupart des périphériques SPI SPI.beginTransaction(), vous écrivez ensuite la


broche LOW de sélection d’esclave, appelez SPI.transfer()un nombre quelconque de fois
pour transférer des données, puis écrivez la broche SS HAUT et, enfin,
appelez SPI.endTransaction().

Exemples

 Capteur de pression barométrique : lisez la pression atmosphérique et la température d'un capteur


à l'aide du protocole SPI.
 Contrôle numérique du pot : Contrôlez un potentiomètre numérique AD5206 en utilisant le
protocole SPI.
Les connexions à la carte Arduino sont très simples à faire. Considérez le brochage du MCP4162 :

Vdd est connecté au 5 V, Vss à la masse GND, /CS au connecteur D10, SCK au connecteur D13, SDI au
connecteur D11 et enfin SDO au connecteur D12 de l'Arduino Uno. Maintenant, on fait varier la sortie
du MCP4162 avec le programme suivant :

/*
Example 34.1 - SPI bus demo using a Microchip MCP4162 digital potentiometer
http://tronixstuff.com/tutorials > chapter 34 | CC by-sa-nc | John Boxall
*/

#include "SPI.h" // necessary library


int ss = 10; // using digital pin 10 for SPI slave select
int del = 200; // used for various delays

void setup()
{
pinMode(ss, OUTPUT); // we use this for SS pin
SPI.begin(); // wake up the SPI bus.
SPI.setBitOrder(MSBFIRST);
// our MCP4162 requires data to be sent MSB (most significant byte) first
}

void setValue(int value)


{
digitalWrite(ss, LOW);
SPI.transfer(0); // send command byte
SPI.transfer(value); // send value (0~255)
digitalWrite(ss, HIGH);
}

void loop()
{
for (int a = 0; a < 256; a++)
{
setValue(a);
delay(del);
}
for (int a = 255; a >= 0; --a)
{
setValue(a);
delay(del);
}
}
I2C dans AVR ATmega16 / ATmega32

Introduction
I2C (Inter Integrated Circuit) est un protocole de connexion d'interface de bus série. Il est également
appelé TWI (interface à deux fils) car il utilise seulement deux fils pour la communication, deux fils
appelés SDA (données série) et SCL (horloge série). L’ATmega16 / ATmega32 à base d’AVR possède
un module TWI composé de plusieurs sous-modules, comme indiqué sur la figure.

I2Cworks dans deux modes à savoir,

 Mode maître
 Mode esclave

Module ATmega16 / 32 I2C

Broches SDA et SCL

 Ces broches sont utilisées pour interfacer les périphériques externes et le microcontrôleur basés
sur TWI.
 Les pilotes de sortie contiennent un limiteur de vitesse de balayage. Les étages d’entrée
contiennent une unité de suppression de pointes qui supprime les pointes inférieures à 50 ns.

Unité d'interface de bus

 L'unité d'interface de bus contient la commande marche / arrêt responsable de la génération et


de la détection des conditions START, REPEATED START et STOP.
 Le registre à décalage TWDR add / data contient des données à transmettre et à recevoir.
 Le bit ACK reçoit un accusé de réception / transfert en mode émetteur et est généré par le
logiciel en mode de réception.
 L'unité de suppression de pointes prend en charge les pointes tandis que l'état du bus de
surveillance surveille en continu la détection d'arbitrage et en informe l'unité de contrôle.
Unité de correspondance d'adresse
En mode esclave, l’unité de correspondance d’adresses reçoit l’adresse 7 bits entrante et la compare à
l’adresse du registre TWAR (registre d’adresses à deux fils) pour vérifier si elle correspond ou non.
Lorsqu’une correspondance est détectée, il est intime que la centrale prenne les mesures
nécessaires. Il considère également l'adresse d'appel générale si le bit TWGCE dans TWAR est
activé.

Unité de génération de débit


Le générateur de débit binaire contrôle la période SCL en mode maître pour générer la fréquence
SCL. Il est calculé par,

Fréquence SCL = (fréquence CLK de la CPU) / (16 + 2 (TWBR) * 4 ^ TWPS)

Où TWPS est la valeur d'un bit de pré-détartreur dans TWSR.

Unité de contrôle

 L'unité de contrôle contient TWSR (registre d'état TWI), TWCR (registre de contrôle TWI).
 Il contrôle le processus global d'attention pour les événements nécessaires, identifiant les
événements qui se produisent, l'assertion d'interruption TWINT et la mise à jour de TWSR.
 Tant que le drapeau TWINT est réglé, SCL est maintenu bas. TWINT défini chaque fois que
TWI termine la tâche en cours.

Voyons les registres dans le module ATmega16 / 32 I2C

TWBR: registre de débit binaire TWI


Registre de débit TWI utilisé pour générer la fréquence SCL tout en fonctionnant en mode maître

TWCR: Registre de contrôle TWI


Résistance de contrôle TWI utilisée pour contrôler les événements de toutes les communications I2C.

Bit 7 - TWINT: interruption TWI

 Ce bit est activé chaque fois que TWI termine son événement actuel (comme démarrer, arrêter,
transmettre, recevoir, etc.).
 Tandis que le bit I dans SREG et le bit TWIE dans TWCR sont activés, le vecteur d'interruption
TWI est appelé chaque fois qu'une interruption TWI se produit.
 L'indicateur d'interruption TWI doit être effacé par le logiciel en y écrivant une
logique. Ce bit n'est pas automatiquement effacé par le matériel.
Bit 6 - TWEA: bit d'accusé de réception d'activation TWI

 Il s'agit du bit d'activation de l'accusé de réception TWI. Il est défini en mode récepteur pour
générer un accusé de réception et effacé en mode émission.

Bit 5 - TWSTA: bit de condition TWI START

 Le dispositif maître a activé ce bit pour générer la condition START en surveillant l’état du
bus libre afin de prendre le contrôle sur le bus TWI.

Bit 4 - TWSTO: bit de condition TWI STOP

 Le dispositif maître a activé ce bit pour générer une condition STOP afin de laisser le contrôle
sur le bus TWI.

Bit 3 - TWWC: collision d'écriture TWI

 Ce bit est activé lors de l'écriture dans le registre TWDR avant la fin de la transmission actuelle,
c.-à-d. Que TWINT est faible.

Bit 2 - TWEN: bit d'activation TWI

 Ce bit est activé pour activer l'interface TWI dans le périphérique et prend le contrôle des
broches d'E / S.

Bit 1 - Réservé

Bit 0 - TWIE: activation d'interruption TWI

 Ce bit est utilisé pour activer la routine d'interruption TWI alors que le bit I de SREG est défini
tant que l'indicateur TWINT est élevé.

TWSR: Registre d'état TWI

Bit 7: Bit 3 - TWS7: TWS3: bits d'état TWI

 Les bits d'état TWI indiquent l'état de la commande et du bus TWI

Bit 1: 0 - TWPS1: TWPS0: bits de pré- détartrage TWI

 TWI bits de pré-détartreur utilisés dans la formule de débit pour calculer la fréquence SCL
TWPS1 TWPS0 Exposant Valeur du détartreur

0 0 0 1

0 1 1 4

1 0 2 16

1 1 3 64

TWDR: registre de données TWI

 TWDR contient des données à transmettre ou à recevoir.


 Ce n'est pas accessible en écriture tant que TWI est en train de déplacer un octet.
 Les données restent stables tant que TWINT est défini.

TWAR: registre d'adresses TWI

 Le registre TWAR contient l'adresse de l'unité TWI en mode esclave.


 Il est principalement utilisé dans les systèmes multi-maîtres.

Bit 7: 1 - TWA6: TWA0: bits d'adresse TWI

 Les bits d'adresse TWI contiennent une adresse TWI de 7 bits avec laquelle il peut être appelé
par d'autres maîtres en mode esclave.

Bit 0 - TWGCE: bit d'activation d'appel général TWI

 Le bit d'activation d'appel général TWI, lorsqu'il est activé, permet la reconnaissance de l'appel
général sur le bus TWI

Il existe quatre modes de transmission dans I2C dans lesquels le périphérique I2C fonctionne.

 Lorsque l'appareil est maître, il fonctionne en modes de transmission MT et MR.


 Et lorsque l'appareil est esclave, il fonctionne en modes de transmission ST et SR.
SR No. Mode de transmission Opération

1 Émetteur maître (MT) Le dispositif maître écrit des données sur SDA.

2 Maître Récepteur (MR) Le dispositif maître lit les données à partir de SDA.

3 Émetteur Esclave (ST) Le périphérique esclave écrit des données sur SDA.

4 Récepteur esclave (SR) Le périphérique esclave lit les données à partir de SDA.

Programmation de l'ATmega32 I2C en mode maître

Pour programmer l'AVR ATmega32 I2C en mode maître, vous devez d'abord initialiser le module I2C
avec une fréquence SCL, puis exécuter une opération de lecture et d'écriture à l'aide des événements
START, REPEATED START, STOP. Commençons par initialiser le module TWI dans ATmega16.

Initialisation I2C

Pour initialiserATmega16 TWI en mode maître, nous devons définir la fréquence d'horloge SCL en
définissant les valeurs dans le registre TWBR et les bits TWPS dans le registre TWSR.

La valeur TWBR est définie par la formule de fréquence SCL ci-dessus. par exemple

/* Define bit rate */


#define BITRATE(TWSR) ((F_CPU/SCL_CLK)-16)/(2*pow(4,(TWSR&((1<<TWPS0)|(1<<TWPS1)))))

Maintenant, chargez cette valeur dans le registre TWBR

void I2C_Init() /* I2C initialize function */


{ TWBR = BITRATE(TWSR=0x00); /* Get bit rate register value by formula */
}

Événements I2C

Comme l’AVR I2C est orienté octet et basé sur des interruptions, c’est-à-dire des interruptions émises
après chaque événement de bus. Des événements tels que Démarrer, Écrire, Lire, Arrêter. Le statut est
également mis à jour après chaque événement de bus. Voyons donc les événements et conditions I2C
avec leurs codes de fonction.

Événements I2C en mode Maître

DÉPARTS)

 Condition START émise par le maître.


 Il est généré par la transition haut à bas sur SDA alors que SCL est élevé.
 Lorsque le bus est libre, le périphérique maître émet une condition START avec l'adresse du
périphérique esclave (SLA) pour lancer la transmission.
Fonction I2C_Start

Cette fonction initie la condition START

Argument d'entrée: - il a l'argument d'entrée de l'adresse d'écriture du périphérique esclave (SLA + W).

Retour: - renvoie l'état de l'événement.

uint8_t I2C_Start(charwrite_address)/* I2C start function */

{
uint8_t status; /* Declare variable */

TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate START */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */


status=TWSR&0xF8; /* Read TWI status register */

if(status!=0x08) /* Check weather START transmitted or not? */

return 0; /* Return 0 to indicate start condition fail */


TWDR=write_address; /* Write SLA+W in TWI data register */

TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI & clear interrupt flag */


while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */
status=TWSR&0xF8; /* Read TWI status register */

if(status==0x18) /* Check for SLA+W transmitted &ack received */


return 1; /* Return 1 to indicate ack received */
if(status==0x20) /* Check for SLA+W transmitted &nack received */

return 2; /* Return 2 to indicate nack received */

else
return3; /* Else return 3 to indicate SLA+W failed */
}

DÉPART RÉPÉTÉ (Sr)

 Condition de départ répété émise par le maître.


 Il est généré en émettant une autre condition START pour lancer une nouvelle transmission.
 Une condition de démarrage répété avec une adresse d'appareil esclave (SLA) est émise entre
les conditions de démarrage et d'arrêt

Fonction I2C_Repeated_Start

Cette fonction génère une condition de démarrage répété pour l'opération de lecture.

Argument d'entrée: - il a l'argument d'entrée de l'adresse de lecture du dispositif esclave (SLA + R).

Retour: - renvoie l'état de l'événement.

uint8_t I2C_Repeated_Start(charread_address) /* I2C repeated start function */


{
uint8_t status; /* Declare variable */
TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT);/* Enable TWI, generate start */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

status=TWSR&0xF8; /* Read TWI status register */

if(status!=0x10) /* Check for repeated start transmitted */

return 0; /* Return 0 for repeated start condition fail */

TWDR=read_address; /* Write SLA+R in TWI data register */

TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

status=TWSR&0xF8; /* Read TWI status register */

if(status==0x40) /* Check for SLA+R transmitted &ack received */

return 1; /* Return 1 to indicate ack received */

if(status==0x48) /* Check for SLA+R transmitted &nack received */

return 2; /* Return 2 to indicate nack received */

else

return 3; /* Else return 3 to indicate SLA+W failed */

ÉCRIRE (W)

 L'événement de données / adresse WRITE est émis par le maître après l'acquittement réussi de
START reçu du périphérique esclave.

Fonction I2C_Write

Cette fonction écrit les données / adresses sur le bus

Argument d'entrée: - il a un argument d'entrée de données / adresse.

Retour: - renvoie l'état de l'événement.

uint8_t I2C_Write(chardata) /* I2C write function */

{ uint8_tstatus; /* Declare variable */

TWDR=data; /* Copy data in TWI data register */

TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

status=TWSR&0xF8; /* Read TWI status register */

if(status==0x28) /* Check for data transmitted &ack received */

return 0; /* Return 0 to indicate ack received */

if(status==0x30) /* Check for data transmitted &nack received */

return 1; /* Return 1 to indicate nack received */

else

return 2; /* Else return 2 for data transmission failure */

LIRE (R)
 L'événement de lecture de données est émis par le maître après la réussite de la condition de
répétition du démarrage.

Fonction I2C_Read_Ack

Cette fonction lit les données disponibles sur la ligne SDA et renvoie son accusé de réception au
périphérique esclave lorsque les données ont été lues avec succès. Elle demande également à l'esclave
de transmettre d'autres données.

Argument d'entrée: - il n'a pas d'argument d'entrée.

Return: - renvoie les données reçues.

char I2C_Read_Ack() /* I2C read ack function */

{ TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA); /* Enable TWI, generation of ack */


while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

returnTWDR; /* Return received data */


}

Fonction I2C_Read_Nack

Cette fonction lit le dernier octet de données nécessaire disponible sur la ligne SDA mais ne renvoie
pas d'accusé de réception. Auparavant, il indiquait à un esclave que son maître ne voulait pas de
données à venir et voulait arrêter la communication.

Argument d'entrée: - il n'a pas d'argument d'entrée.

Retour: - renvoie les données reçues.

char I2C_Read_Nack() /* I2C read nack function */

TWCR=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

return TWDR; /* Return received data */

STOP (P)

 Événement STOP émis par le maître pour indiquer qu’il doit s’arrêter.
 Il est généré par une transition faible à élevée sur SDA alors que SCL est élevé.

Fonction I2C_Stop

Cette fonction initie la condition STOP

Argument d'entrée: - il n'a pas d'argument d'entrée.

Return: - il ne renvoie aucun type de données.

void I2C_Stop() /* I2C stop function */


{
TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN);/* Enable TWI, generate stop */
while(TWCR&(1<<TWSTO)); /* Wait until stop condition execution */

Exemple

Prenons l'exemple du premier transmetteur principal (MT) et des modes de récepteur maître
(MR). Considérez ATmega16 en tant que mémoire maître et mémoire EEPROM en tant qu'esclave.
Nous pouvons écrire des données sur EEPROM en mode émetteur principal (MT) et les lire à partir de
EEPROM en mode récepteur maître (MR).

 Ici, ATmega16 est un appareil maître et l'EEPROM est un appareil esclave.

Étapes de programmation pour l'opération d'écriture:

1. Initialiser I2C.
2. Générer une condition START.
3. Envoyez l'adresse d'écriture du périphérique esclave (SLA + W) et vérifiez l'accusé de
réception.
4. Écrivez l'adresse de l'emplacement de la mémoire pour les périphériques de mémoire sur
lesquels nous voulons écrire.
5. Ecrire les données jusqu'au dernier octet.
6. Générer une condition STOP.

Étapes de programmation pour l'opération de lecture:

1. Initialiser I2C.
2. Générer une condition START.
3. Écrire l'adresse du périphérique (SLA + W) et vérifier l'accusé de réception.
4. Écrire l'adresse de l'emplacement de la mémoire pour les périphériques de mémoire.
5. Génère une condition de démarrage répété.
6. Lire les données et renvoyer l'accusé de réception.
7. Retour Pas d'accusé de réception pour le dernier octet.
8. Générer une condition STOP.

Programme
/*

* ATmega16_Master_I2C.c

* http://www.electronicwings.com

*/

#define F_CPU 8000000UL /* Define CPU clock Frequency 8MHz */

#include <avr/io.h> /* Include AVR std. library file */

#include <util/delay.h> /* Include Delay header file */

#include <string.h> /* Include string header file */

#include "I2C_Master_H_file.h" /* Include I2C header file */

#include "LCD_16x2_H_file.h" /* Include LCD header file */

#define EEPROM_Write_Addess 0xA0

#define EEPROM_Read_Addess 0xA1

int main(void)

char array[10] = "test"; /* Declare array to be print */

LCD_Init(); /* Initialize LCD */

I2C_Init(); /* Initialize I2C */

I2C_Start(EEPROM_Write_Addess);/* Start I2C with device write address */

I2C_Write(0x00); /* Write start memory address for data write */

for (int i = 0; i<strlen(array); i++)/* Write array data */

I2C_Write(array[i]);

I2C_Stop(); /* Stop I2C */

_delay_ms(10);

I2C_Start(EEPROM_Write_Addess);/* Start I2C with device write address */

I2C_Write(0x00); /* Write start memory address */

I2C_Repeated_Start(EEPROM_Read_Addess);/* Repeat start I2C SLA+R */

for (int i = 0; i<strlen(array); i++)/* Read data with acknowledgment */

LCD_Char(I2C_Read_Ack());

I2C_Read_Nack(); /* Read flush data with nack */

I2C_Stop(); /* Stop I2C */

return 0;

Programmation de l'ATmega32 I2C en mode esclave


Pour programmer l'AVR basé sur ATMéga16 I2C en mode esclave, nous devons initialiser le module
TWI. En mode esclave, l’appareil ne peut pas générer les conditions START, REPEATED START ou
STOP. Un périphérique esclave doit toujours écouter le bus TWI pour être adressé par un périphérique
maître ou un appel général. Laissez initialiser le module TWI en mode esclave.

Fonction d'initialisation de l'esclave I2C

Ici, pour initialiser ATmega16 en mode esclave, nous devons attribuer une adresse de périphérique à
7 bits dans le registre TWAR. Après l'attribution de l'adresse, nous devons activer TWI et le bit d'accusé
de réception dans TWCR. Et effacez le drapeau d’interruption TWI en y écrivant la logique 1.

Argument d'entrée: - il possède un argument d'entrée d'adresse d'esclave.

Return: - il ne renvoie aucun type de données.

void I2C_Slave_Init(uint8_tslave_address)

{ TWAR=slave_address; /* Assign Address in TWI address register */

TWCR=(1<<TWEN)|(1<<TWEA)|(1<<TWINT);/* Enable TWI, Enable ack generation */

Voyons maintenant que des événements se sont produits en mode esclave,

Écoutez le bus

 Le périphérique esclave doit toujours écouter le bus TWI pour vérifier s’il est adressé par un
maître quelconque.
 Quand il est adressé, le bit TWINT est activé. Donc besoin de surveiller le bit TWINT.

Fonction I2C_Slave_Listen

Argument d'entrée: - il n'a pas d'argument d'entrée.

Retour: - renvoie l'état de l'événement.

int8_t I2C_Slave_Listen()

{ while(1)

{ uint8_t status; /* Declare variable */

while(!(TWCR&(1<<TWINT))); /* Wait to be addressed */

status=TWSR&0xF8; /* Read TWI status register */

if(status==0x60||status==0x68) /* Own SLA+W received &ack returned */

return 0; /* Return 0 to indicate ack returned */

if(status==0xA8||status==0xB0) /* Own SLA+R received &ack returned */

return 1; /* Return 0 to indicate ack returned */

if(status==0x70||status==0x78) /* General call received &ack returned */

return 2; /* Return 1 to indicate ack returned */

else

continue; /* Else continue */

}}
Transmettre des données

 Après avoir été adressé par le maître avec l'adresse SLA + R, l'esclave doit envoyer les données
demandées.
 Les données à envoyer doivent être écrites dans le registre TWDR.
 Après l’écriture des données, activez TWI avec accusé de réception et désactivez le drapeau
d’interruption.
 Si l'accusé de réception n'a pas été reçu du maître, l'appareil esclave effacera l'indicateur
TWINT et écoutera à nouveau le bus.
 De même, si REPEATED START / STOP est reçu, le dispositif esclave effacera le drapeau
TWINT et écoutera à nouveau le bus.

Fonction I2C_Slave_Transmit

Argument d'entrée: - il a l'argument d'entrée des données de caractère à envoyer.

Retour: - renvoie l'état de l'événement.

int8_t I2C_Slave_Transmit(chardata)

{ uint8_t status;

TWDR=data; /* Write data to TWDR to be transmitted */

TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA);/* Enable TWI & clear interrupt flag */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

status=TWSR&0xF8; /* Read TWI status register */

if(status==0xA0) /* Check for STOP/REPEATED START received */

TWCR|=(1<<TWINT); /* Clear interrupt flag & return -1 */

return -1;

if(status==0xB8) /* Check for data transmitted &ack received */

return0; /* If yes then return 0 */

if(status==0xC0) /* Check for data transmitted &nack received */

TWCR|=(1<<TWINT); /* Clear interrupt flag & return -2 */

return -2; }

if(status==0xC8) /* Last byte transmitted with ack received */

return -3; /* If yes then return -3 */

else /* else return -4 */

return -4;

Recevoir des données

 Une fois adressé par le maître avec l'adresse SLA + W, l'esclave doit recevoir les données
envoyées par le maître.
 Après chaque octet reçu, l’esclave doit renvoyer un accusé de réception à son sujet.
 Si REPEATED START / STOP est reçu, l’appareil esclave effacera le drapeau TWINT et
écoutera à nouveau le bus.

Fonction I2C_Slave_Recieve

Argument d'entrée: - il n'a pas d'argument d'entrée.

Retour: - renvoie les données reçues ou l'état de l'événement.

char I2C_Slave_Receive()

uint8_tstatus; /* Declare variable */

TWCR=(1<<TWEN)|(1<<TWEA)|(1<<TWINT);/* Enable TWI & generation of ack */

while(!(TWCR&(1<<TWINT))); /* Wait until TWI finish its current job */

status=TWSR&0xF8; /* Read TWI status register */

if(status==0x80||status==0x90)/* Check for data received &ack returned */

return TWDR; /* If yes then return received data */

/* Check for data received, nack returned & switched to not addressed slave mode */

if(status==0x88||status==0x98)

return TWDR; /* If yes then return received data */

if(status==0xA0) /* Check wether STOP/REPEATED START */

{ TWCR|=(1<<TWINT); /* Clear interrupt flag & return -1 */

return -1; }

else

return -2; /* Else return -2 */

Exemple

Prenons un exemple, ici ATmega16 en tant que périphérique maître et ATmega32 en tant que
périphérique esclave. Le premier appareil maître envoie le compte à l’appareil esclave, puis le même
maître lit l’appareil esclave.

Schéma d'interface
Communication maître esclave ATmega I2C

Étapes de programmation dans l'appareil maître

1. Initialiser I2C.
2. Générer une condition START.
3. Écrire l'adresse du périphérique (SLA + W) et vérifier l'accusé de réception.
4. Après l'accusé de réception, écrivez les données sur l'esclave.
5. Générez une condition de démarrage répété avec SLA + R.
6. Recevoir des données de l'appareil esclave.

Étapes de programmation dans un appareil esclave

1. Initialise I2C avec l'adresse du périphérique esclave.


2. Écoutez le bus pour que le maître vous adresse.
3. Lorsque le périphérique maître adresse SLA + W, recevez les données de ce dernier.
4. Renvoyer l'accusé de réception après chaque octet reçu.
5. Efface le drapeau d'interruption après réception de REPEATED START / STOP.
6. Imprimer les données reçues sur l’écran LCD.
7. Écoutez à nouveau le bus pour que le maître vous adresse.
8. Une fois adressé avec SLA + R par le périphérique maître, transmettez les données au
périphérique maître.
9. Transmettez les données jusqu'à ce que NACK / REPEATED START / STOP soit reçu du
maître.
10. Efface le drapeau d'interruption après réception de NACK / REPEATED START / STOP.

Programme pour appareil maître

/*

* ATmega16_Master.c

* http://www.electronicwings.com

*
*/

#define F_CPU 8000000UL /* Define CPU clock Frequency 8MHz */

#include <avr/io.h> /* Include AVR std. library file */

#include <util/delay.h> /* Include inbuilt defined Delay header file */

#include <stdio.h> /* Include standard I/O header file */

#include <string.h> /* Include string header file */

#include "I2C_Master_H_file.h" /* Include I2C header file */

#include "LCD_16x2_H_file.h" /* Include LCD header file */

#define Slave_Write_Address 0x20

#define Slave_Read_Address 0x21

#define count 10

int main()

{ char buffer[10];

LCD_Init(); /* Initialize LCD */

I2C_Init(); /* Initialize I2C */

LCD_String_xy(1, 0, "Master Device");

while (1)

{ LCD_String_xy(2, 0, "Sending : ");

I2C_Start_Wait(Slave_Write_Address);/* Start I2C with SLA+W */

_delay_ms(5);

for (uint8_t i = 0; i < count ; i++)

{ sprintf(buffer, "%d ",i);

LCD_String_xy(2, 13, buffer);

I2C_Write(i); /* Send Incrementing count */

_delay_ms(500);

LCD_String_xy(2, 0, "Receiving : ");

I2C_Repeated_Start(Slave_Read_Address);/* Repeated Start with SLA+R */

_delay_ms(5);

for (uint8_t i = 0; i < count; i++)

{ if(i < count - 1)

sprintf(buffer, "%d ", I2C_Read_Ack());/* Read & Ack of data */

else

sprintf(buffer, "%d ", I2C_Read_Nack());/* Read & Nack to data */

LCD_String_xy(2, 13, buffer);

_delay_ms(500);

I2C_Stop(); /* Stop I2C */

}
Programme pour appareil esclave

/*

* ATmega32_Slave.c

* http://www.electronicwings.com

*/

#define F_CPU 8000000UL /* Define CPU clock Frequency 8MHz */

#include <avr/io.h> /* Include AVR std. library file */

#include <util/delay.h> /* Include inbuilt defined Delay header file */

#include <stdio.h> /* Include standard I/O header file */

#include <string.h> /* Include string header file */

#include "LCD_16x2_H_file.h" /* Include LCD header file */

#include "I2C_Slave_H_File.h" /* Include I2C slave header file */

#define Slave_Address 0x20

int main(void)

char buffer[10];

int8_t count = 0;

LCD_Init();

I2C_Slave_Init(Slave_Address);

LCD_String_xy(1, 0, "Slave Device");

while (1)

{ switch(I2C_Slave_Listen()) /* Check for SLA+W or SLA+R */

{ case 0:{

LCD_String_xy(2, 0, "Receiving : ");

do

{ sprintf(buffer, "%d ", count);

LCD_String_xy(2, 13, buffer);


count = I2C_Slave_Receive();/* Receive data byte*/

} while (count != -1);/* Receive until STOP/REPEATED START */


count = 0;

break;

case 1:

{ int8_t Ack_status;

LCD_String_xy(2, 0, "Sending : ");

do
{

Ack_status = I2C_Slave_Transmit(count);/* Send data byte */

sprintf(buffer, "%d ",count);

LCD_String_xy(2, 13, buffer);

count++;

} while (Ack_status == 0);/* Send until Ack is receive */

break;

default:

break;

}
Arduino I2C

Intoduction
I2C (Inter-Integrated Circuit) est un protocole de connexion d'interface de bus série. Il est également
appelé TWI (interface à deux fils) car il utilise seulement deux fils pour la communication. Ces deux
fils sont SDA (données série) et SCL (horloge série).

I2C est un protocole de communication basé sur les accusés de réception, c’est-à-dire que l’émetteur
recherche un accusé de réception du récepteur après la transmission des données pour savoir si les
données ont été reçues correctement par le récepteur.

I2C a deux modes à savoir,

 Mode maître
 Mode esclave

Le fil SDA (données série) est utilisé pour l’échange de données entre les appareils maître et esclave.

SCL (horloge série) est utilisée pour l’horloge synchrone entre le maître et l’esclave.

L'appareil maître établit la communication avec un appareil esclave. L'adresse d'un appareil esclave
est nécessaire pour engager la conversation. Le périphérique esclave répond à un périphérique maître
lorsqu'il est adressé par un périphérique maître.

Le périphérique I2C a une adresse unique 7 bits ou 10 bits. Ainsi, pour accéder à ces périphériques, un
maître doit les adresser par l’adresse unique 7 bits ou 10 bits.

I2C est utilisé dans de nombreuses applications telles que la lecture de l'horloge temps réel (RTC),
l'accès à la mémoire externe EEPROM. Il est également utilisé dans des modules de capteurs tels qu'un
gyroscope, un magnétomètre, etc.

Le protocole I2C utilise 2 lignes pour la communication:

1. Horloge série (SCL): C'est un signal d'horloge. Les données seront envoyées à d'autres
appareils lors d'un événement d'horloge. Seul le périphérique maître a le contrôle de cette ligne
SCL.
2. Données série (SDA): Il s'agit d'une ligne de données série utilisée pour échanger des
données entre un appareil maître et un appareil esclave.

Communication maître-esclave I2C


Le bus I2C est une configuration à drain ouvert, ce qui signifie qu’ils peuvent tirer la ligne de signal
correspondante vers le bas mais ne peuvent pas l’alourdir. Par conséquent, la ligne passera à l'état
inconnu. Pour éviter cela, les résistances de rappel doivent être connectées aux broches SCL et SDA.

Arduino I2C Pins


La carte Arduino Uno ne comporte qu'un seul module I2C, mais elle fournit ces lignes SDA et SCL à
deux emplacements différents.
Remarque: lors de la communication avec des périphériques utilisant le protocole de communication
I2C, des résistances de rappel doivent être utilisées. La valeur des résistances de rappel peut varier en
fonction des dispositifs utilisés.

Fonctions I2C pour Arduino


Wire.write (data)

Il est utilisé pour écrire (transmettre) des données sur le périphérique maître ou esclave.

Paramètre

data il peut s'agir d'une valeur à un octet, d'une chaîne de caractères, d'un tableau de données.

Résultats : Nombre d'octets écrits.

par exemple, Wire.write (7); // envoie un octet de données

Wire.write («i2c»); // envoie une chaîne à un périphérique esclave

Wire.write (a, 6); // ici a est un tableau

Wire.available ()

Cette fonction est utilisée par un maître ou un esclave pour vérifier si les données demandées sont
disponibles ou non. Il retourne le no. d'octets disponibles.

Wire.read ()

Il est utilisé pour lire les données demandées par le maître à partir de l'esclave ou pour lire les données
transmises d'un maître à un esclave.

Fonctions pour Arduino I2C Master


Remarque: chaque périphérique esclave I2C a une adresse unique. Lors de la communication via le
protocole I2C, cette adresse esclave doit être utilisée par le maître.

Remarque: chaque périphérique esclave I2C a une adresse unique. Lors de la communication via le
protocole I2C, cette adresse esclave doit être utilisée par le maître.

Arduino a Wire Library qui nous permet de communiquer avec des périphériques I2C.

Wire.begin () Il initie la bibliothèque Wire et rejoint le bus en tant que maître.


Wire.beginTransmission ( slave address )

Cette fonction commence une transmission avec le périphérique esclave I2C ayant une adresse
esclave spécifiée.

slave address Adresse 7 bits du périphérique avec lequel nous souhaitons communiquer.

Par exemple, Wire.beginTransmission (50) // commence la transmission avec l'esclave ayant


l'adresse 50

Câble. requestDe (Address, No. of byte ) OU

Câble. requestFrom (adresse, no d'octet, stop)

Cette fonction est utilisée par le maître pour demander ou recevoir des données d'un périphérique
esclave. Les données demandées peuvent être lues à l’aide de Wire.read ().

Paramètres

Address adresse de l'appareil avec lequel nous voulons communiquer

No. of byte non. d'octet doit demander

Stop C'est un booléen.

true - envoie un message d'arrêt après la demande, libérant le bus,

false - envoie continuellement un redémarrage après la demande, en


maintenant la connexion active

Résultats : Nombre d'octets renvoyés par un périphérique esclave.

par exemple, Wire.requestFrom (50, 4) // request 4 no. d'octets d'esclave ayant l'adresse 50

Wire.requestFrom (50, 4, true) // cessera de recevoir des données après 4 octets, libérant le bus

Wire.endTransmission ()

Il met fin à une transmission vers un périphérique esclave commencée par beginTransmission () et
transmet les octets mis en file d'attente par write ().

Résultats : Retour octet indiquant l'état de la transmission

Fonctions pour Arduino I2C Slave


Wire.begin (adresse)

Il initie la bibliothèque Wire et rejoint le bus I2C en tant qu'esclave avec l'adresse spécifiée.

Paramètre : Address Adresse d'esclave 7 bits, si elle n'est pas spécifiée, rejoignez le bus en
tant que maître

Wire.onReceive (gestionnaire)

La fonction de gestionnaire à appeler lorsqu'un périphérique esclave reçoit une donnée transmise d'un
maître.
par exemple

void setup() {

Wire.begin(8); // join i2c bus with address #8

Wire.onReceive(receiveEvent); // register event

Serial.begin(9600); // start serial for output

void receiveEvent (int howmany){

while (1 < Wire.available()) { // loop through all but the last

char c = Wire.read(); // receive byte as a character

Serial.print(c); // print the character

Wire.onRequest (gestionnaire)

La fonction de gestionnaire à appeler lorsque le maître demande à un périphérique esclave, ne prend


aucun paramètre et ne renvoie rien.

par exemple

void setup() {

Wire.begin(8); // join i2c bus with address #8

Wire.onRequest(requestEvent); // register event

void loop() {

delay(100);

// function that executes whenever data is requested by master

// this function is registered as an event, see setup ()

void requestEvent() {

Wire.write("hello "); // respond with message of 6 bytes

// as expected by master

Référencées :

1/ Fiche technique ATmega16 et ATmega32

2/ www.arduino.cc
3/ http://www.electronicwings.com
Servo Motor

Les servomoteurs sont d'excellents appareils qui peuvent tourner dans une
position spécifiée.

Habituellement, ils ont un bras servo qui peut tourner à 180 degrés. Un
servomoteur a tout intégré : un moteur, un circuit de rétroaction et, plus
important encore, un pilote de moteur. Il a juste besoin d'une ligne
d'alimentation, la GND et d'une broche de contrôle.

Voici les étapes pour connecter un servomoteur à l'Arduino:

- Le servomoteur a un connecteur femelle à trois broches. Le noir est généralement le


GND Connectez-le à l'Arduino GND.
- Connectez le câble d'alimentation qui, dans toutes les normes, doit être rouge à 5 V sur
l'Arduino.
- Connectez la ligne restante du connecteur servo à une broche numérique sur l'Arduino.
Exemple 1 :

Le code suivant fera tourner un servomoteur à 0 degrés, attendez 2 seconde, puis tournez-le à
90, attendez encore 2 seconde, tournez-le à 180, puis revenez en arrière.

Comment ça marche
Les servos sont des appareils intelligents. En utilisant une seule broche d'entrée, ils
reçoivent
la position de l'Arduino et ils y vont. En interne, ils ont un pilote de moteur et un
circuit de rétroaction qui s'assure que le bras du servo atteint la position souhaitée. Mais quel
type de signal reçoivent-ils sur la broche d'entrée?
Il s'agit d'une onde carrée similaire à PWM. Chaque cycle du signal dure 20
millisecondes et la plupart du temps, la valeur est FAIBLE. Au début de chaque cycle, le signal
est ÉLEVÉ pendant un temps compris entre 1 et 2 millisecondes. À 1 milliseconde, il représente
0 degré et à 2 millisecondes, il représente 180 degrés. Entre les deux, il représente la valeur de
0 à 180. Il s'agit d'une méthode très bonne et fiable. Le graphique le rend un peu plus facile à
comprendre.

Exemple 2 :

Vous aimerez peut-être aussi