C embarqué ADC Quoi ? Quand ? Comment ? Où ?
Conclusion
Variables C et classes de stockage
Microcontrôleurs II - S6 Qu’est-ce qu’une variable C du point de vue d’un
Utilisation du Convertisseur microprocesseur ?
Une variable est un nom qui désigne une donnée, et aussi son
Analogique-Numérique adresse mémoire si cette donnée est placée dans une
mémoire. Le langage C distingue trois types de variables en
fonction de leur classe de stockage (storage class).
Pierre Corbineau
I Les variables de classe static
IESE3 S6 I classe par défaut des variables globales
I Les variables de classe auto
2024–2025 I classe par défaut des variables locales
I Les variables de classe extern
I accès à l’espace mémoire des périphériques du système
La classe de stockage détermine deux choses :
I où la variable est placée en mémoire.
I comment et quand la variable est initialisée.
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Variables statiques et sections de données Variables automatiques et pile
Les variables de classe static sont placées en mémoire à
une adresse fixée à la compilation et initialisées au chargement
du programme :
Les variables de classe auto (variables locales) sont placées
I Les static const sont placées dans la mémoire Flash.
dans les registres du CPU ou dans la pile, ou les deux (au
(section .rodata) et n’ont pas besoin d’être initialisées.
I Les static mutables (non constantes) sont placées en choix du compilateur).
RAM (section .data). I Elles sont initialisées pendant l’exécution du programme
I On stocke dans la Flash leur valeur d’initialisation et on la I Pas de différence de placement entre const et mutables.
recopie dans la RAM au moment du reset.
I Certaines variables intermédiaires peuvent être éliminées
I Si la valeur d’initialisation est 0, la variable est placée en
du calcul par les optimisations du compilateur.
section .bss (section initialisée à 0 au reset).
I Conséquence : il est difficile de connaître à l’avance
Remarque : On peut déclarer une variable locale statique, elle
l’adresse d’une variable locale.
se comporte comme une variable globale à portée locale.
uint32_t compteur() {
static uint32_t c=0;
return (c++); }
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Variables externes et périphériques La conversion analogique/numérique
Les variables de classe extern ne sont pas placées en
mémoire ni initialisées par le compilateur. Leur adresse est
déterminée lors de l’édition de liens. On distingue deux
utilisations : Principe : Conversion d’une tension en valeur numérique
I Partage de variables globales déclarées dans d’autres exploitable par un programme.
fichiers ou bibliothèques
Les questions à résoudre :
I Déclaration de variables pour représenter des objets
I Que veut-on mesurer ?
présents dans l’espace mémoire du système :
(périphériques GPIOA, SysTick ...) I Quand veut-on mesurer ? Pendant combien de temps ?
I Les zones mémoires modifiées par le matériel doivent être I Comment sont codés les résultats ?
déclarées volatile pour forcer le compilateur à les relire. I Où sont stockés les résultats ?
Exemple tiré de sys/devices.h :
extern const uint16_t TS_CAL2; /∗ valeurs programmées d’usine ∗/
extern const uint16_t TS_CAL1;
extern const uint16_t VREFIN_CAL;
. . .
extern volatile struct GPIO_registers GPIOA; /∗ périphériques ∗/
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Avant de commencer : Allumage Avant de commencer : les horloges
Les convertisseurs analogique-numérique ADC1-3 sont reliés
au bus APB2.
I En TP, ce bus est cadencé à 84MHz.
Pour utiliser les convertisseurs ADC1, ADC2, ADC3 : Il faut
valider leurs horloges (ex : ADC1) Les convertisseurs utilisent l’horloge ADCCLK pour leur parties
analogiques.
enable_ADC1();
I Selon la datasheet, il faut que fADCCLK ≤ 36MHz.
Il faut aussi allumer la partie analogique du convertisseur : ADCCLK est une division de l’horloge PCK2 du bus APB2 par
ADC1.CR2|=1; /∗ ADON=1 ∗/ un prédiviseur configurable.
ADC2.CR1|=1<<8; /∗ SCAN=1 (conversion multiples) ∗/
ADC_common.CCR
On va donc choisir une division par 4 (ADCPRE=01).
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Que veut-on mesurer ? (1) Que veut-on mesurer ? (2)
Un convertisseur peut mesurer une
En général, on programme le convertisseur pour effectuer
tension à la fois. Elle est choisie
plusieurs mesures successives sur des canaux différents :
parmi un ensemble de sources de
signaux (les canaux) :
I canaux internes
I capteur de température TS ADC1.SQR1
I tension de référence Vrefint
I canaux externes
I GPIO en mode analogique
(MODER=0b11)
ADC1.SQR2
ADC1.SQR3
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Que veut-on mesurer ? (3) Quand veut-on mesurer ?
Exemple : On veut mesurer les canaux 3, 4, 5, 3 (à nouveau) ,
7, 9, 10, 12.
ADC1.SQR1=7<<20; /∗ 7+1=8 canaux à mesurer ∗/
ADC1.SQR2=(12<<5) | 10; /∗ canaux 10,12 ∗/
ADC1.SQR3=(9<<25) | (7<<20) | (3<<15) | (5<<10) | (4<<5) | 3; ADC1.CR2
La séquence de mesure peut être déclenchée :
On peut aussi programmer une deuxième séquence de
I Par logiciel : écriture d’un 1 sur le bit SWSTART (ou
mesures, dite injectée car elle peut interrompre la séquence
régulière : JSWSTART pour la séquence injectée).
I Par matériel : détection d’un évènemement matériel
TIMER ou EXTI.
ADC1.JSQR I EXTEN ou JEXTEN pour valider les fronts actifs
I EXTSEL ou JEXTSEL pour choisir le signal source
I Indéfiniment : CONT=1 indique le mode continu où les
mesures sont relancées à chaque fin de séquence.
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Pendant combien de temps mesurer ? (1) Pendant combien de temps mesurer ? (4)
La durée d’échantillonnage se configure en périodes par
rapport à l’horloge ADCCLK@21MHz.
Pour chaque canal, on peut programmer la durée
d’échantillonnage pendant laquelle on mesure la tension
d’entrée. ADC1.SMPR1
La durée d’échantillonnage est un compromis :
I Plus courte, elle permet de prendre des échantillons plus
rapidement, et donc plus fréquemment. ADC1.SMPR2
I Plus longue, elle permet de rester précise même pour des
sources d’impédance trop forte.
Exemple : on veut mesurer le canal 18 (TS) avec une durée
supérieure à 10µs, soit au moins 10*21=210 cycles ADC, on
choisit donc SMP18=0b111 (480 cycles).
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Quand sait-on que la mesure est terminée ? Comment ? Résolution de la mesure
I Une tension mesurée est codée sous la forme d’un
nombre binaire sur r bits (résolution).
I Une tension V donne un résultat x lorsque
ADC1.SR x V x+1
rc_w0 = read, clear by writing 0 2r ≤ VDDA ≤ 2r .
I Les indicateurs EOC et JEOC permettent de savoir si une I Réduire la précision de mesure permet de rendre celle-ci
séquence normale ou injectée s’est achevée. plus rapide.
I Les indicateurs STRT et JSTRT permettent de savoir si I La valeur numérique mesurée est inversement
une séquence normale ou injectée a été lancée. proportionnelle à la tension de référence VDDA .
Exemple : attendre la fin d’une séquence injectée (JEOC=1) La résolution peut être configurée dans le registre CR1 :
while((ADC1.SR & 4) == 0); /∗ ne pas oublier ; ou {} ∗/
Exemple : On mesure 123410 sur un canal avec une résolution
de 12 bits et VDDA = 3, 3V ; la tension mesurée est donc
environ 3, 3V ∗ 1234/4096 = 0, 994V .
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Comment ? Codage de la mesure Où ? Résultats d’une séquence
Les résultats d’une séquence injectée :
I disponibles après la fin de séquence dans ADC1.JDR1 à
ADC1.JDR4.
I Les r bits significatifs d’une mesure sont rangés dans les Les résultats d’une séquence ordinaire sont stockés dans un
16-bits de poids faible d’un registre de données 32 bits. unique registre de données ADC1.DR.
I On peut choisir de placer ces bits en position de poids fort I Si une seule mesure dans la séquence (L=0 ou SCAN=0)
(alignement à gauche) ou de poids faible (alignement à I Le résultat est disponible dans ADC1.DR
droite). I Sinon, chaque nouveau résultat efface le précédent :
I il faut recopier ailleurs chaque résultat avant qu’il ne soit
I Le choix d’alignement se fait avec le bit 11 (ALIGN) du
effacé par le suivant (Overrun).
registre CR2. I On peut utiliser le contrôleur DMA (Direct Memory Access)
I ALIGN=0 : à droite (poids faible) pour effectuer ces transferts de données automatiquement
I ALIGN=1 : à gauche (poids fort) sans intervention logicielle.
I On peut aussi faire le transfert à l’aide d’une boucle
logicielle.
I En configurant EOCS=1 (CR2), le bit EOC indiquera la fin de
chaque mesure.
I On vérifie l’absence d’overrun (OVR=0) à chaque mesure.
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025
C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion C embarqué ADC Quoi ? Quand ? Comment ? Où ? Conclusion
Où ? Transfert des résultats Chaîne d’acquisition complète
Exemple : Séquence de mesure avec transfert des résultats par
logiciel.
uint32_t ADC_convert_sequence Dans une application réelle :
(volatile struct ADCx_registers *ADCx, uint32_t *data_buffer) I Un timer génère un signal périodique.
{
uint32_t len=((ADCx->SQR1>>20)&15) + 1; I Ce signal déclenche des mesures dans un ou plusieurs
uint32_t i=0;
ADCx->SR = 0; /∗ clear all SR flags ∗/
convertisseurs.
ADCx->CR2|=(1<<10); /∗ enable EOC after each conversion ∗/ I Le contrôleur DMA transfère les données acquises dans
ADCx->CR2|=(1<<30); /∗ SWSTART=1 ∗/
while (i<len) { un tampon mémoire.
while ((ADCx->SR&0x22)==0); /∗ Wait for EOC==1 or OVR==1 ∗/ I Le DMA signale le remplissage du tampon à une routine
if ((ADCx->SR&0x20)!=0) break; /∗ If OVR exit immediately ∗/
data_buffer[i++]=ADCx->DR; /∗ reading DR clears EOC flag ∗/ de traitement des données (par interruptions).
}
return i; /∗ i<len if overrun ∗/
}
Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025 Microcontrôleurs II - S6 — P. Corbineau Cours 7 IESE3 S6 — 2024–2025