stm32 PDF
stm32 PDF
stm32 PDF
G. Goavec-M erou, J.-M Friedt 28 f evrier 2012 Au sein de la gamme des curs de processeurs propos es par ARM, le Cortex-M3, op erant sur des registres de 32 bits, fournit un compromis entre une puissance de calcul appr eciable et une consommation r eduite qui, sans atteindre les performances du MSP430 (16 bits), propose n eanmoins des modes de veille en vue de r eduire la consommation moyenne dune application. Bien que les nombreux p eriph eriques disponibles ainsi que l enorme quantit e de m emoire associ ee ` a ce processeur puissent justier lutilisation de biblioth` eques dont une impl ementation libre est disponible sous le nom de libopencm3, nous verrons quil est possible dappr ehender un certain nombre de ces p eriph eriques pour en faire un usage optimal en acc edant directement aux registres qui en contr olent lacc` es. Le cur M3 est d eclin e par de nombreux fondeurs : nous nous focaliserons ici sur limpl ementation de ST Microelectronics sous le nom de STM32F1 (dans la suite, le microcontr oleur sera nomm e simplement STM32 car la plupart des applications sont portables sur les autres mod` eles).
Introduction
La famille des microprocesseurs STM32 de ST Microelectronics fournit une vaste gamme de p eriph eriques autour dun cur dARM Cortex-M3 [CortexM3], allant du simple GPIO (port dentr ee-sortie g en eraliste) et interface de communication s erie synchrone (SPI) ou asynchrone (RS232) aux interfaces aussi complexes que lUSB, ethernet ou HDMI. Un point remarquable est quun certain nombre de ces processeurs poss` edent deux convertisseurs analogique-num eriques, permettant un echantillonnage simultan e de deux grandeurs analogiques. Cadenc e sur un r esonateur interne ou sur un quartz externe haute fr equence 8 MHz (multipli e en interne au maximum ` a 72 MHz), ce processeur est compatible pour des applications faibles consommations (section 9) avec un mode veille dont le r eveil sobtient par une condition sur une horloge interne ou une interruption externe. La multiplicit e des horloges et leur utilisation pour cadencer les divers p eriph eriques est dailleurs un des aspects les plus d eroutant dans la prise en main du STM32. Notre choix dinvestissement de temps sur ce microcontr oleur en particulier est dirig e par quelques contraintes techniques : avant tout, un double convertisseur analogique-num erique rapide (1 M echantillons/s) sens e garantir la simultan eit e des conversions sur deux voies, un point cl e si du traitement num erique additionel est eectu e sur une combinaison des deux voies, une architecture ARM Cortex-M3 exploit ee par dautres constructeurs : nous ne nous enfermons pas sur une architecture support ee par un unique fondeur, les principes de base concernant le cur du processeur et la toolchain peuvent etre r eutilis es ult erieurement sur un autre processeur bas ee sur la m eme architecture (par exemple Atmel SAM3), un mode veille proposant une consommation raisonnable pour les application embarqu ees autonomes qui nous int eressent.
Le lecteur d esireux de simplement exploiter un circuit commercialement disponible devrait pouvoir travailler sur le circuit STM32H103 de Olimex 1 .
1. http://www.olimex.com/dev/stm32-h103.html
Pour notre part, nous nous proposons dexploiter un circuit d edi e, sp eciquement d evelopp e en vue d emuler le port parall` ele dun PC, fournissant ainsi acc` es ` a la majorit e des signaux utiles mais surtout illustrant le peu de composants annexes n ecessaires au fonctionnement de ce microcontr oleur : un quartz 32,768 kHz, eventuellement un quartz 8 MHz, et des condensateurs de d ecouplage aux 4 coins pour ltrer lalimentation (Figs. 1 et 2). Ce circuit comporte par ailleurs un convertisseur USB-RS232 pour fournir une interface commun ement disponible sur tout PC r ecent. Nous verrons deux applications de cette carte, dans un cas pour emuler le comportement du port parall` ele dun PC pour le contr ole dun instrument (section 5), et, plus ambitieux, la r ealisation dune station de mesure m et eorologique (section 8).
LLV70033DCK
VBUSP$1
39 40 51 52 53 2 3 4
U1PORTC_H
100n
P$5 C14 P$4
GND P$2
P$3
OUT P$5
P$4
VCC IC2
20 4 VCC VCCIO RESET OSCI OSCO TXD RXD RTS CTS DTR DSR DCD RI CBUS0 CBUS1 CBUS2 CBUS3 CBUS4 TEST GND GND GND 1 5 3 11 2 9 10 6 23 22 13 14 12 26
R20 R21
19 27 28
41 42 43 44 45 46 49 50
U1PORTA_H
R6
X1
C4 C3
EN
NC
32K
CMDVCCSD
GND
USB
R4 R5
1 2 3 4
GND ET312SMD
5 3 4 GPIO1 RX TX GND7 GND6 GND5 GND4 GND3 GND2 GND1 BATT VCC 13 11 10 9 8 2 1 6 7
GND
14 15 16 17 20 21 22 23
U1PORTA_L
VCCSD
VCC T1
GND X3
12
4 3 2 1
USB
17
R1
R2
D1 1N4148DO35-7
15 16 25
LTI-SASF54GT
R7
RF
U$2 VCC
STM32F10XRXT6
GND
BOOT0
X2 JP4
1 2
GND
7 18 21
60 7
BOOT0 NRST
U1RESET
25 24 23 22 21 20 19 18 17 16 15 14
13 12 11 10 9 8 7 6 5 4 3 2 1
C12
GND
1 2 3 4 5 6 7 8 9 CD WP SW 14
2 1
GND
1 2
RESET
3 4 32
X4
U1POWER
LLV70033DCK
C11 100n GND VBUSP$1 GND P$2
P$3
OUT P$5
P$4
VCC
GND
48 64 19
EN
NC
IC1A
1
GND
ADC0
C13
VSS_1 VSS_2 VSS_3 VSS_4
R8
JP6
1 2
4 5 6
GND
GND
18
11
LMV324M
R15
5 6
IC1B
7
ADC1
13
Q2 8 MHz
PC0 PC1 PC2 PC3 PC4 PC5 PC6 PC7 PD2 PD1/OSC=> PD0/OSC<=
1 2
4 5 6
GND
R3
JP5
C9
12 1
JP2
LMV324M
GND
59 58 57 56 55 28 27 26 PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
U1PORTB_L
IC1C
8
R10 LMV324M
C2 C1
JP3
1 2
4 5 6
GND BOOT1
GND
U1PORTD/OSC
1 2
IC1D
14
GND
R11 LMV324M
Figure 1 Exemple de circuit exploitant le STM32 (sch ema). Le quadruple-amplicateur op erationnel (en bas ` a droite) prot` ege 4 voies de conversion analogique-num erique et ajoute une tension constante permettre la mesure de signaux de valeur moyenne nulle. Une carte SD est connect ee sur bus synchrone SPI (en bas ` a gauche). Un r egulateur lin eaire (en haut ` a droite) permet lalimentation de ce circuit sur le bus USB qui sert aussi ` a la communication au travers dun convertisseur RS232-USB FT232.
La cha ne de compilation est bas ee sur lhabituelle g en eration des binaires issus de binutils et gcc sur architecture x86 ` a destination du processeur ARM, et en particulier Cortex M3. Un script ` a peu pr` es parfait est disponible sous la nomenclature summon-arm-toolchain accessible par git au moyen de git clone git://github.com/esden/summon-arm-toolchain.git pour aller rechercher lensemble des archives sur les sites appropri es et compiler les outils n ecessaires ` a g en erer un binaire ` a destination du STM32. On notera que cette m eme toolchain est fonctionnelle
RS232
45,2
SCINORTCELE
5 2F
USB
SCINORTCELE
1N4148DO35-7
T1
R6
52 31
41 1
2X D1R20 R21
100n
C11
TLV
100n
C14
FT232RL
STM32F10XRXT6
4X
R4 1X
R5
C6 IC2 100n
R2
JP4
R3
BOOT0 1K
ET312SMD U$2
100n
C9
100n C10
TLV
C7 100n
1T O O B
JP2 JP1
2 2 VQ A
31 C
R7
X3
ET312
2K
R1 U$1
C5 C3 100n
U1
C8 91 R 100n
11 R 1CI 8R
21 R 31 R 41 R 51 R 9R
2 2 VQ A
3K
RESET
LTI-SASF54GT C12
C4 32K Q2 C2 8 MHz
81 R 61 R M 4 2 3V M L 71 R 01 R
JP6
JP5
Figure 2 Exemple de circuit exploitant le STM32 (implantation des composants). pour dautres architectures ARM, notamment lARM7 fourni dans lADuC7026 de Analog Devices d ej` a pr esent e auparavant [LM117]. La compilation se fait classiquement ` a laide de la commande suivante :
1 cd summonarm t o o l c h a i n . / summonarm t o o l c h a i n USE LINARO=0 OOCD EN=0
Celle-ci permet dinstaller la toolchain avec la version Vanilla de GCC au lieu de linaro GCC (USE LINARO=0), sans la compilation et linstallation de OpenOCD (OOCD EN=0), disponible sous forme de paquet binaire dans toutes les distributions. Par d efaut, seule la biblioth` eque libre libopencm3 est install ee. Pour installer une biblioth` eque propri etaire mais gratuite d evelopp ee par ST, libstm32, loption LIBSTM32 EN=1 devra etre pass ee ` a la ligne de commande. Nous exploitons en particulier cette fonction pour compiler les nombreux exemples disponibles sur le web, en d ecortiquer le fonctionnement et ainsi acc eder aux m emes fonctionnalit es en enrichissant libopencm3. Par d efaut, les outils seront install es dans $HOME/sat. Obtenir un compilateur fonctionnel ne constitue que le d ebut de laventure du d eveloppement sur processeur ARM Cortex-M3. Ce cur de processeur 32 bits est en eet support e par divers fondeurs de circuits int egr es, et une tentative dunication du support logiciel en vue de la portabilit e du code dun fondeur ` a lautre est propos ee sous la nomenclature CMSIS. Comme souvent dans cette th ematique, lintention est surement noble, mais le r esultat consiste en une biblioth` eque a la license peu rassurante (ST) exploitant abusivement des structures de donn ` ees lourdes dont lutilisation sur un syst` eme embarqu e est un peu surprenante. Dun autre c ot e, une architecture 32 bits document ee sur plus de 1000 pages [RM0008] est dicile ` a appr ehender par la lecture dune datasheet d ecrivant la fonction de chaque registre 2 : un compromis appr eciable en terme de license dutilisation, complexit e et proximit e au mat eriel semble etre le projet libopencm3 (libopencm3.org). Accompagn ee de nombreux exemples concrets et en particulier sur le point epineux de lexploitation du p eriph erique USB cette biblioth` eque est facile ` a appr ehender malgr e un manque de maturit e certain et quelques p eriph eriques absent qui seront sans doute combl es rapidement. Une fois la compilation de toolchain nie, nous disposons dans $HOME/sat des outils n ecessaires a la compilation dapplications : nous ajoutons le r ` epertoire $HOME/sat/bin dans le PATH,
e x p o r t BASE DIR=/home/ u s e r / s a t 2. ` a la n, on revient toujours aux fondamentaux, mais lapproche est un peu rude en premier abord
2 2 VQ A JP3
C1
SD card
2 e x p o r t PATH =$ {PATH } : $ { CM3 BASE DIR } / b i n e x p o r t CM INC=$ { CM3 BASE DIR } /armnone e a b i / i n c l u d e 4 e x p o r t CM LIB=$ { CM3 BASE DIR } /armnone e a b i / l i b
La ligne relative au r epertoire include et lib servira lors de la compilation dapplications telle que pr esent ee plus loin pour acc eder aux bons r epertoires lors de la g en eration du binaire.
Outils de programmation
Le second pr erequis, apr` es lobtention dune cha ne de compilation fonctionnelle, concerne loutil pour programmer le microcontr oleur. Deux solutions sont possibles : 1. la programmation par RS232 avec un outil tel que stm32flash (code.google.com/p/stm32ash/). 2. la programmation par JTAG gr ace ` a OpenOCD et ` a une sonde.
4.1
stm32ash
stm32flash prend en argument le nom du chier contenant limage binaire ` a placer en m emoire du microcontr oleur (chier .bin ou .hex), la commande ` a eectuer (lecture, ecriture, v erication) et linterface de communication. Accessoirement, le d ebit de communication peut etre ajout e An de passer le STM32 en mode programmation il faut, comme pour bon nombre dautres microcontr oleurs, manipuler deux broches. La premi` ere est BOOT0 qui doit etre mise ` a la tension dalimentation VCC. Cette commande est valid ee par une mise ` a GND de la broche reset du ` ce moment le microcontr STM32. A oleur est pr et ` a etre programm e avec la commande :
s t m 3 2 f l a s h w main . b i n / dev / ttyUSB0 g 0 x0
Le -w signie que le chier main.bin doit etre ecrit en ash, le -g 0x0 sp ecie ladresse o` u commencera lex ecution (0x0 correspond au d ebut de la ash). Nous proposons une modication du module ftdi sio.ko permettant de manipuler deux broches du composant servant de convertisseur USB-RS232 (FT232RL) et de stm32flash pour manipuler ces deux signaux lors de la programmation 3 . Ces manipulations n ecessitent n eanmoins un transistor mont e en circuit inverseur pour palier ` a l etat par d efaut (incorrect) des broches du FT232RL, et dun circuit de gestion du reset, Analog Devices ADM809, pour retarder limpulsion dinitialisation lors de la mise sous tension et ainsi permettre au FT232RL de stabiliser l etat de ses sorties avant que le microcontr oleur ne tente dex ecuter son application (Fig. 3). Une pr esentation plus d etaill ee des possibilit es de d etournement des FTDIs fera lobjet dun futur article.
4.2
OpenOCD
Lutilisation du JTAG pour la programmation dun microcontr oleur pr esente de nombreux int er ets. Sans rentrer dans les d etails, il permet de charger le binaire bien plus rapidement quavec une liaison s erie et de debugger le code (` a laide de GDB connect e` a OpenOCD) . Lincantation pour programmer un STM32 ` a laide dune sonde JTAG et de OpenOCD est
1 openocd f f 3 c c 5 c c 7 c interface / dp busblaster . cfg \ board / o l i m e x s t m 3 2 h 1 0 7 . c f g \ a d a p t e r k h z 2000 \ init \ halt \ s t m 3 2 f 1 x m a s s e r a s e 0 \ f l a s h w r i t e i m a g e main . hex c r e s e t run c shutdown
Linterface (la sonde JTAG) d epend bien entendu du mat eriel disponible. Bien que notre carte ne soit pas une Olimex, lutilisation de ce chier de conguration permet de xer certaines informa3. patchs disponibles sur la page http://www.trabucayre.com/page-ftdi.html
AT1
TXD RXD RTS CTS DTR DSR DCD RI CBUS0 CBUS1 CBUS2 CBUS3 CBUS4 TEST GND GND GND
19 27 28
C4 C3
VCC
15k
R17
GND
10k
100n
VCC
C39
5 4 3 2 1
17 15 16 25
CBUS1 CBUS2
Q1
1
ADM809 RESET
2
Q_32K_SMD
13p 13p
VCC VCCIO
R13
R12
RSTX RSRX
5VRF
Q5
39 40 51 52 53 2 3 4
U1PORTC_H
GND
GND R2 5600
STM32F10XRXT6
60
BOOT0 NRST
U1RESET
FT232RL
2n2222 GND
RST
Figure 3 Circuit de r einitialisation du STM32 : le jumper DLOAD et bouton poussoir RESET permettent de manipuler ` a la main ces fonctions pour passer le microcontr oleur en mode programmation, tandis que les broches CBUS1 et CBUS2 sont exploit ees pour automatiser ces ` ces ns, une version fonctionnalit es en commandant la commutation des signaux depuis le PC. A modi ee de ftdi sio.ko et stm32flash sont n ecessaires. Le transistor Q1 sert dinverseur pour que la valeur par d efaut de CBUS2 (lors de lex ecution dun programme par la carte aliment ee sur USB) ne r einitialise pas le microcontr oleur. tions plus confortablement. Bien entendu l` a encore la conguration devra etre adapt ee ` a la version du STM32 utilis e 4.
4.3
Compilation de programme
La compilation des chiers .c ainsi que la g en eration du chier au format ELF se fait ` a laide des commandes suivantes :
1 armnonee a b i g c c O0 g3 DSTM32F1 Wall Wextra \ I $ {CM INC} I $ {CM INC } / l i b o p e n c m 3 / stm32 I $ {CM INC } / l i b o p e n c m 3 / stm32 / f 1 \ 3 fno common mthumb msoft f l o a t mcpu=c o r t e x m3 o main . o c main . c 5 armnonee a b i g c c o main . e l f main . o l o p e n c m 3 s t m 3 2 f 1 \ L$ { CM LIB } / thumb2 l c l n o s y s L$ { CM LIB } L$ { CM LIB } / l i b / stm32 \ 7Tlibopencm3 stm32 . l d n o s t a r t f i l e s
Nous y activons quelques warnings pour la compilation, ajoutons les en-t etes et la libopencm3 stm32f1.a. Nous en protons pour ajouter egalement la libc qui va permettre dutiliser des fonctions telles que sprintf(). Selon que openOCD ou stm32flash soit utilis e, il faudra g en erer un chier au format hexad ecimal ou binaire.
1 armnonee a b i o b j c o p y Oihex main . e l f main . hex armnonee a b i o b j c o p y Obinary main . e l f main . b i n
Pour ne pas faillir ` a la r egle, la d ecouverte du STM32 va se faire en pilotant une broche. Quelle que soit lapplication, le STM32 par d efaut est cadenc e par son oscillateur interne, peu pr ecis en fr equence : nous allons donc passer sur le quartz 8 MHz, nous autorisant ainsi ` a cadencer le microcontr oleur ` a la vitesse de 72 MHz (au maximum) par multiplication interne. Cadencer le STM32 a ` 72MHz nest pas une obligation. La r eduction de la vitesse des horloges (utilisation dun
4. dans /usr/share/openocd/scripts et ses sous r epertoires (interface pour les sondes, board pour les cartes).
plus faible multiplieur pour la PLL) est une solution pour baisser l eg erement la consommation globale du STM32.
rcc clock setup in hse 8mhz out 72mhz () ;
Cette fonction, dapparence simple, cache de nombreuses dop erations telles que la conguration de la PLL, des horloges APB1 et APB2 utilis ees pour les p eriph eriques du STM32, le basculement sur quartz HSE (quartz externe haute-fr equence) et lattente de la n du calibrage de ce dernier. Les ports dentr ee-sortie (General Purpose Input Output, GPIO) du STM32 sont synchrones : nous avons besoin dactiver lhorloge pour le(s) port(s) que nous allons utiliser. Dans notre cas la broche est PC7, ainsi il faut en premier lieu activer ce port :
1 / Enable GPIOC c l o c k . / r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB2ENR, RCC APB2ENR IOPCEN) ;
Pour nir nous entrons dans une boucle innie dans laquelle nous mettons la GPIO ` a l etat haut, puis apr` es une attente (it eration sur la mn emonique assembleur nop en boucle), nous la passons ` a l etat bas :
while (1) { g p i o s e t (GPIOC, GPIO7) ; Delay ( 0 x a f f f f ) ; 4 g p i o c l e a r (GPIOC, GPIO7) ; Delay ( 0 x a f f f f ) ; 6} 2
En quelques lignes de code nous avons ainsi pu congurer la vitesse du STM32, la nature de la source dhorloge, et avons pu manipuler une GPIO. Une application concr` ete de ces concepts tr` es simples consiste ` a emuler le port parall` ele dun PC en vue de contr oler un instrument exploitant une telle interface. Le RADAR de sol (Ground Penetrating RADAR, GPR) de la soci et e su edoise Mal a est un instrument permettant de sonder les discontinuit es de permittivit e ou de conductivit e dans le sous-sol ` a des profondeurs allant de quelques centim` etres ( etat des routes ou des armatures dans les murs en b eton arm e par exemple) ` a quelques centaines de m` etres (glaciers et banquise). Cet instrument, relativement ancien pour ses versions CU (Fig. 4) et CUII, se connecte ` a un ordinateur de contr ole de type compatible IBM au moyen du port parall` ele (Centronics). Notre objectif est dautomatiser la mise sous tension de cet instrument, lacquisition de trames contenant les mesures, stockage des informations sur support de stockage non-volatil, et mise en veille, le tout pour une consommation r eduite en vue dun fonctionnement autonome pendant plusieurs mois. Ayant identi e la fonction des diverses broches du port parall` ele dans ce protocole de communication (en partie gr ace ` a une documentation fournie par le constructeur, et en partie par nos propres ecoutes sur le bus de communication lors de l echange dinformations sous le contr ole du logiciel propri etaire commercialis e par le constructeur de linstrument), ce protocole est emul e par GPIO. La puissance du Cortex M3 ne se justie evidemment pas pour cette application triviale, mais nous verrons plus loin comment les informations acquises sont stock ees sur carte SD (section 10) et comment le microcontr oleur est p eriodiquement r eveill e de son mode de veille profonde par une horloge temps-r eel fournie comme p eriph erique mat eriel ind ependant (section 9). La puissance de calcul du Cortex M3 ne se justie que sil y a traitement embarqu e des informations en vue den extraire les informations pertinentes permettant de r eduire la quantit e dinformation stock ee (compression, intercorr elation) ou en transmission par liaison sans l. Lextrait de programme ci-dessous propose une impl ementation de la fonction d ecriture entre le STM32 et lunit e de contr ole du RADAR RAMAC (la fonction de lecture est trop longue et sans nouveaut e pour etre pr esent ee ici, mais est disponible dans larchive de programmes associ ee au manuscrit de cet article sur les sites http://jmfriedt.free.fr et www.trabucayre.com 5 . Connaissant le protocole de communication qui a et e sond e par un analyseur logique Logic Snier 6 , les diverses s equences de manipulation de l etat des broches sont impl ement ees de fa con logicielle. La s equence
5. http://www.trabucayre.com/lm/lm stm32 examples.tgz 6. http://dangerousprototypes.com/open-logic-snier/
Time
3 ms
0 1 16 255
0 3 29 1 0
254
3 1
20 5
02
254
0 3
19
195
254
RESET_P
R_FREQ
S_SAMP
S_SIGPOS
CONT
Figure 4 Haut : chronogramme de la communication par port parall` ele entre lunit e de contr ole du RADAR de sol RAMAC et un PC, sond e par un Logic Snier. Les donn ees sont sur les broches 2 ` a 8 du port parall` ele (bidirectionnel dans cette conguration), SELECTIN est la broche 17, BUSY est en 11, INIT est en 16 et STROBE est en 1. Tous les signaux de contr ole ` a lexception de BUSY sont impos es par le microcontr oleur (sortie) ` a lunit e de contr ole (entr ee) : BUSY sert ` a cadencer le ux de donn ees et acquitter le transfert de donn ees par lunit e de contr ole. Bas : unit e de contr ole CU dun Mal a RAMAC (RADAR de sol GPR pour Ground Penetrating RADAR con cu pour communiquer avec un PC via le port parall` ele, et ici command e par un STM32 dont les GPIO emulent les fonctionnalit es de ce bus de communication. Bien quune partie du protocole de communication nous ait et e fournie par le constructeur, une phase d ecoute des informations transitant sur le bus a et e n ecessaire pour impl ementer sur STM32 un protocole permettant de communiquer avec ce RADAR. des commandes, dont seules les premi` eres etapes dinitialisation sont d ecrites ici (Fig. 4, haut), consistent ` a placer lunit e de contr ole en liaison de donn ees bidirectionnelles sur 8 bits, lecture de la fr equence de fonctionnement (R FREQ), d enition du nombre d echantillons acquis (S SAMP), position du d ebut dacquisition des echos par rapport ` a limpulsion dexcitation (S SIGPOS), et relance dune acquisition temporairement interrompue (CONT).
// CU i n p u t s i g n a l s 2#d e f i n e STROBE 0 x01 #d e f i n e INIT 0 x04 4#d e f i n e SLCTIN 0 x08 // CU ou tp ut s i g n a l s 6#d e f i n e BUSY 0 x02 8#d e f i n e TAILMAX 2700
10 v o i d g p i o s e t u p ( v o i d ) { g p i o s e t m o d e (GPIOC, GPIO MODE OUTPUT 10 MHZ, GPIO CNF OUTPUT PUSHPULL, INIT | STROBE | SLCTIN) ; 12 g p i o s e t m o d e (GPIOC, GPIO MODE INPUT, GPIO CNF INPUT FLOAT , BUSY) ; } 14 void busy low ( void ) 16 { i n t i =0; do { i ++; b = g p i o p o r t r e a d (GPIOC) ; } 18 w h i l e ( ( ( b & BUSY) == 0 ) && ( i < MAXITER) ) ; } 20 void busy high ( void ) 22 { i n t i =0; do { i ++;b = g p i o p o r t r e a d (GPIOC) ; u s l e e p (DELA) ; } 24 w h i l e ( ( ( b & BUSY) != 0 ) && ( i < MAXITER) ) ; } 26 v o i d write command ( u n s i g n e d c h a r cmd ) 28 { i n t j = 0 ; do { 30 g p i o p o r t w r i t e (GPIOB, ( cmd [ j ] << 8 ) ) ; // 1 . e n v o i d e s commandes u s l e e p (DELA) ; 32 g p i o c l e a r (GPIOC, STROBE) ; // 2 . s t r o b e p u l s e busy low ( ) ; // 3 . busy high , o r i g i n e low 34 g p i o s e t (GPIOC, INIT + STROBE) ; // 4 . s t r o b e p u l s e busy high () ; // 5 . busy low ( o r i g i n e h i g h ) 36 g p i o c l e a r (GPIOC, INIT ) ; // 6 . i n i t bas j ++; 38 } w h i l e ( j < ( cmd [ 0 ] 2 5 6 + cmd [ 1 ] + 2 ) ) ; // nbre e l e m e n t s dans cmd 40 } 42 i n t main ( v o i d ) { 44 u n s i g n e d c h a r cmd [ 1 0 ] ; [...] 46 g p i o s e t u p ( ) ; cmd [ 0 ] = 0 ; cmd [ 1 ] = 1 ; cmd [ 2 ] = 1 6 ; // RESET P 48 write command ( cmd ) ; read command ( cmd ) ; 50 [ . . . ] }
Dans le premier exemple, les attentes entre deux transitions d etat du GPIO sobtiennent par des boucles bas ees sur une instruction ne faisant rien. Non seulement cette solution nest pas satisfaisante car la dur ee dattente est intimement li ee ` a la vitesse du cur, mais en plus selon le niveau doptimisation cette boucle peu potentiellement etre supprim ee par le compilateur. Nous allons pr esenter une solution plus able nous permettant davoir une base de temps plus stable. Pour cela et g en eralement apr` es avoir appris ` a manipuler une broche, le but suivant est dapprendre a ` communiquer, nous allons appliquer cette r egle mais dune mani` ere plus ancienne, ` a savoir transmettre un classique hello world en morse [morse] au lieu du RS232. hello world va donc donner ceci : h e l l o / w o r l d .... . .-.. .-.. . .-. .-.. -.. Le . correspond ` a 1/4 de temps, le - et le temps entre deux caract` eres ` a 3/4. Lespace entre deux mots ` a 7/4 de p eriode. Une attente de 1/4 de temps est plac ee entre chaque impulsion. Le code etant clair, limpl ementation sera egalement facile sans compliquer inutilement lexemple. 8
Pour obtenir des dur ees pr ecises et non d ependantes du compilateur nous allons utiliser un p eriph erique du STM32 dont le travail consiste ` a d eclencher une interruption lors du d ebordement dun compteur interne, le systick. Dans la suite nous nallons pas reprendre linitialisation de lhorloge, pas plus que la conguration de la broche, nous allons juste nous focaliser sur la partie conguration du systick et son utilisation. La premi` ere etape consiste en linitialisation :
1 / 72MHz / 8 => 9000000 c o u n t s p e r s e c o n d / s y s t i c k s e t c l o c k s o u r c e (STK CTRL CLKSOURCE AHB DIV8) ; 3 / 9000000/9000 = 1000 o v e r f l o w s p e r s e c o n d e v e r y 1ms one i n t e r r u p t / s y s t i c k s e t r e l o a d (9000) ; 5 systick interrupt enable () ; systick counter enable () ;
Le systick est congur e avec une fr equence de 9 MHz (l.2) et un d ebordement (g en eration dune interruption) toutes les 1 ms (l.4). Les interruptions sont activ ees et le compteur est d emarr e. Bien entendu dans le code si dessus la dur ee avant interruption est cod ee en dur mais il est tout ` a fait possible de faire la m eme chose dune mani` ere plus el egante et capable de sadapter automatiquement ` a la fr equence de lhorloge. La seconde etape consiste en lajout du gestionnaire dinterruptions pour le systick et en la cr eation dune fonction dattente.
v o l a t i l e uint32 t current time32 ; 2 / we c a l l t h i s h a n d l e r e v e r y 1ms / 4 void s y s t i c k h a n d l e r ( ) { c u r r e n t t i m e ++;} 6 v o i d Delay ( u i n t 3 2 t nCount ) 8 { uint32 t begin = current time ; w h i l e ( c u r r e n t t i m e b e g i n < nCount ) ; 10 }
La fonction sys tick handler est, par convention de libopencm3, le gestionnaire pour linterruption du systick. Cette fonction naura comme seul r ole que dincr ementer une variable ` a chaque d ebordement. Quand la variable atteindra 0x, son incr ement fera retomber la valeur a 0; ` La seconde fonction (Delay()) va attendre que la di erence entre le contenu de la variable lors de lentr ee dans la fonction et la valeur courante ait atteint la valeur d esir ee. Finalement une derni` ere fonction qui va g erer le comportement dattente selon le caract` ere fourni :
v o i d sendChar ( u i n t 8 t c ) 2{ uint32 t delai ; 4 switch ( c ) { c a s e . : d e l a i = SHORT TIME ; b r e a k ; 6 c a s e : d e l a i = LONG TIME ; b r e a k ; c a s e : Delay (LONG TIME) ; r e t u r n ; 8 c a s e / : Delay (SPACE TIME) ; default : 10 return ; } 12 g p i o c l e a r (GPIOC, GPIO7) ; Delay ( d e l a i ) ; g p i o s e t (GPIOC, GPIO7) ; Delay (SHORT TIME) ; 14 }
La fonction est relativement simple ` a comprendre. Pour le caract` ere . ou - une dur ee va etre renseign ee, la LED est allum ee pendant un temps correspondant, puis eteinte, et une seconde attente va etre r ealis ee. Dans les autres cas la fonction est mise en attente puis ressort sans toucher a la LED. SHORT TIME correspond ` ` a 250 ms, LONG TIME ` a 750 ms, et SPACE TIME ` a 1750 ms. Enn il ne reste plus qu` a assembler le tout pour avoir un programme pr et pour la compilation.
i n t main ( v o i d ) 2{ int i ; u i n t 8 t message [ ] = . . . . //h 4 . // e
6 8 10 12 14
. .. . .. / . . . . .. .. \ 0 ; i n i t s t () ;
// l // l // o // //w // o // r // l //d
\ 0 ; i ++)
Hormis le tableau contenant le message, la fonction principale main() est tr` es simple puisquapr` es conguration du microcontr oleur, le programme rentre dans une boucle innie qui va envoyer le message en permanence. Nous pouvons voir clignoter une LED au rythme de lenvoi du message. Mais il faut reconna tre que ce nest pas une mani` ere sp ecialement evidente de transmettre des informations ni de debugger une application.
Communication RS232
Le STM32 dispose selon les mod` eles de 4 ` a 6 USARTs. Sur notre carte, lUSART1 est connect e a un convertisseur USB-s ` erie. La conguration de ce p eriph erique se fait de la fa con suivante : Comme tous les p eriph eriques du STM32, il est n ecessaire dactiver lhorloge pour lUSART ainsi que pour les broches de communication :
1 r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB2ENR, RCC APB2ENR USART1EN) ; r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB2ENR, RCC APB2ENR IOPAEN) ;
Chaque broche du microcontr oleur dispose de plusieurs fonctions selon les besoins, il est donc n ecessaire de congurer les broches PA9 (USART1 TX) et PA10 (USART1 RX) en alternate function push-pull (GPIO CNF OUTPUT ALTFN PUSHPULL) pour TX et en input oating ( GPIO CNF INPUT FLOAT) ou input pull-up (GPIO CNF INPUT PULL UPDOWN) pour RX ([RM0008, pp.161-162]).
/ Setup GPIO p i n GPIO USART1 TX/GPIO9 on GPIO p o r t A f o r t r a n s m i t . / 2 g p i o s e t m o d e (GPIOA, GPIO MODE OUTPUT 50 MHZ, GPIO CNF OUTPUT ALTFN PUSHPULL, 4 GPIO USART1 TX) ; / Setup GPIO p i n GPIO USART1 RX/GPI10 on GPIO p o r t A f o r r e c e i v e . / 6 g p i o s e t m o d e (GPIOA, GPIO MODE INPUT, GPIO CNF INPUT FLOAT , 8 GPIO USART1 TX) ;
Une fois encore, la libopencm3 fournit des fonctions qui simplient notre code de tous les d etails sp eciques au mat eriel vis e.
10
La derni` ere etape consiste ` a faire appel ` a cette fonction dans un main avant denvoyer des messages sur le port s erie :
i n t main ( ) 2{ int i ; 4 u i n t 8 t message [ ] = h e l l o world ! \ r \ n \ 0 ; clock setup () ; 6 SetupUART ( ) ; while (1) { 8 f o r ( i = 0 ; message [ i ] ! = \ 0 ; i ++) u s a r t s e n d b l o c k i n g (USART1, message [ i ] ) ; 10 Delay ( 0 x a f f f f ) ; } 12 return 1; }
La fonction usart send blocking(..) va sassurer en premier lieu que lUSART est disponible (pas de caract` ere en cours denvoi) en attendant que le bit TXE du registre USART SR (status register) soit ` a 1. D` es que le p eriph erique est disponible loctet est charg e dans le registre USART DR (data register) et la fonction rend la main.
Application pratique
Les premiers exemples nous ont permis de d ecouvrir le STM32, de comprendre comment g en erer un binaire et de programmer le microcontr oleur. Cependant, cette compr ehension est en somme relativement basique : nous savons certes comment manipuler des GPIOs, nous avons un m ecanisme dattente pr ecis et une solution pour communiquer avec lext erieur, mais par rapport aux p eriph eriques disponibles sur ce microcontr oleur, cette premi` ere d ecouverte nest en somme quun amuse-bouche, tout reste ` a faire en pratique.
Figure 5 Vue int erieure de la station et installation en ext erieur. La liaison sans l avec lordinateur charg e de placer les informations recueillies sur le web se fait par Bluetooth. Nous nous sommes donc x es comme objectif la r ealisation dune station m et eorologique (Fig. 5) equip ee dun capteur de pression, dune sonde de temp erature, dun hygrom` etre et dun capteur de lumi` ere (Fig. 6). Au-del` a de laspect ludique de pouvoir enregistrer les donn ees sur une carte SD ou de les transmettre ` a un ordinateur, cette application va nous permettre daller plus avant 11
dans la d ecouverte de ce microcontr oleur. Les composants choisis etant h et erog` enes du point de vue du protocole, il est donc n ecessaire de comprendre et ma triser des p eriph eriques tels que le SPI, lI2C, lADC et les timers.
temt6000
ADC1_CH0 I2C1
HH10D
TIM2_CH2
STM32
usart3 Free2move
ms5534a
Figure 6 Sch ema bloc de la station. Les capteurs ont et e s electionn es de fa con ` a illustrer lutilisation des divers p eriph eriques propos es par le STM32. Lacquisition de donn ees se fait par conversion analogique-num erique (TEMT6000), communication num erique synchrone (SPI pour le MS5534A, I2C pour les param` etres du HH10D) et mesure de largeur dimpulsion (HH10D) exploitant les timers. Ces informations sont ensuite transmises pour une liaison sans l Bluetooth au moyen dune liaison num erique asynchrone (RS232). Un second objectif de la compr ehension de la structure de ce microcontr oleur est le portage de TinyOS sur celui-ci : cette partie sera pr esent ee dans un prochain article. An de pouvoir coller au plus pr` es ` a la structure interne du STM32 (registre, conguration, ...), nous avons d ecid e dans la suite de ne plus faire usage de la libopencm3 qui, bien que pratique car permettant de d evelopper rapidement sans avoir ` a conna tre la structure de chaque registre pour un p eriph erique, emp eche davoir une id ee pr ecise de comment faire en sorte de rendre les modules les plus g en eriques possibles et donc eviter la duplication de code.
8.1
8.1.1
MS5534A : SPI
Pr esentation du capteur
Le MS5534A[MS5534] est un capteur de pression compens e en temp erature qui communique avec un microcontr oleur au moyen dun bus synchrone bidirectionnel (deux signaux de donn ees, lun en provenance et lautre vers le p eriph erique, et une horloge). Les commandes ` a envoyer sont sur 10 bits et les donn ees re cues sont sur 16 bits. Ce capteur fournit non seulement une information permettant de calculer la pression mais egalement la temp erature. An dobtenir ces deux informations, il est n ecessaire de r ecup erer un jeu de constantes de calibrage qui permettront ensuite de r ealiser les calculs n ecessaires pour obtenir des valeurs en C et en hPa. La communication peut sapparenter ` a du SPI ` a quelques exceptions pr` es : il ny a pas de Chip-Select, le capteur risque donc de parler alors quil nest pas la cible ; le capteur lit les donn ees sur le front montant de lhorloge et le microcontr oleur doit lire les donn ees issues du capteur sur le front descendant. Il nexiste pas de mode SPI adapt e` a cette situation ; les commandes ` a lui envoyer sont cod ees sur 10 bits. La plupart des microcontr oleurs ne peuvent communiquer quen 8 ou 16 bits.
12
SPI2
Une application note [AN510] explique comment utiliser ce composant avec ce protocole. Ainsi, pour palier au manque de CS, un buer trois etats (74HC1G125 par exemple) doit etre install e: ce composant dispose dun enable actif ` a l etat bas. Gr ace ` a ce composant il est possible de couper la ligne MISO an de ne pas parasiter la communication dans le cas de lutilisation de plusieurs esclaves SPI. Le probl` eme du mode de communication non compatible est r egl e par une reconguration de CPHA entre les phases de lecture et d ecriture. Finalement, ce document fournit les commandes en 16 bits (par adjonction de 0). 8.1.2 Conguration du SPI
En vue de communiquer avec le capteur, il est logiquement n ecessaire de mettre en place un certain nombre de fonctions pour la conguration et la communication en SPI. Nous allons utiliser arbitrairement SPI2 mais le m eme code sera applicable ` a tous les autres SPI disponibles. Attention, la conguration des registres est identique, modulo le passage de ladresse adapt ee, mais par contre les broches ne sont (bien evidemment) pas les m emes et le SPI1 est cadenc e par APB2 et non APB1 (donc fr equence maximale de fonctionnement di erente). Comme nous lavons vu dans les premiers exemples, il est n ecessaire dactiver les p eriph eriques ainsi que de congurer les broches :
1 void s p i r c c g p i o c o n f i g ( void ) { 3 r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB1ENR, RCC APB1ENR SPI2EN) ; r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB2ENR, RCC APB2ENR IOPBEN) ; 5 g p i o s e t m o d e (GPIOB, GPIO MODE INPUT, 7 GPIO CNF INPUT FLOAT , GPIO SPI2 MISO ) ; g p i o s e t m o d e (GPIOB, GPIO MODE OUTPUT 50 MHZ, 9 GPIO CNF OUTPUT ALTFN PUSHPULL, GPIO SPI2 MOSI | GPIO SPI2 SCK ) ; 11 g p i o s e t m o d e (GPIOB, GPIO MODE OUTPUT 50 MHZ, GPIO CNF OUTPUT PUSHPULL, GPIO1) ; 13 g p i o s e t (GPIOB, GPIO1) ; }
Vient maintenant la conguration du SPI (baudrate, mode master, CPHA, CPOL, ...). Dans le cas de lutilisation du SPI sans interruption ni DMA, la conguration se fait uniquement au niveau du registre SPI CR1 :
void s p i c o n f i g ( void ) 2{ / d i s a b l e SPI / 4 SPI CR1 ( SPI2 ) &=(SPI CR1 SPE ) ; 6 8 10 12 14 16 18 } / e n a b l e SPI / SPI CR1 ( SPI2 ) | = SPI CR1 SPE ; SPI I2SCFGR ( SPI2 ) & (1 << 11) ; SPI CR1 ( SPI2 ) = SPI CR1 BIDIMODE 2LINE UNIDIR | SPI CR1 DFF 8BIT / 8 b i t s data / | SPI CR1 SSM / CS s o f t w a r e / | SPI CR1 MSBFIRST | SPI CR1 BAUDRATE FPCLK DIV 8 | SPI CR1 MSTR / master s e l e c t i o n / | SPI CR1 CPOL CLK TO 0 WHEN IDLE | SPI CR1 CPHA CLK TRANSITION 1 ;
Par acquis de conscience, ne sachant pas l etat courant du SPI et comme certains param` etres ne peuvent etre modi es si le p eriph erique est actif, nous mettons le bit 6 (SPE : SPI enable) ` a0 pour d esactiver le SPI (l.4). Les p eriph eriques SPI peuvent egalement etre congur es en I 2 S (Inter-IC Sound, Integrated In7 terchip Sound) , il faut donc choisir le mode SPI en mettant ` a 0 le bit 11 du registre SPI I2SCFGR(l.6)
7. http://wikipedia.org/wiki/I2S
13
Nous ne nous soucions pas du contenu ant erieur du registre SPI CR1 que nous ecrasons avec notre conguration. Le SPI est maintenant congur e en tant que ma tre (l.11), full duplex (MISO et MOSI)(l.6) pour des paquets de 8bits par transfert (l.7) le bit de poids fort en premier (l.9) , SCK ` a l etat bas lors de labsence de transmission (l.12), avec une vitesse de transfert de 4,5 MHz (36 MHz pour APB1, divis e par 8)(l.10) et avec un Chip-Select g er e manuellement (l.8) . Il ne reste plus qu` a activer le p eriph erique (l.16). Nous allons ajouter quelques fonctions utilitaires pour la communication avec le capteur : comme pr esent e pr ecedemment ce capteur re coit toutes les donn ees lues sur le front montant de lhorloge et le microcontr oleur doit lire sur le front descendant :
1#d e f i n e SET CPHA 0 do SPI CR1 ( SPI2 ) 3 SPI CR1 ( SPI2 ) SPI CR1 ( SPI2 ) 5 } while (0) #d e f i n e SET CPHA 1 do 7 SPI CR1 ( SPI2 ) SPI CR1 ( SPI2 ) 9 SPI CR1 ( SPI2 ) } while (0) { \ &=(SPI CR1 SPE ) ; \ &= SPI CR1 CPHA ; \ | = SPI CR1 SPE ; \ { \ &=(SPI CR1 SPE ) ; \ | = SPI CR1 CPHA ; \ | = SPI CR1 SPE ; \
Le STM32 ne supporte pas un changement de mode alors que le SPI est actif, il faut donc d esactiver celui-ci, changer le CPHA et le r eactiver. Ensuite nous cr eons une fonction qui va envoyer et recevoir les donn es.
u i n t 8 t s p i p u t ( u i n t 8 t data ) 2{ SPI DR ( SPI2 ) = data ; 4 w h i l e ( ( SPI SR ( SPI2 ) & ( SPI SR TXE ) )==0x00 ) ; w h i l e ( ( SPI SR ( SPI2 ) & SPI SR RXNE )==0x00 ) ; 6 r e t u r n SPI DR ( SPI2 ) ; }
La donn ee est charg ee dans le Data Register (SPI DR), ensuite une attente est faite sur la transmission de celle-ci, puis sur la r eception dun octet depuis le capteur. Le m eme registre SPI DR est utilis e pour r ecup erer linformation. Et pour nir, la fonction qui va g erer la totalit e de la communication (envoi dun ordre, attente, puis r ecup eration de linformation fournie par le capteur) : 8.1.3 Acquisition et traitement des donn ees
La partie purement li ee au SPI du STM32 (conguration et communication) est maintenant nie. Il nous faut nalement ajouter quelques fonctions pour envoyer et recevoir des commandes et les donn ees, transmettre un reset au capteur, obtenir lensemble des param` etres n ecesaires ` a lexploitation de celui-ci, et traiter les informations de temp erature et de pression obtenues.
1 u i n t 1 6 t ms5534a send ( u i n t 1 6 t cmd ) { 3 u i n t 8 t txbuf [ 2 ] ; u i n t 8 t rxbuf [ 2 ] ; 5 uint16 t result = 0; 7 9 11 13 Delay ( 7 0 ) ; 15 17 19 21 r e s u l t = r x b u f [ 0 ] << 8 | r x b u f [ 1 ] ; return r e s u l t ; SET CPHA 1 ; rxbuf [ 0 ] = s p i p u t (0 x f f ) ; rxbuf [ 1 ] = s p i p u t (0 x f f ) ; SET CPHA 0 ; spi put ( txbuf [ 0 ] ) ; spi put ( txbuf [ 1 ] ) ; t x b u f [ 0 ] = cmd >> 8 ; t x b u f [ 1 ] = cmd & 0 x f f ;
14
Cette fonction sert ` a transmettre une commande et ` a recevoir la r eponse du capteur. Les commandes, sur 16 bits, sont d ecoup ees en deux octets. Le p eriph erique est bascul e dans le mode denvoi, puis la commande est envoy ee (l.8-10). Le ms5534a n ecessite un temps de conversion de 33 ms, la donn ee doit etre r ecup er ee dans un d elai de maximum 100 ms apr` es la n de la conversion, ainsi nous utilisons la fonction Delay() pr esent ee plus t ot pour garantir une attente correcte. Le SPI est ensuite bascul e en mode lecture (l.16), les deux octets sont re cus (l.17-18) et la donn ee sur 16 bits est reconstruite (l.20). La seconde fonction concerne la transmission de la commande de reset :
void ms5534a sendReset ( void ) 2{ c h a r t x b u f [ ] = { 0 x15 , 0 x55 , 0 x40 } ; 4 int i ; SET CPHA 0 ; 6 f o r ( i =0; i < 3; i ++) spi put ( txbuf [ i ] ) ; 8}
Cette fonction ne pr esente pas de dicult es particuli` eres, comme elle ne fait quenvoyer 4 octets sans faire de lecture, nous congurons le STM32 puis nous envoyons s equentiellement les octets. Il nous faut ensuite etre capable dobtenir les donn ees de calibrage du capteur :
void receiveParam ( void ) 2{ u i n t 1 6 t w1 , w2 , w3 , w4 ; 4 ms5534a sendReset ( ) ; w1 = ms5534a send (CAL READ W1) ; 6 w2 = ms5534a send (CAL READ W2) ; w3 = ms5534a send (CAL READ W3) ; 8 w4 = ms5534a send (CAL READ W4) ; ms5534a c1 = w1 >> 1 ; 10 ms5534a c2 = ( ( w3 & 0x3F ) << 6 ) | ( w4 & 0x3F ) ; ms5534a c2 = 4 ; 12 ms5534a c3 = w4 >> 6 ; ms5534a c4 = w3 >> 6 ; 14 ms5534a c5 = ( w2 >> 6 ) | ( ( w1 & 0 x01 ) << 1 0 ) ; ms5534a c6 = ( w2 & 0x3F ) ; 16 ms5534a UT1 = ( ms5534a c5 8 ) + 2 0 2 2 4 ; ms5534a ta = ( ms5534a c6 + 5 0 ) ; 18 }
Lobtention des param` etres de calibrage du capteur na rien de particuli` erement dicile non plus. Apr` es avoir envoy e la commande de reset, tel que pr esent e dans la datasheet, nous r ecup erons les 4 mots (l.5-8). Ensuite nous calculons lensemble des informations n ecessaires pour lobtention de la pression et de la temp erature que nous stockons dans des variables globales pour leur r eutilisation ult erieure. Les CAL READ Wx sont des #define fournis dans [AN510]. Et pour nir nous cr eons la fonction de r ecup eration et de calcul des deux grandeurs qui nous int eressent.
v o i d m s 5 5 3 4 a r e a d p r e s s u r e a n d t e m p ( f l o a t temp , u i n t 3 2 t p r e s s u r e ) 2{ i n t t , dT , D1 , D2 , o f f , s e n s , x ; 4 ms5534a sendReset ( ) ; 6 D1 = ms5534a send (READ PRESS) ; 8 D2 = ms5534a send (READ TEMP) ; 10 12 14 16 18 dT = D2 ms5534a UT1 ; / t e m p e r a t u r e / i f (D2 >= ms5534a UT1 ) { temp = 200 + ( ( dT ms5534a ta ) >> 1 0 ) ; } else { t = dT / 1 2 8 ; dT = dT ( t t ) / 4 ; temp = 200 + ( ( dT ms5534a ta ) >> 1 0 ) + (dT / 2 5 6 ) ; }
15
20 22 24 }
/ P r e s s u r e / o f f = ms5534a c2 + ( ( ( ms5534a c4 5 1 2 ) dT) >> 1 2 ) ; s e n s = ms5534a c1 + ( ( ms5534a c3 dT) >> 1 0 ) + 2 4 5 7 6 ; x = ( ( s e n s (D1 7 1 6 8 ) ) >> 1 4 ) o f f ; p r e s s u r e = ( ( x 1 0 ) >> 5 ) + 2 5 0 0 ;
Apr es transmission ` a un ordinateur, nous pouvons g en erer des courbes d evolution des informations fournies par le capteur telles que pr esent ees Fig.7
Figure 7 Evolution de la pression athmosph erique (g. haut) et de la temp erature (g. bas) ` partir de cette date, le capteur na plus donn entre le 11/02/2012 14:50 et le 19/02/2012 19:53. A e dinformations correctes (322,1 C et 183 hPa) ou alors la n du monde est en avance !
16
8.2
8.2.1
Le HH10D [HH10D] est un capteur dhumidit e qui fournit un signal p eriodique proportionnel au pourcentage dhumidit e dans lair. Chaque composant est etalonn e individuellement, ces informations sont stock ees dans une EEPROM accessible en I2C. Lobtention de la dur ee de la p eriode dun signal se fait, sur STM32, ` a laide dun des p eriph eriques timer. Il existe deux modes de capture : le mode input capture qui permet dobtenir uniquement la dur ee de la p eriode du signal. le mode pwm input capture qui fournit en plus la dur ee de l etat haut ou bas (selon le front choisi pour la p eriode) de ce m eme signal. Bien que le HH10D fournisse un signal p eriodique (rapport cyclique de 50%), nous allons utiliser le pwm input capture pour comprendre ce mode qui est sans doute le plus complexe, sans pour autant n ecessiter de grosses modications par rapport au mode input capture de base. 8.2.2 Interrogation de lEEPROM
Pour pouvoir exploiter linformation de p eriode du signal, il est n ecessaire de r ecup erer les donn ees issues du calibrage du capteur, stock ees dans lEEPROM. Cette m emoire est accessible en I2C ` a une vitesse de communication de 400 kHz maximum. Nous nallons pas copier ` a nouveau lactivation de lhorloge pour ce p eriph erique. Il faut juste savoir que I2C1 est cadenc e sur APB1 et utilise les broches PB6 et PB7 qui doivent etre congur ees en mode GPIO CNF OUTPUT ALTFN OPENDRAIN. La conguration du p eriph erique est en somme relativement simple.
/ D i s a b l e t h e I2C . / 2 I2C CR1 ( I2C1 ) &=I2C CR1 PE ; 4 / S e t p e r i p h e r a l i n i 2 c mode / I2C CR1 ( I2C1 ) &=I2C CR1 SMBUS ; 6 / APB1 i s r u n n i n g a t 36MHz. 8 no i n t e r r u p t s g e n e r a t e s / I2C CR2 ( I2C1 ) = 3 6 ;
Classiquement, le p eriph erique est d esactiv e (l.2). Pour lheure, la conguration du registre I2C CR1 se r esume ` a forcer le mode i2c et non le SMBUS (l.5). Le registre I2C CR2 ne pose pas plus de dicult es, nous ne voulons pas dinterruptions, il nest donc n ecessaire que de fournir la fr equence dutilisation du p eriph erique (soit 36 MHz qui est le maximum pour APB1).
1 / 400 kHz I2C Fast Mode / I2C CCR ( i 2 c ) = I2C CCR FS // f a s t mode 3 | 0 x00 <<14 // t l o w / t h i g h = 2 | 0 x1e ; // 400 kHz : 2500 ns / ( 3 t p c l k 1 )
Le registre I2C CCR est d edi e` a la fr equence de transfert, ` a la forme du signal SCL, ainsi quau mode de fonctionnement. Nous le congurons en fast mode an de pouvoir atteindre les 400 kHz (l.2), le signal SCL aura un rapport cyclique de 1/3 (l.3) et nalement nous fournissons la dur ee de la p eriode de SCL (l.4). Cette valeur correspond ` a la dur ee de l etat haut du signal SCL divis ee par la p eriode de lhorloge(I2C CR2) [RM0008, p.755]. Donc il nous faut en premier lieu conna tre cette dur ee en divisant la p eriode de SCL (400 kHz : 2500 ns) par 3. Ce qui nous donne 833,33 ns, et nalement diviser ce r esultat par 27,778 ns (36 MHz) ce qui nous donne 30 ou 0x1e.
I2C TRISE ( I2C1 ) = 1 1 ; 2 / Enable t h e p e r i p h e r a l . / 4 I2C CR1 ( I2C1 ) | =I2C CR1 PE ;
La derni` ere partie va consister ` a congurer I2C TRISE. Ce registre correspond au nombre maximum de p eriode de lhorloge APB1 incr ement e de 1 pour la dur ee de transition entre l etat bas et l etat haut des signaux SCL et SDA. Cette information na pas de relation avec la vitesse de communication. Elle d epend du mode de communication et se trouve dans les sp ecications du protocole I2C. Elle est de 1000 ns en standard mode et 300 ns en fast mode. La donn ee ` a charger
17
dans le registre correspond donc, puisque nous sommes en fast mode, ` a (300 ns/27,778 ns) ce qui donne 10,8. Cette valeur nest pas enti` ere, il faut donc la tronquer, soit 10. Le r esultat etant donc 11. Finalement nous activons le p eriph erique (l.4). La conguration du p eriph erique etant nie, nous allons ajouter les fonctions de communications sur bus i2c. En se basant sur la documentation de lEEPROM, la lecture des 4 octets n ecessaires va se faire de la fa con suivante : g en eration dun start bit, suivit de lenvoi de ladresse de lEEPROM en mode ecriture, le composant va produire un ACK, suite ` a quoi le microcontr oleur envoie ladresse de la position en m emoire du premier octet ` a lire, cette seconde transmission va etre egalement acquitt ee par lEEPROM ; le microcontr oleur va re-g en erer un start bit et envoyer ladresse de lEEPROM mais en mode lecture (bit de poids faible ` a 1), comme pr ec edemment lEEPROM va acquitter la ` la n de chacun commande. Ensuite la m emoire va fournir les octets s equentiellement. A deux, le microcontr oleur devra produire un ACK sauf pour le dernier octet o` u ce sera un NACK pour avertir le composant que la lecture est nie. Et nalement un stop bit est envoy e. Par commodit e nous allons cr eer une fonction dont le seul but sera de g en erer le start bit :
void i 2 c s e n d s t a r t ( void ) 2{ / send s t a r t / 4 I2C CR1 ( I2C1 ) | = I2C CR1 START ; w h i l e ( ! ( I2C SR1 ( I2C1 ) & I2C SR1 SB ) ) ; 6}
Le bit START du registre I2C CR1 est mis ` a 1, ensuite le STM32 se met en attente du passage ` a1 du bit SB de I2C SR1 (start bit envoy e). Une seconde fonction va etre utilis ee pour lenvoi dun octet au composant, en mode ecriture :
v o i d i 2 c s e n d m e s s ( u i n t 8 t o f f s e t , u i n t 8 t data ) 2{ uint32 t reg32 ; 4 / Send d e s t i n a t i o n a d d r e s s . / I2C DR ( I2C1 ) = addr ; 6 w h i l e ( ! ( I2C SR1 ( I2C1 ) & I2C SR1 ADDR ) ) ; / C l e a n i n g ADDR / 8 r e g 3 2 = I2C SR2 ( I2C1 ) 10 12 } / Send data / I2C DR ( I2C1 ) = data ; w h i l e ( ! ( I2C SR1 ( I2C1 ) & ( I2C SR1 BTF | I2C SR1 TxE ) ) ) ;
Ladresse du composant est mise dans le registre de donn ee, puis le STM32 se met en attente de la n de la transmission (indiqu ee par le bit ADDR de I2C SR1). Celui-ci passe ` a 1 lorsque ladresse a et e envoy ee et que le composant esclave ` a transmis le ACK. La documentation du microcontr oleur pr ecise quil est egalement n ecessaire de lire I2C SR2 (l.8). Finalement il ne reste plus qu` a envoyer notre donn ee, dans le cas pr esent loset du contenu de lEEPROM. Cette transmission se fait de la m eme mani` ere que pour ladresse, mais avec une attente sur linformation buer denvoi vide (I2C SR1 TxE) et transfert ni (I2C SR1 BTF). La partie r eception est un peu plus complexe ` a mettre en uvre. En fait il est n ecessaire de g erer deux cas de gures. Lobtention dun octet di erent du dernier et le dernier. La documentation du STM32 pr ecise quil faut sp ecier quelle sera la r eponse ( (N)ACK) faite pour la r eception du prochain octet avant de se mettre en attente de la n de la transmission de ladresse, il nest donc pas possible dutiliser la fonction cr e ee pr ec edemment.
1 v o i d r e c e i v e M e s s ( u i n t 8 t addr , { 3 uint32 t reg32 ; u i n t 1 6 t pos =0; 5 / Send d e s t i n a t i o n a d d r e s s . I2C DR ( i 2 c ) = addr ; // admis 7 I2C CR1 ( i 2 c ) | = ( I2C CR1 POS u i n t 8 t data )
/ que l e b i t de mode e s t f o u r n i );
18
I2C CR1 ( i 2 c ) | = I2C CR1 ACK ; w h i l e ( ! ( I2C SR1 ( i 2 c ) & I2C SR1 ADDR ) ) ; r e g 3 2 = I2C SR2 ( i 2 c ) ;
ecise que le (N)ACK La di erence avec le code pr ec edent r eside aux lignes 7 et 8. I2C CR1 POS pr sera emis lors de la r eception du prochain octet, le I2C CR1 ACK pr ecise que ce sera un ACK.
2 4 6 8 10 12 14 } 16 } } w h i l e ( l e n != 0 ) { i f ( l e n >1) { w h i l e ( ! ( I2C SR1 ( i 2 c )&I2C SR1 RxNE ) ) ; data [ pos++] = I2C DR ( i 2 c ) ; l e n ; }else { I2C CR1 ( i 2 c ) &= ( I2C CR1 POS ) ; I2C CR1 ( i 2 c ) &= I2C CR1 ACK ; I2C CR1 ( i 2 c ) | = I2C CR1 STOP ; w h i l e ( ! ( I2C SR1 ( i 2 c ) & I2C SR1 RxNE ) ) ; data [ pos++]= I2C DR ( i 2 c ) ; len = 0;
Ensuite il faut boucler tant quil y a des octets ` a recevoir en dissociant deux cas : le cas o` u il reste plus quun octet ` a recevoir. Lattente se fait sur le simple fait davoir le registre de donn ee non vide (I2C SR1 RxNE) ; le cas o` u le prochain octet est le dernier. Avant de se mettre en attente de la r eception il est n ecessaire de congurer le STM32 pour quun NACK (l.8) soit envoy e` a la n de la r eception de loctet en cours de transfert (l.7), suivit par le stop bit (l.9). Et nalement nous cr eons une fonction qui va faire appel ` a toutes les fonctions pr esent ees pour obtenir les informations dont nous avons besoin.
uint8 t res [ 4 ] ; 2 i 2 c i n i t ( I2C1 ) ; 4 // e n v o i de l a d r e s s e du p r e m i e r o c t e t 6 i2c SendStart () ; i 2 c s e n d m e s s (HH10D ADDR, HH10D SENS) ; 8 // e n v o i de l a commande de l e c t u r e 10 // e t r e c u p e r a t i o n d e s o c t e t s i2c SendStart () ; 12 i 2 c r e c e i v e M e s s (HH10D ADDR | 0 x01 , r e s , 4 ) ; s e n s i v i t y = r e s [0] < < 8 | r e s [ 1 ] ; 14 o f f s e t = r e s [2] < < 8 | r e s [ 3 ] ;
Ainsi nous en avons ni avec lobtention des param` etres de calibrage du capteur et nous pouvons passer ` a lacquisition de donn ees. 8.2.3 R ecup eration de la p eriode du signal et du rapport cyclique
Figure 8 Utilisation du mode input capture sur un signal appliqu e` a la broche TIM2 CH2. Le registre TIM2 CCR1 m emorise le contenu du compteur TIM2 CNT pour chaque front montant du signal.
19
XX
Figure 9 Utilisation du mode pwm input capture, le registre TIM2 CCR2 est mis ` a jour pour ` noter que la chaque front montant du signal et le registre TIM2 CCR1 chaque front descendant. A d etection dun front montant r einitialise le contenu de TIM2 CNT (compteur global du timer). Chaque timer du STM32 dispose de 4 canaux pouvant etre reli es aux broches du bo tier. Chacun de ces canaux est capable de capturer la p eriode dun signal (dur ee entre deux fronts montants ou descendants successifs), cest le mode input capture (Fig. 8). Tel que repr esent e sur a jour avec la valeur courante cette gure, le registre correspondant au canal 1 (TIM2 CCR1) est mis ` du compteur global. Il existe une variante de ce mode dans lequel deux canaux sont li es (Fig. 9) et observent le m eme signal. Un des canaux (le canal 2 sur la gure) est utilis e pour lobtention de la p eriode de la m eme mani` ere quen input capture. Le second canal (canal 1) va etre sensible au front oppos e du signal, ainsi sur la gure, ce canal fournira la dur ee de l etat haut. An de synchroniser les deux canaux, lorsque la condition de d eclenchement du canal ma tre (canal 2) se produit, le compteur global du timer est remis ` a 0. Dans ce cas un timer ne pourra plus etre utilis e que pour une seule capture. Comme pour tous les p eriph eriques du STM32, il est n ecessaire dactiver lhorloge pour TIM2 (sur APB1) et pour le port contenant la broche PA1 (APB2), ainsi que de congurer cette derni` ere en INPUT FLOAT). La conguration du timer2 en pwm input capture commence par le r eglage du compteur global de ce p eriph erique (valeur maximale du compteur, fr equence de comptage, etc.). Nous savons que le HH10D g en` ere une fr equence entre 5 kHz et 10 kHz. Donc nous devons pouvoir compter, au moins, jusqu` a 200 s. La fr equence de lhorloge utilis ee pour tous les timers (sauf TIM1) d epend de APB1 et de son prescaler 8 : sil nest pas utilis e la fr equence de TIMxCLK est identique ` a APB1 ; sil est utilis e alors la fr equence de TIMxCLK est le double de celle de APB1. Comme la PLL qui fournit la fr equence aux APBx est de 72 MHz, le prescaler de APB1 est utilis e (division par 2 pour ne pas d epasser les 36 MHz). Ainsi TIM2CLK vaut 36 MHz x 2 (= ` cette fr 72 MHz), soit une p eriode de 14 ns. A equence, il est possible de compter jusqu` a 910215 ns, soit 900 s, ce qui est plus que susant pour nos besoins. Il serait possible de r eduire la vitesse mais nous aurions une perte de pr ecision.
void timeBaseInit ( ) 2{ TIM CR1(TIM2) = TIM CR1 CKD CK INT / c l o c k d i v i s i o n / 4 | TIM CR1 DIR UP ; / S e t t h e P r e s c a l e r v a l u e / 6 TIM PSC(TIM2) = 0 ; TIM ARR(TIM2) = 0 x f f f f ; 8}
e ` a la fr equence de lhorloge Nous congurons TIM CR1 pour que le compteur soit cadenc dentr ee (l.1) et sincr emente (l.2). Nous congurons TIM2 PSC pour que le compteur soit incr ement e a chaque p ` eriode de lhorloge dentr ee donc ` a 72 MHz. Le compteur repassera ` a 0 lorsquil atteindra 0x. Une fois la base de temps d enie, il faut congurer les deux canaux du timer. Les canaux 1 et 2 peuvent etre utilis es avec comme source les broches TIM2 CH1 ou TIM2 CH2
8. cette information est seulement donn ee sur la [RM0008, g.8 p.90]
20
Du point de vue de la conguration, les 4 canaux partagent le registre TIM2 CCER, TIM2 CH1 et TIM2 CH2 partagent TIM2 CMR1 et TIM2 CH3 et TIM2 CH4 partagent TIM2 CMR2 Voyons donc dabord la conguration du canal 2 :
void channel2 config ( ) 2{ / D i s a b l e c a p t u r e on c h a n n e l 2 and r e s e t c a p t u r e p o l a r i t y / 4 TIM CCER(TIM2) &= ((1 < < 4) | (1 < < 5) ) ; // S e t c a p t u r e on r i s i n g edge 6 TIM CCER(TIM2) | = 0 <<5; 8 10 12 14 / R e s e t Channel 2 c o n f i g u r a t i o n / TIM CCMR1(TIM2) &= 0 x f f 0 0 ; / S e l e c t t h e i n p u t and s e t t h e f i l t e r / TIM CCMR1(TIM2) | = 1 <<12// s a m p l i n g = f c k i n t | (0 << 10) // no p r e s c a l e r , c a p t u r e done f o r each e v e n t | ( 0 x01 <<8) ; // d i r e c t : TI2 i s used a s i n p u t // Enable c a p t u r e on c h a n n e l 2 TIM CCER(TIM2) = 1 <<4;
Le canal 2 est congur e pour etre d eclench e sur le front montant du signal (l.6). a la fr equence de Ensuite nous congurons le registre TIM CCMR1 pour que le canal fonctionne ` lhorloge sans prescaler et nous sp ecions que le canal 2 est connect e en direct (sur TIM2 CH2). Il ne nous reste plus nalement qu` a activer le canal (l.15). Si nous ne souhaitons faire que du input capture, la conguration est quasiment nie ` a ce stade. Mais comme nous allons utiliser le mode PWM, il est encore n ecessaire de congurer le canal 1. Pour eviter dajouter trop de code et comme les deux congurations sont pratiquement identiques seul loset di` ere (il faut enlever 8 ` a chaque d ecalage sur TIM CCMR1 et 4 sur TIM CCER). Les seules lignes r eellement importantes concernent le front de d eclenchement et le passage en mode indirect, cest-` a-dire la connexion du canal 1 sur la broche TIM2 CH2. Pour le canal 2 en mode direct nous avions :
1TIM CCER(TIM2) | = 0 <<5;
et :
1 | ( 0 x01 <<8) ; // d i r e c t : TI2 i s used a s i n p u t
et :
1 | ( 0 x02 <<0) ; // i n d i r e c t : TI2 i s used a s i n p u t
Pour nir avec la conguration du p eriph erique nous avons besoin de synchroniser les deux canaux.
1 3 / S e t t h e I n p u t T r i g g e r s o u r c e / TIM SMCR(TIM2) = 1<<7 // master s l a v e mode e n a b l e | 0 x05 <<4 // s e l e c t TI2FP2 f o r s y n c h r o | 0 x4 ; // r i s i n g edge r e s e t c o u n t e r
Nous passons donc le timer en mode ma tre esclave (l.2), avec une synchronisation des canaux sur TI2FP2 (broche TIM2 CH2) et avec remise ` a 0 du compteur lors dun front montant d etect e sur cette broche. Il ne reste plus qu` a activer le p eriph erique :
TIM CR1(TIM2) | = TIM CR1 CEN
Pour nir nous ajoutons une fonction pour obtenir les informations concernant la forme du signal et pour calculer le taux dhumidit e:
1 f l o a t getHumidity ( ) { 3 u i n t 1 6 t p e r i o d , DutyCycle ; f l o a t time , f r e q ; 5 w h i l e ( ( TIM SR (TIM2) & ( TIM IT CC2 ) ) == 0 x00 ) ; / Get t h e p e r i o d v a l u e / 7 p e r i o d = TIM2 CCR2 ; / Duty c y c l e v a l u e / 9 DutyCycle = TIM2 CCR1 ; 11 time = p e r i o d 1 3 . 8 8 9 ; / / TIME BASE ; f r e q = ( 1 0 0 0 0 0 0 / time ) 1 0 0 0 . 0 f ;
21
13
r e t u r n ( f l o a t ) ( ( o f f s e t f r e q ) s e n s i v i t y ) /4096
le STM32 est mis en attente dun front montant (et donc de la n de la capture) (l.5), les valeurs mesur ees sont disponibles dans le registre relatif au canal 2 pour la p eriode (l.7) et au canal 1 pour la dur ee de l etat haut du signal (l.9). Nous convertissons la valeur de la p eriode en une dur ee (l.11) puis en une fr equence en kHz (l.12) et nous r ealisons le calcul pour obtenir le taux dhumidit e.
Figure 10 Exemple de courbe dhumidit e sur la p eriode du 11-02-2012 14:50 au 23-02-2012 13:08. On peut constater les fortes variations entre le jour et la nuit.
8.3
8.3.1
TEMT6000 : ADC
Pr esentation
Le dernier composant que nous allons mettre en uvre est le TEMT6000[TEMT6000]. Cest un capteur de lumi` ere ambiante. Ce composant se pr esente sous la forme dun transistor NPN (mont e en collecteur commun avec une r esistance de 10 k) qui fournit une tension proportionnelle ` a lintensit e lumineuse. Pour cela nous allons utiliser lADC du STM32, le composant etant connect e sur la broche PA0. 8.3.2 Conguration et acquisition
Contrairement aux pr ec edents exemples, lADC dispose dun prescaler au niveau du RCC. Ce composant ne peut pas etre cadenc e` a plus de 14 MHz, la fr equence dentr ee du prescaler etant donn ee par APB2 (72 MHz dans notre cas). Il nest possible que de faire des divisions par 2,4,6,8. Ainsi pour obtenir la fr equence la plus rapide sans d epasser la limite, il faut donc diviser par 6.
1RCC CFGR &= ( 0 x02 <<14) ; RCC CFGR | = 0 x02 <<14;
Le coecient de division etant donn e [RM0008, p.125] (2 correspond ` a une division par 6). L etape, classique, et suivante consiste en lactivation du p eriph erique et du port contenant la GPIO qui nous int eresse. Il faut donc activer ADC1 et le port A sur APB2. La broche sur etre congur ee en mode entr ee et de type laquelle est connect ee etant PA0 (ADC1 0), elle doit INPUT ANALOG. 22
Apr` es la d esactivation du ph eriph erique nous congurons les deux registres de contr ole. Pour ADC CR1 nous ne souhaitons pas lutilisation du watchdog, ni des modes tels que scan mode ou dual mode, et nous nallons pas utiliser dinterruptions, sa conguration se r esume ` a y mettre 0. Pour ADC CR2 le r esultat est le m eme car nous nallons pas utiliser la temp erature du STM32, nous nexploiterons pas plus le d eclenchement de la conversion sur ev` enement, ni le DMA et nous souhaitons que les 12 bits issus de la conversion soient align es ` a droite (bit de poids faible). Nous congurons ensuite le temps de conversion du canal que nous allons exploiter :
1 3 / 2 8 . 5 c y c l e f o r c h a n n e l 0 / ADC SMPR2(ADC1) &=(0x07 ) ; ADC SMPR2(ADC1) | =(0 x03 ) ;
Pour cela plusieurs registres sont disponibles, pour le cas qui nous int eresse, le canal 0 de lADC es ` a ce canal sont remis se trouve (ainsi que les canaux < 10) dans ADC SMPR2. Les trois bits destin a 0 puis nous le congurons pour avoir un temps de conversion de 28,5 cycles (valeur 3 [RM0008, ` p.235]). Avec cette conguration le temps de conversion sera de 3,41 s (tconv = (sample time + 12,5 cycles)*p eriode de ADCCLK) [RM0008, section 11.6, p.216] Maintenant il nous faut activer et calibrer lADC :
1 3 5 7 / e n a b l e ADC1 / ADC CR2(ADC1) | = ADC CR2 ADON ; / r e s e t c a l i b r a t i o n / ADC CR2(ADC1) | = ADC CR2 RSTCAL ; w h i l e ( ( ADC CR2(ADC1) & ADC CR2 RSTCAL) != 0 x00 ) ; / c a l i b r a t i o n / ADC CR2(ADC1) | = ADC CR2 CAL ; w h i l e ( ( ADC CR2(ADC1) & ADC CR2 CAL) != 0 x00 ) ;
Cette etape se fait en deux temps, nous commen cons par r einitialiser le registre de calibrage (l.4) et attendons que le bit soit remis ` a 0 (l.5) signiant que lop eration sest eectu ee avec succ es. Ensuite nous lan cons le calibrage (l.7) et attendons la n du traitement (l.8). Pour nir avec la conguration, il faut sp ecier quel sera le canal qui sera utilis e (dans cet exemple nous nutilisons quun seul canal, mais nous pourrions aller jusqu` a 16).
2 4} ADC SQR1( adc ) = 0 < < 20 | 0; ADC SQR2( adc ) = 0 ; ADC SQR3( adc ) = 0 ;
Le registre ADC SQR1 contient ` a la fois 4 bits (bits [23:20]) pour sp ecier le nombre de canaux ` a exploiter ` a chaque fois quune conversion est lanc ee, 0 signiant une conversion. Le reste de ce registre contient lordre des canaux lorsque plus de 12 conversions sont ` a faire. le registre ADC SQR2 comporte les canaux pour les conversions 12 ` a 7, et nalement ADC SQR3 pour les conversions 6 ` a 1. Comme nous ne voulons quune seule conversion sur le canal 0 nous laissons ce dernier registre a 0. ` Nous en avons donc ni avec la conguration. Une demande de conversion se fait de la fa con suivante :
uint16 t getConversion () 2{ ADC CR2(ADC1) | = ADC CR2 ADON ; 4 / Wait f o r end o f c o n v e r s i o n . / 6 w h i l e ( ( ADC SR(ADC1) & ADC SR EOC)==0x00 ) ; 8 10 } temp = ADC DR(ADC1) ; r e t u r n ( 3 3 0 0 temp / 4 0 9 5 ) ;
23
Une conversion est d eclench ee quand le bit ADON est remis ` a 1 (l.3). Nous attendons ensuite a 1 (l.6) pour r ecup erer le r esultat de la conversion que le bit SR EOC du registre ADC SR passe ` (l.8). Comme lADC est sur 12 bits et que la valeur maximale correspond ` a 3,3 V nous divisons le r esultat par 4095 puis nous le multiplions par 3300 pour retourner le r esultat en milivolts (Fig. 11).
Figure 11 Evolution de l eclairage sur la p eriode du 11-02-2012 14:50 au 23-02-2012 13:08. Ce capteur semble n ecessiter un remplacement de la r esistance (1 k au lieu de 10 k) an dobtenir plus de d etails concernant les maxima.
8.4
Nous avons ` a disposition lensemble des pilotes n ecessaires ` a la fois pour lexploitation du STM32 mais egalement pour la communication et le traitement des donn ees acquises des capteurs de la station.
void init component ( ) 2{ init hh10d () ; 4 ms5534a init () ; init adc () ; 6 s y st i c k i n i t () ; } 8 i n t main ( v o i d ) 10 { f l o a t temp , hygro ; 12 uint32 t pressure ; uint16 t lux ; 14 char b u f f e r [ 2 5 6 ] ; 16 18 20 22 clock setup () ; usart3 setup (57600) ; init component () ; while (1) { hygro = getHumidity ( ) ; m s 5 5 3 4 a r e a d p r e s s u r e a n d t e m p (&temp , &p r e s s u r e ) ;
24
l u x = readAdc ( 0 ) ; 24 26 28 Delay ( 6 0 0 0 ) ; 30 } } s p r i n t f ( b u f f e r , %04d %03 f %04 f %04u \ r \ n , ( i n t ) p r e s s u r e , temp , hygro , l u x ) ; usart3 put string ( buffer ) ;
Il faut donc associer tout ca dans un main(). Pas grand chose de complexe, apr` es la conguration du STM32 comme pr esent ee au d ebut, nous congurons lUSART3 sur lequel est connect e le convertisseur bluetooth-s erie. Lensemble des composants est ensuite congur e ainsi que le systick pour appliquer une pause entre chaque envoi. Dans notre boucle innie, les donn ees sont acquises, format ees et envoy ees, toutes les 6 secondes. Bien entendu, une attente active faite par notre fonction Delay nest pas id eale. Il serait plus judicieux dexploiter lun des modes de mise en veille du microcontr oleur an de r eduire la consommation globale de la station.
Le STM32 (et plus largement lensemble des cortex-m3 semble-til) dispose de trois modes faibles consommations : le sleep mode qui ne fait quarr eter lhorloge du CPU, mais laisse actif les quartz ainsi que les p eriph eriques. Le microcontr oleur peut etre r eveill e` a laide dune interruption ; le stop mode qui arr ete les quartz haute fr equence et la plupart des p eriph eriques. La seule possibilit e pour sortir le microcontr oleur de ce mode est quil re coive une interruption externe (broches d edi ees) ; le standby mode qui a les m emes caract eristiques que le pr ec edent, mais qui autorise le r eveil a laide de la RTC(Real Time Clock). Ce mode est le plus ` economique mais pr esente le d efaut de remettre le STM32 dans son etat initial (perte des congurations des registres et remise a z ` ero de la m emoire), comme apr` es une mise ` a GND de la broche RESET. Nous allons nous int eresser plus sp ecialement au standby mode en reposant le r eveil sur lusage de lhorloge temps-r eel (RTC). Pour simplier cette pr esentation et comme ce nest pas r eellement un point critique ` a comprendre en terme de programmation nous allons faire usage de la libopencm3, seuls les parties non disponibles dans celle-ci seront faites ` a la main. Lexemple ci-dessous initialise lhorloge temps-r eel pour sincr ementer toutes les secondes (compteur ` a 0x7f sur le quartz ` a 32768 Hz) et place le microcontr oleur en mode de veille profonde tel que d ecrit dans la section 5.3 de [RM0008, p.70]. Lors de chaque interruption, lalarme est incr ement ee de 10 s.
1#d e f i n e temps mesure 10 // exprime en s e c o n d e 3 void i n i t r t c ( void ) { 5 // e n a b l e c l o c k r c c p e r i p h e r a l e n a b l e c l o c k (&RCC APB1ENR, 7 RCC APB1ENR BKPEN | RCC APB1ENR PWREN) ; //BKP ( backup domain ) 9 11 13 15 17 } 19 void r t c i s r ( void ) r t c a u t o a w a k e (LSE , 0 x 7 f f f ) ; / Without t h i s t h e RTC i n t e r r u p t r o u t i n e w i l l n e v e r be c a l l e d . / n v i c e n a b l e i r q (NVIC RTC IRQ) ; n v i c s e t p r i o r i t y ( NVIC RTC IRQ , 1 ) ; / Enable t h e RTC i n t e r r u p t t o o c c u r o f f t h e SEC f l a g . / r t c i n t e r r u p t e n a b l e (RTC ALR) ; rtc enable alarm () ;
25
21 { if 23 25 } } ( (RTC CRL & RTC CRL ALRF) != 0 x00 ) { r t c c l e a r f l a g (RTC ALR) ; r t c s e t a l a r m t i m e ( r t c g e t c o u n t e r v a l ( ) + temps mesure ) ;
An d etre en mesure dutiliser la RTC, il est n ecessaire dactiver ` a la fois le backup domain et le power control. Ensuite la RTC elle-m eme est congur ee pour etre cadenc ee par le quartz basse fr equence externe et pour incr ementer le compteur toutes les secondes. Il ne reste plus ensuite qu` a activer globalement les interruptions pour la RTC et sp ecier que l ev enement alarme ( valeur congur ee du compteur atteinte) doit d eclencher une interruption. ealis e la fonction rtc isr est le gestionnaire dinterruptions pour la RTC. Le seul traitement r etant dacquitter linterruption puis de r eamorcer lalarme pour un d eclenchement temps mesure apr` es la date actuelle. Dans notre cas ce traitement na pas r eellement dint er et car le STM32 sera r einitialis e d` es le d eclenchement de cette interruption.
v o i d PWR EnterSTANDBYMode( v o i d ) 2{ / S e t SLEEPDEEP b i t o f Cortex System C o n t r o l R e g i s t e r / 4 SCB SCR | = SCB SCR SLEEPDEEP ; / S e l e c t STANDBY mode / 6 PWR CR | = PWR CR PDDS ; / C l e a r Wakeup f l a g / 8 PWR CR | = PWR CR CWUF; asm v o l a t i l e ( WFI ) ; 10 }
Cette fonction est la plus importante pour le passage en standby mode. Le registre SCB SCR nest pas document e dans [RM0008] car il est relatif au cur ARM CM3. le bit SCB CR SLEEPDEEP sert a d ` eterminer si le processeur doit passer en sleep mode ou dans lun des deux autres modes. Le bit PWR CR PDDS sp ecie que le STM32 va entrer en standby mode (bit ` a 1) ou en stop mode (bit ` a 0) lors du passage en mode deep sleep. Le passage en mode basse consommation est ensuite valid e par la mn emonique WFI.
i n t main ( v o i d ) 2{ [...] 4 i n i t r t c () ; 6 8 10 } [...] r t c s e t a l a r m t i m e ( r t c g e t c o u n t e r v a l ( ) + temps mesure ) ; PWR EnterSTANDBYMode ( ) ; while (1) ;
Apr` es conguration de la RTC, nous r ealisons nos traitements. Quand ceux-ci sont ni nous xons le moment o` u la RTC va produire son interruption et nous rentrons dans la fonction qui passe le STM32 en mode basse consommation. La boucle innie ne sera nalement jamais atteinte car ` a la sortie de WFI le STM32 sera r einitialis e. Les mesures de consommation (table 1) se font dans un premier temps avec un convertisseur s erie-USB FT232RL en mode veille (RESET# en position basse), avant que les r esultats excessivement elev es nous obligent ` a eectuer une mesure nale avec le STM32 seul, en mode veille, sans aucun composant p eriph erique autre que les condensateurs de d ecouplage et les quartz. Lors de la pr esence du FTDI, la liaison asynchrone entre le FTDI (TX et RX) et le STM32 se fait au travers de r esistances de 36 k. Dans cet exemple nous ne faisons rien de particulier, mais il peut sembler parfois laborieux voir consommateur en ressources de devoir, pour chaque r eveil, faire toute une s erie dinitialisation du fait de la r einitialisation de la m emoire volatile. Pour palier ` a ce probl` eme le STM32 dispose de 16 registres de 16 bits (BKP DRxx) qui ne seront pas r einitialis es lors de la mise en veille, ils peuvent donc permettre d eviter certains traitements pouvant etre fait une fois et r eutilis es ensuite. ` titre indicatif, la fonction RTC GetTime() propose une lecture du contenu du registre de A lhorloge temps-r eel en vue dune datation des trames acquises.
1 v o i d RTC GetTime ( v o l a t i l e u32 THH, v o l a t i l e u32 TMM, v o l a t i l e u32 TSS )
26
Statut STM32 seul FTDI seul (USB retir e, RESET#=bas) mode veille profonde (quelque soit cong. quartz) mode veille (Sleep) (quelque soit cong. quartz) quartz externe 8 MHz, PLL 72 MHz quartz externe 8 MHz, PLL 24 MHz oscillateur interne, PLL 24 MHz oscillateur interne, PLL 64 MHz
Table 1 Mesures de consommation sur un circuit contenant un STM32F103RCT6, avec ou sans (premi` ere ligne uniquement) FT232 : nous constatons quen mode actif, la consommation cro t avec la vitesse dhorloge du cur, mais semble ind ependant de la nature de loscillateur. Un courant de fuite important aecte les mesures lorsque le STM32 est connect e au FT232 : en enlevant ce dernier, la consommation en mode de veille profonde chute ` a 3,6 A, une valeur qui nest que le double de celle observ ee sur MSP430 [MSP430].
{ v o l a t i l e u32 tmp ; 3 tmp = r t c g e t c o u n t e r v a l ( ) ; THH = ( tmp / 3 6 0 0 ) % 2 4 ; 5 T M M = ( tmp / 6 0 ) % 6 0 ; TSS = tmp % 6 0 ; 7}
Le STM32 na pas vocation ` a etre exploit e dans les applications ` a tr` es basse consommation. N eanmoins, mentionnons que la s erie de processeurs Tiny Gecko de Energy Micro 9 annonce des consommations aussi basses que 900 nA en mode veille et 20 nA lorsque d esactiv es. Un port de la biblioth` eque libopencm3 pour ces processeurs semble etre amorc ee.
10
Nous avions d ej` a mentionn e auparavant les perspectives spectaculaires oertes, pour les syst` emes embarqu es par la capacit e` a stocker des informations sur support non-volatile de type Secure Digital (SD), et en particulier la capacit e` a organiser les donn ees selon des chiers exploitables par tout utilisateur gr ace au format FAT [LM117]. Nous avions propos e la biblioth` eque EFSL qui, de par son excellente structuration, ne n ecessite que le portage de quelques fonctions bas niveau pour etre utilisable sur une nouvelle architecture. Nous avons donc modi e EFSL pour une utilisation sur STM32 avec biblioth` eque libopencm3. Nous nexploitons cependant pas les fonctionnalit es avanc ees de cette architecture telles que la capacit e ` a transf erer les donn ees par DMA, optimisation qui m eriterait ` a etre impl ement ee pour r eduire limpact du stockage sur lecacit e du programme principal. Dans larborescence dEFSL, lunique chier contenant la description des acc` es bas-niveau entre le microcontr oleur et la carte SD communiquant au travers du protocole SPI se trouve dans efsl/source/interface/efsl spi.c. Dans ce chier, nous red enissons, tel que vu auparavant, la direction et la fonction des broches associ ees ` a SPI1 (port A) au niveau de SPI Config(), ainsi que les macros d enissant le niveau du signal dactivation de la carte (GPIOA 4 dans notre exemple).
1#d e f i n e MSD CS LOW( ) g p i o c l e a r (GPIOA, GPIO4) #d e f i n e MSD CS HIGH ( ) g p i o s e t (GPIOA, GPIO4)
Les fonctions de communication sur bus SPI sont d ej` a encapsul ees dans libopencm3 sous forme de spi send(SPI1, outgoing); et incoming = spi read(SPI1);. Rapidement, nous avons ainsi
9. http://www.energymicro.com/news-archive/energy-micro-launches-efm32-tiny-gecko-microcontrollers
27
la satisfaction dacc eder ` a un chier dans un r epertoire et dy stocker des informations dans un format accessible sur tout ordinateur personnel.
char ouvre sd ( ) 2 { char e r r ; e r r = e f s i n i t (& e f s , 0 ) ; 4 i f ( ( e r r ) != 0 ) { r e t u r n ( 0 ) ; } e l s e { SD Present = 1 ; // SD ok 6 // C r e a t i o n du r e p e r t o i r e i f ( mkdir(& e f s . myFs , GPR ) == 0 ) // s i i l n e x i s t e pas 8 a f f i c h e (# New data d i r e c t o r y c r e a t e d . \ r \ n ) ; else 10 a f f i c h e (# u n a b l e t o c r e a t e new d i r ( a l r e a d y e x i s t i n g ? ) \ r \ n ) ; 12 // i l FAUT u t i l i s e r a pour append , s i n o n e r r e u r quand l e f i c h i e r e x i s t e d e j a // e t qu on u t i l i s e w 14 i f ( f i l e f o p e n (& f i l e , &e f s . myFs , GPR/DATA.TXT , a ) != 0 ) { i f ( f i l e f o p e n (& f i l e , &e f s . myFs , GPR/DATA.TXT , w ) != 0 ) 16 SD Present = 0 ; } 18 e l s e a f f i c h e (# F i l e Open OK\ r \ n ) ; i f ( SD Present == 1 ) 20 { f i l e f c l o s e (& f i l e ) ; f s u m o u n t (& e f s . myFs ) ; 22 } } 24 r e t u r n ( SD Present ) ; } 26 main ( ) { 28 SD Present = o u v r e s d ( ) ; i f ( SD Present == 1 ) 30 i f ( f i l e f o p e n (& f i l e , &e f s . myFs , GPR/DATA.TXT , a ) !=0) { i f ( f i l e f o p e n (& f i l e , &e f s . myFs , GPR/DATA.TXT , w ) != 0 ) 32 { SD Present = 0 ; } } 34 i f ( SD Present == 1 ) { f i l e w r i t e (& f i l e , s i z e o f ( b ) , &b ) ; // c h a r b c o n t i e n t l e t a b l e a u a e c r i r e 36 f i l e w r i t e (& f i l e , 2 , \ r \ n ) ; f i l e f c l o s e (& f i l e ) ; 38 f s u m o u n t (& e f s . myFs ) ; } e l s e { SD Present = 0 ; } 40 [...] }
Nous testons dans cet exemple si le chier de sauvegarde existe d ej` a en tentant dy ajouter les informations (mode a). En cas d echec, le chier est cr e e (mode w). Si cette cr eation echoue, il y a eu disparition de la carte depuis son initialisation (ouvre sd()) et nous la marquons comme absente, sinon le contenu du tableau de caract` eres b est transf er e sur la carte. Noter que les informations ne sont physiquement ecrites que lors du d emontage du syst` eme de chiers fs umount(). Ainsi, une application naturelle qui d ecoule de lutilisation de lhorloge temps-r eel (vue dans la section pr ec edente) et du stockage au format FAT sur carte SD est lobtention dun enregistreur autonome capable de stocker des informations dun instrument r eveill e de fa con p eriodique, et ce en labsence dintervention des utilisateurs pendant un intervalle de temps d eni par lautonomie des batteries alimentant le circuit. En ce sens, nous avons constat e que toutes les cartes SD ne se valent pas, et tandis que certains mod` eles passent automatiquement en mode veille une fois la phase d ecriture achev ee, les mod` eles les moins chers continuent ` a drainer un courant important m eme en labsence de toute op eration. La fa con la plus s ure de r eduire la consommation est donc dalimenter la carte SD au travers dun r egulateur DC-DC avec d esactivation (shutdown) ou dun interrupteur analogique.
28
11
Conclusion
Cet ensemble de mises en uvre nous a permis de se faire une bonne id ee de la mani` ere dexploiter le STM32 et de congurer les p eriph eriques. Il est ainsi possible de constater que pour un p eriph erique donn e une partie est totalement li ee ` a celui-ci (activation de lhorloge pour le p eriph erique et pour le port, conguration des broches, etc...). Une seconde partie de la conguration/utilisation se base sur des registres index es par ladresse du p eriph erique. Cette partie pourra donc etre facilement incluse dans un module utilisable par tous les p eriph eriques dun m eme type. Nous navons pas d etaill es dans le pr esent article lusage du DMA, ceci est toutefois fait dans larticle Traitement du signal sur syst` eme embarqu e -- application au RADAR a onde continue. ` La compr ehension de la structure du STM32 est l etape in evitable pour etre en mesure de r ealiser le portage dun ex ecutif tel que TinyOS sur ce microcontr oleur, ainsi que nous le verrons dans un prochain article. Il est ` a noter que les STM32 disposent selon le mod` ele dun USB device , voir OTG sur les hauts de gammes. La libopencm3 ne propose ` a lheure actuelle que limpl ementation pour le mode device, la partie OTG etant ` a faire. Des exemples de port-s eries virtuels (entre autres) sont fournis avec la libopencm3.
R ef erences
[CortexM3] J. Yiu, The Denitive Guide to the ARM Cortex-M3, 2nd Ed., Newnes (2009) [RM0008] RM0008, Reference manual rev. 13, Mai 2011, disponible ` a http://www.st.com/ internet/com/TECHNICAL RESOURCES/TECHNICAL LITERATURE/REFERENCE MANUAL/ CD00171190.pdf [morse] Page wikipedia concernant lalphabet morse http://fr.wikipedia.org/wiki/Alphabet morse [MS5534] Datasheet du MS5534C (rempla cant du MS5534A) http://www.meas-spec.com/ WorkArea/linkit.aspx?LinkIdentier=id&ItemID=6673 [AN510] Utilisation du MS5534A en SPI http://www.meas-spec.com/downloads/Using SPI Protocol with Pressure Sensor Modules.pdf [HH10D] Datasheet du capteur dhumidit e HH10D http://www.hoperf.com/upload/sensor/HH10D. pdf [TEMT6000] Datasheet du capteur de lumi` ere TEMT6000 http://www.vishay.com/docs/81579/ temt6000.pdf [MSP430] J.-M. Friedt, A. Masse, F. Bassignot, Les microcontr oleurs MSP430 pour les applications faibles consommations asservissement dun oscillateur sur le GPS, GNU/Linux Magazine France 98, Octobre 2007, disponible ` a http://jmfriedt.free.fr [LM117] J.-M. Friedt & E. Carry, D eveloppement sur processeur ` a base de cur ARM7 sous GNU/Linux GNU/LINUX Magazine France 117, juin 2009, pp.32-51, disponible ` a http:// jmfriedt.free.fr
29