Vous êtes sur la page 1sur 39

STM32

SOMMAIRE :

. introduction

. Les principaux periferiques

. Les registres

. Configurez les ports


d'entrée/sortie avec exemple

. Timer

. Les interruptions avec exemple

. ADC

. Remerciement
INTRODUCTION :
STMicroelectronics a développé depuis 2006 une
gamme de microcontrôleur appelée STM32. Ces
processeurs sont basés sur un cœur Cortex M conçu
par ARM. Comme son nom l'indique, ces STM32 sont
des microcontrôleur 32 bits.

A la fin de 2016 cette gamme comprenait 7 familles


allant de processeur très basique (STM32L0 basé
sur un Cortex M0) à des produits nettement plus
performants en terme de capacité de calcul et
d'équipements périphériques (SMT32 H7). Le rapport
de puissance de calcul entre ces deux extrêmes est
de l'ordre de 30. Toujours fin 2016, cette gamme
comprenait plus de 700 références ! Le milieu de
gamme est constitué des microcontrôleurs STM32F0 à
STM32F7.

Pour favoriser la distribution de ces produits, ce


fondeur propose un panel de cartes de
développement à bas coût qui porte le nom
générique de Nucléo et dont la grosse majorité est
basée sur des STM32F.
Les principales caractéristiques du STM32F103 sont
: jusqu à 80 GPIO, 4 timers (incluant des

fonctionnalités de PWM, de Capture et de Compare),
2 timers de type watchdog, le timer propre au
coeur Cortex, 2 ADC, 2 bus I²C, 2 bus SPI, 3
USART,1 bus CAN, 1 port USB. Bref déjà un bel
objet qui permet de piloter des process déjà
évolués et complexes notamment en nombres
d'entrées et de sorties.

+ ce qu'il faut savoir :


+ La datasheet du microcontrôleur 103xB

Ce n'est peut-être pas le plus utile et ses pages


117 pages vont globalement plus intéresser un
électronicien qui devra concevoir la carte qui
hébergera ce processeur mais c est le seul

endroit où il vous sera possible de savoir à quel


GPIO et à quels périphériques sont associés
chacune des broches du circuit. Information
intéressante au passage : on y apprend qu'il
appartient à la medium-density performance line,

+ Le Reference manual
Le morceau de choix avec ses 1137 pages est sans
conteste le Reference manual. Ce document est déjà
plus générique que le précédent puisqu il

concerne tous les STM32 F10x (101, 102, 103 105 et
107). Ce document est découpé en chapitres qui
contiennent chacun une partie ou un périphérique
bien spécifique. Par exemple le chapitre 11 est
dédié aux ADC.

Les chapitres sont structurés de la même façon :


ils débutent par une description globale, donnent
ensuite des précisions sur toutes les possibilités
de fonctionnement et se terminent par une partie
qui détaille le contenu de chacun des registres.

Le fait que ce document soit commun à toute une


série de processeurs est bien compréhensible (une
pensée émue à ce sujet envers les petites mains
chargées de rédiger de telles œuvres ) mais cela

en complique la lecture. À titre d exemple,


regardons ce qui se passe pour les GPIO (chapitre


9). Il débute ainsi :
Il est donc déjà important de savoir que nous
sommes dans la case medium density. Par la suite,
on trouve des informations comme :

On pourrait en déduire qu'il existe des ports GPIO


qui vont de GPIOA jusqu'à GPIOG. Et bien non ! Sur
le 103RB il n'y a que 4 ports (A à D) et encore D
n'existe qu'avec 3 broches de sortie. Pour le
savoir cela nécessite d'avoir déjà parcouru le
document précédent.

+ Le programming manual du Cortex M3


Ce document est aussi nécessaire : et 156 pages de
plus ! Rappelez-vous que les STM32 sont basés sur
un cœur Cortex. Ce dernier étant générique, il
possède sa propre documentation. Celui nous sera
nécessaire pour comprendre et programmer le timer
commun (appelé Systick), mais aussi les mécanismes
d'interruption.
Il y a bien sur d'autres documents qui seraient
nécessaires de consulter pour avoir une maîtrise
complète de cet ensemble matériel. Mais pour
débuter ces trois PDF sont largement suffisants.
Rassurez-vous immédiatement, nul besoin de
potasser l'ensemble de ces documents pour y
arriver. Par la suite, si on souhaite par exemple
programmer un nouveau service de PWM, il suffit
d aller directement aux pages ciblées pour y

comprendre ce qu'il convient de faire.

Les principaux périphériques :


Une application embarquée et un microcontrôleur
pourront « dialoguer » ensemble si les signaux
qu ils se transmettent sont compréhensibles et

compatibles entre eux. Cette information est


transmise par les broches du circuit et donc sera
toujours supportée par un signal électrique que
l'on peut séparer en trois grandes classes :

.les grandeurs binaires

.les grandeurs analogiques

.les grandeurs numériques (succession de


valeurs binaires dont la suite forme des valeurs
codées)

Le sens de transmission est aussi essentiel : pour


une broche donnée, on va soit du processus
physique au microcontrôleur (on dit que la broche
est en entrée) soit l'inverse (la broche est en
sortie).
Les GPIO :
Allumer une lampe, savoir qu un bouton poussoir


est appuyé, ouvrir une électrovanne tout ou rien,
détecter la présence d une pièce avec un capteur


inductif

Tous ces exemples montrent que beaucoup


d informations que l on envoie ou que l on


reçoit du process sont binaires. En étant capable
de piloter l état binaire d une broche (en


entrée ou en sortie), il devient facile d un


point de vue fonctionnel de réaliser ces services.
Même si ce n est pas le sujet ici, il faudra tout

de même s interroger sur l aspect électronique


’ ’

des branchements. Inutile d espérer allumer un


halogène de 500W sans un étage de puissance
intermédiaire.

Le timer :
La gestion du temps est une problématique
générique et essentielle pour les systèmes
embarqués et on se doute bien que les
périphériques de type timer vont répondre à ce
besoin. Mais la notion « d unité timer » est plus

subtile. Ce sont des unités qui, à la base, ne


vont que compter (ou décompter) les changements
d état (front montant, front descendant ou les

deux) d un signal binaire. On parle alors de



compteur (counter). Si l entrée de l unité est


choisie comme étant une broche du circuit, il est
possible de dénombrer un événement. Si le signal
que cette unité voit est une horloge synchrone
(donc un signal carré périodique) dont la
fréquence est fixe et connue, la conversion entre
le nombre de changements d états et le temps


écoulé est directe. On parle alors de timer bien
que le mécanisme soit strictement similaire. En
interne, un processeur possède au minimum une
horloge pour cadencer le fonctionnement du cœur.
Les unités de timer sont donc naturellement
connectées à de telles horloges via un diviseur de
fréquence pour pouvoir choisir la base de temps.

Les signaux sont aussi de type binaire


puisqu intrinsèquement la succession de valeurs

binaires ne codent pas de valeurs.

Ramené à sa plus simple expression, un


compteur/timer n est rien d'autre qu un registre

qui s incrémente ou qui se décrémente en fonction


de ce qu il voit à son entrée.



Rien ne peut donc lui arriver de bien méchant sauf
le débordement (overflow ou underflow). En effet,
le registre est à capacité finie, par exemple un
registre de 16 bits. Aussi en comptage lorsqu il


vaut 0xFFFF et qu un nouveau front apparait il ne

peut basculer que vers 0 ; toute l information


précédemment accumulée est alors perdue, ce qui
peut être fort regrettable. Un tel événement est
heureusement détectable car l unité va alors

émettre une requête d interruption pour que le


programme puisse réagir en conséquence.


Lors de ce débordement, un autre mécanisme se met
en place : plutôt que de repartir à 0, l unité va

repartir d une valeur prédéfinie à l avance


(c est-à-dire stockée dans un registre ad-hoc,


nommé généralement reload). Le temps entre deux


débordements est alors modifié.
Comme la base de temps est ajustable (diviseur de
fréquence) et que l on peut aussi programmer le

nombre de fronts qui pourra intervenir entre deux


requêtes d interruptions successives (reload), il

est possible de mettre en place des événements


logiciels synchrones de façon très précise à
l aide de ces timers.

Dans le périmètre des timers on trouve aussi la


notion de Watchdog. Ces timers spécifiques sont
des mécanismes qui existent pour s assurer que le


système (le programme en l occurrence) ne reste


pas bloqué dans le traitement qu il exécute


(typiquement une boucle infinie). C est donc une


sorte de sablier qu il faut venir retourner avant

qu il ne se soit vidé. S il est vide alors une



alerte (interruption) est levée. Bien évidemment
le temps propre au watchdog (la quantité de sable
dans le sablier) est paramétrable.

Les Capture/Compare :
Ces unités sont en quelque sorte des sous-
fonctions des timers. Elles sont parfois
directement associées aux unités timer, parfois
elles sont indépendantes, mais auquel cas, elles
intègrent une capacité propre de type timer.
La fonction Capture consiste à dater un évènement
lorsqu apparaît sur une broche du circuit un

front montant ou un front descendant ou un des


deux. L unité capture est donc associée à un

signal de type binaire sur une broche, à un timer


qui mesure le temps qui passe et à un registre
pour stocker la valeur capturée du timer lorsque
l événement apparait. Exemple d application : je


mesure le temps pendant lequel un bouton poussoir
a été appuyé.
La fonction Compare est un peu le symétrique. Il
y a toujours un signal de type binaire, mais le
timer est remplacé par un compteur qui compte les
événements (toujours les fronts) qu il détecte


sur la broche. Il a également, stocké dans un
registre interne, une valeur dite de comparaison.
Lorsque le compteur égale cette valeur l unité va


déclencher une demande d interruption. Exemple

d application : je compte le nombre de pièces qui

sont passées sur mon tapis roulant et je déclenche


une action quand 100 pièces ont été détectées.

L'ADC :
Le monde que l on cherche à piloter peut nous

indiquer son état à travers de grandeurs physiques


(température, pression, distance, accélération,

). L électronicien de service aura équipé le


process d un capteur qui transforme cette


grandeur en une grandeur proportionnelle en volts.


Nous sommes en présence alors d un signal de type
’’

analogique dont on espère que l échelle de


grandeur soit compatible avec notre
microcontrôleur (typiquement [0V - 5V]).
Le processeur lui ne connait que le monde
numérique, il faut donc une unité spécialisée qui
réalise cette transformation : l Analog Digital

Converter.
Très généralement cette unité est branchée sur un
multiplexeur, c est à dire que plusieurs broches


sont capables de porter un signal analogique et
qu il revient au programmeur de sélectionner

logiciellement sur quelle(s) voie(s) d entrée du


multiplexeur il doit connecter l ADC.

Une grandeur importante qui qualifie un ADC est sa


résolution, c est-à-dire la quantité de valeurs

entières que peut prendre l'ADC après conversion.


Elle peut être donnée par :
le nombre de bits du registre de conversion (par
exemple 12 bits),
le nombre de valeurs différentes de conversion
(par exemple 1024=210),
le quantum en volts entre deux valeurs numériques
de conversion (par exemple si la pleine échelle
est de [0V - 5V] on obtient 4,88mV=51024).
La PWM :
Le symétrique d un ADC est un DAC (Digital Aanlog


Converter) qui permet de transformer une valeur
numérique en une valeur analogique proportionnelle
permettant de commander le process. Cependant ces
unités sont peu courantes dans une gamme complète
de microcontrôleur. La raison principale est que
ce genre de circuit consomme beaucoup (on
transfère directement de l énergie électrique).
’’
On peut d autant mieux s en passer qu une unité


Pulse Width Modulation peut très correctement
remplacer un DAC.

Comprendre la notion de registre


Sur les microcontrôleurs les périphériques sont
configurés et contrôlés à travers des registres
ayant une adresse mémoire réservée. Cela signifie
que l accès et la configuration d un

périphérique se fait au niveau du code simplement


en écrivant ou en lisant à des adresses mémoires
spécifiques.

Un registre est généralement de la taille d un


mot du processeur, par exemple de 32 bits pour le


STM32, et chaque bit qui le compose peut avoir une
fonctionnalité différente. Prenons à titre
d exemple le registre CR1 qui est associé à un

timer (vous verrez dans la suite ce qu est un



timer) sur un STM32F103, la documentation de ce
microcontrôleur nous en fournit la description
suivante :

Ce tableau permet de savoir que les bits 10 à 31


du registre CR1 ne sont pas utilisés et que les
bits 0 à 9 ont des fonctions bien particulières.
Toujours dans la même documentation, en consultant
la description de ce registre (p. 403), nous
apprenons que le bit 0, nommé CEN, sert à mettre
en marche ou à stopper le compteur du timer, et
que les bits 5 et 6, nommés CMS, permettent de
configurer la manière dont le timer compte (en
incrémentant, en décrémentant, etc.).
Cet exemple montre que les bits d un registre

doivent être considérés de manière indépendante et


que pour configurer un périphérique il faut être
capable de modifier un ou plusieurs bits sans
modifier les autres. Pour réaliser cela, nous
allons utiliser des masques logiques avec des
opérateurs bit-à-bit.
Configurez les ports d'entrée/sortie
Un microcontrôleur interagit avec les éléments
extérieurs par le biais de plusieurs fils que
l on appelle broche, ou pin en anglais. Ces

broches sont regroupées généralement par paquet de


8 (octet) ou 16 (mot) pour former ce que l on


nommera par la suite des ports d entrée/sortie


(I/O ports). Du point de vue logiciel, un port est
un ensemble de registres.
Une broche peut être pilotée soit directement par
le biais de registres dédiés (on parle alors de
General Purpose Input Output, GPIO) soit
indirectement par le biais d un périphérique (on


parle alors d Alternate Function). Dans tous les

cas, il sera nécessaire de configurer l'étage
électronique qui permet d'interfacer le matériel
et le logiciel.

Dans la grande majorité des cas, les différentes


broches d un même port sont configurables

indépendamment des autres broches.


Sur cette famille de microcontrôleur, le nombre de
ports disponibles varie en fonction de la taille
du boîtier. Pour la carte nucleo qui vous a été
proposée, le boîtier LQFP64 a seulement quatre
ports de disponibles. Ils sont identifiés par les
lettres A, B, C et D. Les ports A, B et C ont
chacun 16 broches et le port D seulement 3.
Le STM32F103-LQFP64 peut avoir au mieux 51 broches
utilisables pour s interfacer avec un process. A

noter que pour d autres versions de ce


processeurs (en boiter LFPQ100 par exemple), il


est possible de trouver jusque 7 ports GPIO, d où


l existence dans la documentation des ports E, F

et G qui n ont pas de réalité dans le


microcontrôleur sur lequel nous basons nos
exemples.
Pour désigner un port, nous utiliserons par la
suite la notation GPIO suivie de la lettre le
désignant. Ainsi GPIOA désigne le port A. On
ajoutera parfois un point suivi d un nombre pour


désigner la broche, ainsi GPIOB.10 désigne la
broche 10 du port B. Comme les différents ports
sont structurés et fonctionnent de la même
manière, la documentation fait généralement
référence aux GPIOx, où x est à remplacer par la
lettre correspondante au port concerné.
Trouver la bonne adresse
Pour la famille des microcontrôleurs STM32F1xx, le
document de référence est le
https://cutt.ly/auvqrEv disponible sur le site de
la société ST. Nous pouvons y trouver la liste des
adresses associées à chaque périphérique. Ainsi,
nous découvrons page 50 que, par exemple,
l ensemble des registres du port B sont fixés sur

la plage mémoire de 0x4001 0C00 à 0x4001 0FFF.


trouver les différents registres d'un port
Pour répondre à cette question, il faut de nouveau
explorer la documentation .vous aurez compris que
sans consulter les documents techniques, il est
impossible de faire le travail et se référer au
chapitre dédié au GPIO (chapitre 9, page 158). Au
début du chapitre, nous trouvons une description
générique du périphérique et à la fin un tableau
qui présente sous forme synthétique l'ensemble de
ses registres (p. 193). Une description bit à bit
des registres est aussi faite dans des sections
dédiées.
Le registre contenant l'état des broches est nommé
GPIOx_IDR. D'après le tableau, il a un offset de
0x08, ce qui signifie que l'adresse de GPIOx_IDR
est celle de base du port x auquel s'ajoute un
décalage de 0x08, soit pour le port B une valeur
de 0x4001 0C08.
Pour lire la valeur du registre IDR du port B :
valueIDR = *(int *)0x40010C08;
À noter que la variablevalueIDR contiendra alors
la valeur logique des broches du port B.
Pour résumer, si on souhaite manipuler le registre
GPIOx_IDR, il faut chercher l'adresse de base du
périphérique, puis décaler cette adresse de la
valeur d'offset propre au registre.
Configurer la direction
Concentrons-nous sur les registres pour configurer
les broches d'un port. D'après la documentation,
ce sont les registre GPIOx_CRL et GPIOx_CRH qu'il
faut utiliser pour configurer la direction d un


port.

Malheureusement, on constate qu'il faut quatre


bits pour configurer un seul port et qu'il y a
huit configurations possibles. Le tableau ci-après
décrit toutes les possibilités.
Reprenons : il y a 16 broches sur un port, il faut
4 bits par broche pour la configurer en entrée ou
sortie, soit 64 bits pour configurer l ensemble

des broches d un port. Or un registre fait 32


bits. Il faut donc deux registres pour configurer


l ensemble des broches du même port d où
’’

l existence de deux registres : CRL et CRH.


Le registre CRL (L pour low) permet de configurer
les broches de 0 à 7 et le registre CRH (H pour
high) de 8 à 15.
Supposons que nous voulions configurer la broche 5
du port A en entrée (input floating). Il faut
alors affecter la valeur binaire 0b0100 aux bits
b23 b22 b21 b20 du registre CRL. Pour cela on
écrit simplement

Dans la même idée, pour mettre la broche 10 du


port A en sortie (output push-pull), il faut fixer
la valeur 0b0001 aux bits b11 b10 b9 b8 dans le
registre CRH, soit

Lire les valeurs en entrée


En continuant l exploration des registres liés à

un port, on rencontre le registre IDR qui contient


sur ses 16 premiers bits une image de l'état des
broches. Pour connaître cette valeur, il suffit
donc d aller lire le registre IDR.

Supposons que nous voulons connaître la valeur de


la broche 7 du port C, nous écrivons alors
simplement :

Écrire sur un port en sortie


Contrôler l'état d une broche en sortie n est

pas compliqué. Pour cela nous utilisons le


registre ODR, dont les seize premiers bits fixent
l'état de chaque broche en sortie d un port.

Ainsi pour mettre à 1 la broche 8 du port B, nous
fixons simplement à 1 le bit 8 de ODR, soit

EXEMPLE :
Passons à un exemple concret. Vous allez créer un
programme qui allume la led branchée sur la broche
5 du port A et l éteindre quand le bouton USER

est appuyé, bouton qui est branché sur la broche


13 du port C.
Pour réaliser la suite, il vous faut un projet
configuré (voir la partie 1) avec un main qui ne
fait rien, mais qui inclut le fameux fichier
STM32f10x.h. Votre fichier main.c contient donc
uniquement les lignes suivantes :

Pour commencer, ajouter dans le main avant la


boucle while(1) la ligne

Nous voulons que GPIOA.5 soit en sortie (output


push-pull) et GPIOC.13 en entrée (input floating),
soit :
.Affecter la valeur b0001 aux bits 20 21 22 23
du registre CRL de GPIOA :

.Affecter la valeur b0100 = 0x04 au bits 20 21


22 23 du registre CRH de GPIOC :

Pour vérifier que cela est bien fait, compilez le


code en simulation, puis lancer le debug. Mettez
un point d arrêt au niveau de la bouclewhile.

Ouvrez les fenêtres peripheral->GPIOA et


peripheral->GPIOC. Lancez l'application et
parcourez les broches pour observer leur
configuration.
Maintenant, vous allez mettre en place dans la
boucle une scrutation de l état du bouton USER.

Ce bouton est branché sur le GPIOC.13. En écrivant

le bit 13 du registre IDR du port C est évalué à


chaque fois que la boucle est exécutée. On regarde
donc si le bouton est pressé ou non.
Changeons maintenant l'état de la broche 5 du port
A pour allumer et éteindre la led à chaque appui
sur le bouton. Pour cela nous allons tester la
valeur actuelle de la broche et l'inverser.
Ajoutez dans la boucle while(1) :
Cette opération peut être réalisée bien plus
efficacement avec un XOR avec 1 sur le bit 5, soit
en remplaçant le code précédent par les lignes :

Pour tester cela, compilez en simulation, placez


un point d arrêt au niveau du test (GPIOA->ODR=

GPIOA->ODR ^ (1 << 5)) et ouvrez les fenêtres de


débug de GPIOA et GPIOC.
Après avoir lancé l exécution vous pouvez changer

l état du bit 13 de IDR pour le GPIOC en cliquant


simplement dans le carré représentant le bit qui


vous intéresse (ligne Pins dans le fenêtre d'un
port).
Faites avancer l exécution et observer la valeur

de ODR de GPIOA. Changez la valeur de IDR pour le


GPIOC et observez de nouveau ODR de GPIOA, faites
avancer plusieurs fois l exécution.

Normalement vous constaterez que nous n avons pas


le comportement souhaité car la led change d état


tant que le bouton USER est pressé, or nous


voulons seulement modifier la led quand le bouton
est pressé.
une solution simple est donc de simplement
mémoriser l état précédent du bouton en ajoutant

une nouvelle variable qui stocke l état précédent


du bouton. Pour cela, déclarez dans le main une
variable state :

Il faut maintenant changer l état de la led


uniquement si state est différent de l état



actuel du bouton et enfin, ne pas oublier de
mettre à jour state, soit

Compilez, lancez le débogueur et observer le


comportement de votre led quand vous changez
l état de GPIOC.13.

Principe des timers


Un timer est avant tout un compteur électronique.
Il a une résolution qui dépend de son architecture
et contraint l amplitude des valeurs sur

lesquelles il peut compter. Ainsi un timer avec


une résolution de 8 bits pourra compter entre 0 à
255, un timer de 16 bits entre 0 à 65 535 et une
timer de 32 bits de 0 à 4 294 967 295 ! A noter
que dans de nombreuses architectures il est
possible de « mettre en série » deux timers du
processeur. Ainsi si on dispose de 2 timers 16
bits en les sérialisant, on peut fabriquer un
timer 32 bits.
L incrémentation d un timer se fait sur des


événements. Ces événements sont usuellement
générés par une horloge avec une fréquence fixée.
Dans ce cas, le timer

compte le temps


d où


son nom. Il est cependant possible de configurer
le timer pour compter des événements qui ne sont
pas périodiques, par exemple un signal venant
d une broche et présentant des fronts montants et

descendants. Dans ce cas, on parle alors plutôt de


compteur pour désigner le timer. Dans la suite,
nous ne nous focaliserons que sur le comportement
du timer dans le cas d une horloge comme source

d événements.

Calculer les paramètres d'un timer


En connaissant la fréquence de l horloge entrante

du timer et en réglant le prescaler et


l

autoreload il est possible de régler finement


la fréquence à laquelle le timer déborde.
La formule pour obtenir la période à laquelle le
timer déborde est donnée par :
Supposez que vous avez une horloge à 72 Mhz,
comment régler le prescaler et l autoreload pour


obtenir un débordement du timer toutes les
secondes ?
Considérons le cas où le prescaler vaut 1, nous
avons alors :

Configurer un timer sur le STM32F103


Passons à la pratique pour le micro-controlleur
STM32F103. D après la documentation, nous
’’

apprenons qu il y a plusieurs timers disponibles


et qu ils sont de deux espèces différentes : la

première est constituée des timers 1 et 8 qui sont


des Advanced-control timers alors que les timers 2
à 5 sont désignés comme étant des General-purpose
timers. Nous ne verrons pas ici la différence
entre ces deux espèces et nous focaliserons sur
les timers 2 à 5.
Enfin, parmi les registres de configuration d un

timer nous trouvons ARR pour l autoreload et PSC


pour le prescaler. Remarquons au passage que le


prescaler divise par 1 pour la valeur 0, par 2
pour la valeur 1, etc. Il faut donc dans la
formule précédente considérer que
Nous allons configurer le timer 2, désigné par
TIM2 dans le fichier stm32f10x.h et commençons
avec un projet contenant uniquement un main vide.

la ligne 4 permet de configurer les horloges on


verra aprés
Pour configurer le timer 2, il suffit donc
d'ajouter avant la boucle while les lignes :

Il ne vous reste plus qu à démarrer


le timer.
Pour cela, la documentation (p. 404) indique que
le bit 0, nommé CEN, du registre CR1 permet de
lancer et d arrêter le compteur. Il

faut donc
ajouter

pour lancer le compteur. Remarquez que le masque


du bit CEN est défini dans le fichier stm32f10x.h
et qu il est possible d écrire directement


Compiler et passer en debug pour vérifier votre
configuration. Mettez un point d arrêt sur la


ligne TIM2->CR1 |= TIM1_CR1_CEN et ouvrez la
fenêtre liée au timer 2 dans Peripheral. Vous
devriez observer que les registres ARR et PSC
prennent bien les valeurs 0x270F (pour 9999) et
0x1C1F (pour 7199).
Avancez le simulateur pour lancer le comptage et
observez que le compteur, représenté par le
registre CNT, s incrémente bien.

Les interruptions :
Classiquement une interruption est provoquée par
une source extérieure au processeur comme un
périphérique. Le processeur doit donc être capable
de différencier les différentes sources pour
réaliser le traitement voulu. Pour gérer cela, le
processeur dispose d un gestionnaire

d interruption (le NVIC) dont le rôle est


’’

d associer à chaque interruption sa fonction de


traitement.
Comme nous l avons vu, pour utiliser le mécanisme

d interruption en provenance d un périphérique,


il va falloir :
.autoriser le périphérique à lancer une
interruption ;
.configurer le processeur pour gérer
l'interruption ;
.écrire le code associé à l


interruption.
EXEMPLE :
Pour illustrer ces trois étapes, nous allons
réaliser le clignotement de la LED vu dans le
chapitre précédent, non plus par scrutation, mais
avec une interruption. Pour cela, commençons avec
le code suivant pour lequel le timer 2 est
configuré pour déborder toutes les secondes et la
broche 5 du port A est configurée en sortie pour
contrôler la LED USER.

Autorisez l'interruption sur un périphérique


Le débordement d un timer peut être la source

d une interruption. Ainsi, la documentation (p.


409) nous indique que le bit 0, noté UIE, du


registre DIER, permet de contrôler le lancement de
l interruption d un timer. Il faut donc le

passer à 1.
Ainsi en ajoutant, la ligne suivante avant le
lancement du timer.

une demande d interruption sera ainsi transmise



au NVIC à chaque fois que le timer déborde.
Scruter ou interrompre un événement
C est vrai, mais la scrutation est globalement

inefficace car le processeur va passer la plupart


de son temps à attendre qu un état change, alors

qu il pourrait faire autre chose !


De plus, l interruption permet un traitement plus


réactif car le traitement va survenir dès que


l interruption se produit. Alors que dans le cas

de la scrutation, il faut attendre que toute la


boucle soit parcourue avant de détecter le
changement (dans notre cas la boucle ne fait pas
grand chose, mais le traitement pourrait être
beaucoup plus long). Si le signal à observer
change très vite, il se pourrait donc que la
scrutation ne permette pas d observer ce

changement.
Donc, essayez, dans la mesure du possible, de
favoriser une implémentation avec des
interruptions.
Le microcontroleur STM32 a deux types

d'interruptions :
les exceptions systeme
• • •
les interruptions externes numérotées de 0 a 59
le numéro de l'interruption en cours de service
peut-être connue par
le registre spécial IPSR (Interrupt

Program Status Register)


le registre ICSR (Interrupt Control State

Register) du NVIC (Nested Vectored Interrupt


Controller) dans le champs VECTACTIVE
les interruptions ont des priorités permettant

d'avoir un système préemptif

- Exception du systeme :

-Interruption externes :
-ADC STM32 : caracteristiques principales

• Résolution de 12 bits
• Interruption de fin de conversion
• Mode simple conversion ou conversion continue
• Mode de balayage multi-canal
• Auto-Calibration
• Alignement des donn´ees sur 16 bits (droite ou gauche)
• Temps de conversion programmable canal par canal
• Déclenchement par signal externe
• Mode de conversion discontinue lors de balayage
• Chainage de convertisseur (si le circuit en possède au
moins 2)
• Tension requise entre 2,4 V et 3,6V
• Plage de conversion entre Vref − < Vin < Vref +
• Requete DMA pour la conversion régulière

-ADC STM32 : Schema

-ADC STM32 : Desciption fonctionnelle


Mise sous tension
Mise sous tension via la mise a 1 du bit ADON (registre

CR2 de l'ADC)
La premi`ere mise `a 1 du bit ADON met sous tension

l'ADC
La seconde mise a 1 du bit ADON d´emarre la conversion

La mise hors tension et l'arrêt de la conversion s'effectue


en mettant a 0 le bit ADON


En mode hors tension l'ADC ne consomme que

quelques µA .
Horloge
l'horloge ADCCLK du convertisseur est synchrone

avec celle du bus APB2, l'horloge PCLK2 .


Il est possible de programmer un prédiviseur, par

rapport a PCLK2 , pour l'horloge ADCCLK dans le contrôleur


RCC
Mode Simple Conversion
Bit CONT a 0 (registre CR2)

D´emarrage par bit ADON uniquement pour groupe


réguliers
Une fois le canal converti

La donnée convertie est stockée dans le registre



16bits DR
Le drapeau EOC est positionnée

Une interruption est générée si le bit EOCIE est a 1


Mode Conversion Continue


Bit CONT a 1 (registre CR2)

Démarrage par bit ADON uniquement pour groupe


réguliers
Une fois le canal converti

La donnée convertie est stockée dans le registre


16bits DR
Le drapeau EOC est positionnée

Une interruption est générée si le bit EOCIE est a 1


registres ADC :
Remerciement :
Avec un grand plaisir que j'ai realisé ce travail
et je voulais vous remercier infiniment car vous
m'avez donné l'occasion de decouvrir ce type de
microcontrolleur 'STM32'.
Réaliser par : BENHMIMOU MEHDI