Scuola Politecnica e delle Scienze di Base
Corso di Laurea in Ingegneria Informatica
Elaborato finale in Misure per l’Automazione e la Produzione Industriale
Programmazione di microcontrollori
STM32: ADC e gestione interruzioni
Anno Accademico 2014/2015
Candidato:
Aniello Bossa
matr. N46001174
[Dedica]
Indice
Indice ................................................................................................................................................... V
Introduzione ......................................................................................................................................... 7
Capitolo 1: STM32............................................................................................................................... 9
1.1 STM32F3 Discovery board ........................................................................................................ 9
1.1.1 Caratteristiche ..................................................................................................................... 9
1.2 Architettura di sistema ............................................................................................................ 10
1.3 Memory Layout........................................................................................................................ 11
1.4 Safety e security ....................................................................................................................... 11
1.5 Sviluppo Software .................................................................................................................... 12
1.5.1 Realizzazione di un nuovo progetto in ambiente di sviluppo IAR ................................... 12
Capitolo 2: STM32 ADC ................................................................................................................... 21
2.1 Configurazione convertitore A/D............................................................................................. 22
2.1.1 Abilitazione dell’ADC nella periferica RCC .................................................................... 22
2.1.2 Scelta del clock dell’ADC................................................................................................. 23
2.1.3 Configurazione del Regolatore di tensione ....................................................................... 24
2.1.4 Scelta del canale di acquisizione dell’ADC ...................................................................... 24
2.1.5 Configurazione della modalità di campionamento Single-ended o differenziale ............. 25
2.1.6 Auto-Calibrazione ............................................................................................................. 26
2.1.7 Abilitazione dell’ADC ...................................................................................................... 27
2.1.8 Impostazione dei Time Sampling ..................................................................................... 28
2.1.9 Impostazione della sequenza di campionamento .............................................................. 29
2.1.10 Esempio codice ADC ...................................................................................................... 30
2.2 Acquisizione temperatura ........................................................................................................ 31
2.2.1 Codice ADC sensore di temperatura ................................................................................. 32
2.3 Acquisizione Temperatura (Hardware Trigger) ....................................................................... 33
2.3.1 Codice acquisizione temperatura (Hardware Trigger) ...................................................... 34
Capitolo 3: Gestione delle interruzioni .............................................................................................. 36
3.1 Nested Vectored Interrupt Controller (NVIC) ......................................................................... 39
3.2 Extended interrupts and events controller (EXTI) ................................................................... 40
Conclusioni ........................................................................................................................................ 42
Bibliografia ........................................................................................................................................ 43
Introduzione
In elettronica digitale il microcontrollore o microcontroller o MCU (MicroController
Unit) è un dispositivo elettronico integrato su singolo chip, nato come evoluzione
alternativa al Microprocessore ed utilizzato generalmente in sistemi embedded ovvero per
applicazioni specifiche (special purpose) di controllo digitale.
Il primo computer on-chip ottimizzato per applicazioni di controllo è stato il modello 8048
di Intel, uscito nel 1975, con RAM e ROM sullo stesso chip. Questo componente è stato
utilizzato in più di un miliardo di tastiere per PC e numerose altre applicazioni.
Nei primi anni di sviluppo del microcontrollore, la maggior parte dei modelli era
commercializzata in due varianti: la più economica era dotata di memoria di programma
programmata in fabbrica (ROM) su specifiche del cliente oppure programmabile
dall'utente una sola volta (OTP, One Time Programming); la seconda, più costosa, aveva
la memoria di programma cancellabile EPROM mediante esposizione a luce ultravioletta
del chip tramite la finestrella trasparente che lo sovrastava. La programmazione del
firmware veniva fatta direttamente in linguaggio macchina.
Lo sviluppo della tecnologia CMOS e successivamente della HCMOS, nella prima metà
degli anni ottanta, ha fornito un impulso decisivo alla diffusione dei microcontrollori,
consentendo una notevole riduzione dei consumi e della dissipazione nei chip.
Per molti anni Motorola è stata leader mondiale per i microcontrollori: il suo 68HC11 si
rivelò essere una pietra miliare, allorché fu presentato sul mercato nel 1985; oltre alla
RAM ed alla ROM integrava convertitori A/D, porte di I/O, SPI (Serial Peripheral
7
Interface), SCI (Serial Communication Interface), timers multifunzione, EEPROM,
interrupts ed altro ancora, comprendendo persino un firmware di Monitor (Buffalo) che
permetteva di effettuare il caricamento di programmi in RAM e il debug on-chip, tramite
interfaccia seriale.
Nel 1993 Microchip ha introdotto il modello di MCU PIC16C84, caratterizzato da
memoria programma in EEPROM, ovvero cancellabile elettricamente, che permetteva sia
lo sviluppo veloce del prototipo del prodotto finito, sia la modifica del Firmware a circuito
montato (In-System Programming). La semplificazione del contenitore (package), senza
finestrella in quarzo, ha contribuito a ridurre il costo finale del componente.
Nello stesso anno Atmel ha presentato il primo MCU che utilizzava una memoria di tipo
flash, ancora più semplice e veloce da programmare/modificare, più compatta e con un
ciclo di vita (cancellazioni) molto più elevato.
Nel corso degli ultimi anni, una delle maggiori tendenze è stata l’adozione di cpu con
architettura ARM7 e ARM9.
L’architettura ARM indica una famiglia di microprocessori RISC a 32-bit sviluppata da
ARM Holdings e utilizzata in una moltitudine di sistemi embedded grazie alle sue
caratteristiche di basso consumo.
Nel 2007 la STMicroelectronics annuncia la STM32F1-series, la loro prima serie basata
sul nuovo core ARM Cortex-M3, che garantisce nuovi standard per i costi e le
performance.
Una delle componenti chiave del core Cortex-M3 è il Nested Vector Interrupt Controller
(NVIC).
NVIC fornisce una struttura di interrupt standard per i microcontrollori basati su Cortex e
un vettore dedicato alle interrupt per più di 240 periferiche dove ad ogni fonte di
interruzione può essere assegnata una priorità.
Lo scopo di questa tesi è quella di avere un primo approccio con un microcontrollore della
famiglia STM32, analizzeremo in particolare il funzionamento dell’ADC e la gestione
delle interruzioni.
8
Capitolo 1: STM32
STM32 è una famiglia di microcontrollori della STMicroelectronics.
Le diverse serie di microcontrollori vengono raggruppate in base al core: Cortex-M7,
Cortex-M4F, Cortex-M3, Cortex-M0+ o Cortex-M0.
Ogni microcontrollore è costituito da un processore, una memoria SRAM, una memoria
flash, un’interfaccia di debugging e diverse periferiche.
In questa tesi esamineremo
nello specifico la STM32F3.
1.1 STM32F3 Discovery board
Innanzitutto è importante far
distinzione
tra
board
e
microcontrollore.
Il microcontrollore è soltanto
una parte della board.
1.1.1 Caratteristiche
 Core ARM Cortex-M4 32-bit CPU
con FPU (72 MHz max)
 Alimentazione da 3V a 5V
 Memoria :
o Flash 256 Kbytes
o SRAM 48 Kbytes
 CRC
 Quattro
ADCs
0.20
μS
con
9
risoluzione di 12/10/8/6 bits
 Due canali DAC da 12-bit
 L3GD20, ST MEMS sensore di movimento, giroscopio digitale a 3 assi
 LED1 (ROSSO) accensione 3.3 V
 LED2(ROSSO/VERDE) comunicazione USB
 Otto LED
 Due bottoni (utente e reset)
 Interfacce di comunicazione:
o CAN (2.0B Active)
o Due I²C fast mode plus (1Mbit/s)
o Tre SPI
o Cinque USART
1.2 Architettura di sistema
STM32 è composta dal Cortex core il quale è connesso alla memoria FLASH da un
Instruction bus (I-bus) dedicato.
Il Cortex e i System busses sono collegati alla matrice dell’ARM Advanced High Speed
Busses (AHB).
La SRAM interna è connessa direttamente all’ AHB cosi come l’unità DMA.
Le periferiche sono locate su due ARM Advanced Peripheral Busses (APB), ognuno di
questi APB è collegato all’ AHB.
L’ AHB è tarato alla stessa velocità del Cortex core, entrambi gli AHB hanno un proprio
prescaler con il quale può essere diminuita la velocita così da ridurre il consumo.
È importante notare che APB2 può lavorare a 72 MHz mentre APB1 lavora a 36 MHz.
Sia il Cortex che il DMA possono essere bus master, ma a causa del parallelismo intrinseco
della matrice dei bus sono arbitrati se entrambi tentano di accedere alla SRAM, APB1 o
APB2.
10
Il meccanismo di arbitraggio garantirà 2/3 del tempo di accesso al DMA e 1/3 al Cortex.
1.3 Memory Layout
Sebbene STM32 ha numerosi busses interni, al programmatore vengono riservati 4 Gbyte
dello spazio degl’indirizzi.
La memoria di programmazione inizia a 0x00000000. La on-chip SRAM inizia a
0x20000000 e tutte le altre SRAM interne sono posizionate nei bit iniziali.
Le periferiche utente sono memory mapped ed iniziano dall’indirizzo 0x40000000.
Infine i registri del Cortex iniziano dall’indirizzo 0xE0000000.
1.4 Safety e security
Oltre a richiedere maggiore potenza di elaborazione e periferiche più sofisticate, i
microcontrollori devono operare in ambienti critici per la sicurezza.
La STM32 ha una serie di caratteristiche hardware di supporto che garantiscono l’integrità.
Queste caratteristiche includono un rilevatore di bassa tensione, un sistema di sicurezza del
clock e due watchdog separati.
Il primo watchdog è un windowed watchdog, questo deve essere aggiornato in un periodo di
tempo predefinito se viene attivato troppo presto o troppo tardi genererà un trigger.
11
Il secondo watchdog è indipendente e possiede un oscillatore esterno separato dal clock di
sistema.
Un altro aspetto importante della sicurezza è la protezione del codice, la memoria FLASH
dell’STM32 può essere bloccata in lettura, in questo caso la memoria è bloccata anche in
scrittura così da impedire l’inserimento di codice non attendibile nel vettore delle
interruzioni.
Inoltre il resto della memoria FLASH può essere bloccata in scrittura.
1.5 Sviluppo Software
Il software che utilizzeremo per lo sviluppo di un progetto sarò IAR Embeddeb Workbench,
questo software ci permetterà di programmare in codice C.
1.5.1 Realizzazione di un nuovo progetto in ambiente di sviluppo IAR
Apriamo l’ambiente di sviluppo IAR
Creiamo un nuovo workspace. Dal menu a tendina selezioniamo le voci
FILE->NEW->WORKSPACE
Creiamo un nuovo progetto.Sempre dal menu a tendina selezioniamo le voci
PROJECT->CREATE NEW PROJECT
Compare la schermata
12
In questa schermata selezioniamo la voce Empty proect e premiamo OK.
Compare la schermata che ci chiede di salvare il progetto nella cartella desiderata. In questo
esempio creiamo una cartella che conterrà tutti i nostri progetti futuri e una sottocartella che
conterrà il nostro primo progetto.
Nominiamo il progetto e salviamolo nella cartella.
13
Nel Workspace compare quindi il nostro primo progetto.
Posizioniamoci sul progetto nel workspace con il cursore del mouse e con il tasto destro
selezioniamo l'opzione Options...
14
Compare la schermata che ci permette di selezionare le varie opzioni del progetto, Options for
node "Primo progetto"
Di default è selezionata la categoria "General Options"->Target. Qui dobbiamo selezionare il
device. Quindi in Processor variant spuntiamo su Device.
15
In corrispondenza di Device c'è l'icona che apre la lista dei device dalla quale occorre selezionare il
device STM32F303xC
16
Questo processore ha un'unità Floating point per operazioni su numeri con virgola mobile per cui in
FPU troviamo VFPUv4.
Una volta selezionato il device selezioniamo la categoria C/C++ Compiler e quindi l'opzione
Preprocessor per selezionare le cartelle a cui il compilatore deve fare riferimento. Per aggiungere
cartelle al progetto clicchiamo sull'iconcina in corrispondenza di Additional include directories.
Quindi si apre la schermata Edit Include Directories e in questa schermata clicchiamo su <Click
To Add> e selezioniamo le cartelle da aggiungere nel progetto.
Il file stm32f30x.h si trova nella sottocartella Libraries:
C:\..\STM32F3-Discovery_FW_V1.1.0\Libraries\CMSIS\Device\ST\STM32F30x\Include
Per includere il file nel progetto nel main aggiungiamo l'include
#include <stm32f30x.h>
17
e nelle opzioni del progetto nella categoria C/C++ Compiler->Preprocessor aggiungiamo la
cartella che include il file:
Inserire soltanto il file stm32f30x.h nel nostro progetto non è sufficiente. Infatti se si prova a
compilare il progetto viene generato un errore.
Questo errore è dovuto al fatto che il file stm32f30x.h richiama a sua volta il file "core_cm4.h" che
si trova però in un'altra cartella che dobbiamo indicare nel preprocessor.
Il file si trova in:
C:\..\STM32F3-Discovery_FW_V1.1.0\Libraries\CMSIS\Include
Aggiungendo anche questa nuova cartella al progetto l'errore viene quindi risolto.
Per fare in modo che il riferimento alla cartella di progetto non venga perso, nel caso in cui si
decidesse di eseguire il progetto su un altro PC, selezioniamo sostituiamo il percorso cliccando
sull'iconcina a fianco del percorso scelto.
Come passo successivo dobbiamo selezionare il Debugger, selezioniamo quindi la categoria
Debugger. Se disponiamo della scheda selezioniamo il Debbuger ST-LINK dal menu Driver in
Setup.
18
Una volta selezionato ST-LINK sempre nella categoria Debugger selezioniamo Dowunload e
spuntiamo l'opzione Use flash loader.
19
Infine nella Categoria ST-LINK spuntiamo l'opzione SWD, e premiamo OK per salvare le opzioni
impostate.
20
Capitolo 2: STM32 ADC
Analog to Digital Converter (ADC), in italiano convertitore analogico-digitale, è un circuito
elettronico in grado di convertire un segnale analogico con andamento continuo (ad es. una
tensione) in una serie di valori discreti.
La risoluzione di un ADC indica il numero di valori discreti che può produrre. È usualmente
espressa in Bit. Per esempio, un ADC che codifica un ingresso analogico in 256 livelli discreti ha
una risoluzione di 8 bit, essendo 28 = 256. La risoluzione può anche essere definita elettricamente,
ed espressa in volt. La risoluzione in volt di un ADC è uguale alla minima differenza di potenziale
tra due segnali che vengono codificati con due livelli distinti adiacenti.
L’STM32 offre fino a 4 convertitori digitali.
L’ADC ha un alimentazione indipendente che può essere compresa tra 2.4V e 3.6V, il riferimento è
collegato internamente all’ADC o può essere collegato tramite un pin dedicato.
Entrambi gli ADC offrono una risoluzione di 12-bit e un tasso di conversione di 1MHz con fino a
18 canali multiplex, 16 dei quali sono messi a disposizione per misurare segnali esterni.
Dei restanti due, uno è collegato ad un sensore di temperatura interno e il secondo è collegato ad
una tensione di riferimento interna.
L’ ADC nell’STM32 usa il SAR (successive approximation register), per cui la conversione avviene
in più fasi.
Il numero delle fasi è uguale al numero di bit del convertitore ADC, ogni passo è guidato dal clock
dell’ADC.
21
2.1 Configurazione convertitore A/D
Nel microcontrollore sono disponibili 4 convertitori AD di tipo SAR da 12 bit, suddivisi in 2
gruppi, ognuno composto da 2 convertitori uno dei quali può funzionare da master e l’altro da slave;
questo ci permette di poter raddoppiare la frequenza di campionamento agganciando le due
conversioni.
Gruppo 1
Gruppo 2
ADC1
Master
ADC2
Slave
ADC3
Master
ADC4
Slave
Per quanto concerne le connessioni, bisogna in primo step considerare che ciascun convertitore può
essere connesso ad un certo numero di canali interni ed esterni, in particolare ADC1 dispone di 14
canali in totale a cui può essere collegato; 10 canali esterni e 4 canali interni. Questi canali,
selezionati uno alla volta mediante un multiplexer, arrivano al Sample&Hold e quindi all'ingresso
dell'ADC1 (p.201 ADCs main features)
2.1.1 Abilitazione dell’ADC nella periferica RCC
Da RCC register map (p.132 del Reference Manual) troviamo che il bit per abilitare l'ADC si
trovano nel RCC_AHBENR. In questo caso notiamo che c'è un unico bit ADC12 per abilitare la
coppia ADC1 e ADC2 e un altro bit ADC34 per abilitare la coppia ADC3 e ADC4. Infatti gli ADC
22
non possono essere abilitati singolarmente. Se si abilita ADC1 si abiliterà anche ADC2, lo stesso
discorso vale per gli altri due.
2.1.2 Scelta del clock dell’ADC
Il Clock dell'ADC è comune ad entrambi gli ADC, ADC1 e ADC2. IL Clock può essere derivato
dal clock del bus AHB, dividendo questo clock per un fattore 1,2 o 4. Il fattore di divisione è fissato
dai bit CKMODE[1:0] del registro ADC12_CCR (ADC_Common Control Register).
Abbiamo scelto di impostare il clock dell'ADC pari a quello derivato dell'AHB e del "SysTick",
clock di sistema che è pari a 72 MHz. Dobbiamo quindi scegliere come fattore di scala il valore 1.
Per selezionare questo fattore di scala dobbiamo impostare i bit di CKMODE[1:0]='01'.
23
2.1.3 Configurazione del Regolatore di tensione
La conversione avviene confrontando il segnale di ingresso con una tensione di riferimento pari alla
tensione di alimentazione. La tensione è fornita da un regolatore di tensione. Per abilitare il
regolatore occorre eseguire una procedura di abilitazione e attendere 10 μs prima di abilitare l'ADC
(ADEN=1) oppure eseguire un'operazione di calibrazione.
Per poter abilitare il regolatore di tensione allora nell'ADC1_CR occorre portare i bit
ADVREGEN[1:0] dallo stato di reset '10' allo stato '00' e quindi allo stato di abilitazione '01'. I bit
che ci interessano e sui quali agire sono il bit 28 e il bit 29.
2.1.4 Scelta del canale di acquisizione dell’ADC
Per vedere come sono realizzate le connessioni fisicamente tra ADC e PIN, si fa riferimento al Data
Sheet Manual, Pinouts and pin description in cui troviamo l’elenco dei pin di out della board:
scorrendo l’elenco notiamo che PA0 è connesso al canale 1 (ADC1_IN1) di ADC1 come emerge nel
Additional Functions. Quindi per acquisire la tensione su PA0 bisogna andare a convertire il canale
1 di ADC1, invece per acquisire la tensione su PA1 bisogna convertire il canale 2 di ADC1 e così
via per gli altri PIN
24
2.1.5 Configurazione della modalità di campionamento Single-ended o differenziale
Il Convertitore ha 2 ingressi potendo funzionare sia in modalità single-ended che in modalità
differenziale. In modalità single-ended la conversione avviene rispetto ad una tensione di
riferimento fissata una volta per tutte in fase di configurazione. In modalità differenziale come
differenza di due tensioni poste in ingresso al convertitore. Scegliamo la modalità single-ended dal
momento che la tensione che vogliamo misurare varia tra [0
] V ed è solo uno dei due ingressi
che può variare. La tensione di riferimento in modalità single-ended è 0 V.
Quindi avremo a disposizione un convertitore AD a 12 bit ad approssimazioni successive (SAR), in
modalità single-ended, in configurazione Master che effettua una quantizzazione silenziata
uniforme. Infatti la soluzione adottata è tale che il numero di livelli di restituzione del convertitore a
12 bit sarà pari
-1= 4095, in modo da avere una quantizzazione uniforme silenziata e fondo scala
3 V. In questo modo otteniamo un quanto di circa Q=
25
= 0,0007326 V.
Per il canale 1 bisogna quindi dire se l'acquisizione avviene in modalità single-ended o
differenziale. Questo avviene scrivendo i bit DIFSEL[15:0] del registro ADC_DIFSEL. Questa
operazione deve essere effettuata quando il convertitore è disabilitato (ADEN=0).
Poichè per selezionare la modalità single-ended per il canale 1 dovremmo scrivere 0 nel bit di posto
1, e questo bit al reset è proprio 0, potremmo anche non mettere questa istruzione.
2.1.6 Auto-Calibrazione
Dopo questa prima fase di inizializzazione del convertitore, si procede con la fase successiva di
auto-calibrazione dell’AD, procedura che deve avvenire con il convertitore ancora in modalità off
cioè bit ADEN settato a 0.
Nel caso single-ended dobbiamo porre il bit ADCALDIF (modalità single-ended) del registro
ADC1_CR pari a 0. Se avessimo voluto eseguire la procedura di calibrazione per la modalità di
acquisizione differenziale allora avremmo dovuto settare ADCALDIF=1. Quindi la procedura di
auto-calibrazione ha inizio ponendo il bit ADCAL=1 e dobbiamo aspettare fino a quando
ADCAL=0 che indica che la calibrazione è terminata.
26
2.1.7 Abilitazione dell’ADC
A questo punto dobbiamo abilitare la periferica ADC portando al valore logico alto il bit ADEN del
registro ADC1_CR. Tuttavia la periferica sarà pronta per poter lavorare soltanto quando il bit
ADRDY del registro ADC_ISR sarà diventato 1. Pertanto dopo aver alzato il bit ADEN rimaniamo
in attesa della condizione ADRDY==1 mediante un ciclo while.
27
2.1.8 Impostazione dei Time Sampling
Terminate queste operazioni resta ancora da fissare il Tempo di Sample (Tempo di campionamento
che equivale al tempo di chiusura dell'interruttore del circuito di Sample&Hold). Questo tempo
dipende dalla dinamica del segnale di ingresso ( ) ed è il tempo che occorre per portare la tensione
sulla capacità di Hold ( ) ad una tensione parti a quella dell'ingresso ( ). In questo tempo la
tensione di uscita insegue la tensione di ingresso.
Ciascun canale del convertitore può essere campionato con un tempo di campionamento differente,
programmabile settando i bit SMP[2:0] dei registri ADC_SMPR1 e ADC_SMPR2.
E' pertanto possibile selezionare i seguenti valori:
Dato che il convertitore è a 12 bit di tipo SAR il tempo totale di conversione sarà:
TCONV = Tempo di campionamento + 12,5 ADC Clock cycles
28
2.1.9 Impostazione della sequenza di campionamento
Come ultima operazione di configurazione dobbiamo impostare la sequenza di campionamento.
Infatti è possibile organizzare la conversione in un gruppo, dove il gruppo è costituito da una
sequenza di conversioni che può essere fatta su alcuni canali. Quindi nei bit SQ1[4:0] del registro
ADC1_SQR1 scriviamo il numero del primo canale da cui acquisire, in SQ2[4:0] il numero del
secondo e così via, fino all'ultimo canale della sequenza SQ16[4:0] del registro ADC1_SQR1.
Quindi ciascuna sequenza può essere costituita da un minimo di 1 ad un massimo di 16 conversioni.
L'ordine dei canali da cui acquisire può essere qualsiasi. Ciascun canale può essere convertito più
volte nella stessa sequenza. La lunghezza della sequenza è invece fissata dai bit L[3:0].
A questo punto la conversione di una sequenza può iniziare dando un Segnale di Start of
Convertion. Il segnale di Start of Convertion viene dato all'ADC portando ad 1 il bit ADSTART del
registro ADC1_CR. Il convertitore avvisa che la singola conversione è terminata alzando il flag di
EOC (End of Convertion) e che la conversione della sequenza è terminata alzando il flag EOS (End
of Sequence). Una volta che la sequenza di conversione è terminata il bit ADCSTART ritorna a 0
inibendo l'inizio di una nuova conversione. I flag EOC ed EOS vengono riportati a 0 via software.
Tuttavia il flag EOC ritorna a 0 non appena leggiamo il dato acquisito dal Data Register
(ADC1_DR). Nel diagramma temporale seguente è riportata la sequenza delle operazioni. Per
iniziare una nuova conversione dobbiamo rialzare il bit ADSTART. Questa modalità di
campionamento è detta NON CONTINUA. Ogni volta infatti per avviare la conversione di una
sequenza dobbiamo dare il segnale di Start of Convertion. Esiste un'altra modalità questa volta
CONTINUA nella quale il segnale di Start of Convertion deve essere dato soltanto all'inizio. La
conversione della sequenza procede poi ciclicamente fino a quando non si alza via software il flag
ADSTOP del registro ADC_CR. A questo punto anche il flag ADSTART viene riportato a 0
dall'hardware e la conversione ciclica si interrompe. Per impostare un'acquisizione continua della
sequenza dobbiamo settare il flag CONT del registro ADC1_CFGR al valore logico alto.
Al termine della conversione il DATA REGISTER contiene il valore convertito e acquisito su PA0.
Per poter leggere questo valore dobbiamo convertirlo in tensione. Effettuiamo quindi un’operazione
di casting trasformando il dato in tipo float. Il valore è quindi ottenuto moltiplicando il dato per il
quanto del convertitore Q=3/4095. Mediante una funzione printf possiamo quindi visualizzare il
dato acquisito nel Terminal I/O dell'ambiente di sviluppo.
29
2.1.10 Esempio codice ADC
30
2.2 Acquisizione temperatura
In questo paragrafo misureremo la temperatura grazie al sensore di temperatura connesso
internamente al canale ADC1_16, il quale converte in digitale l’uscita del sensore di temperatura.
Il periodo di campionamento del sensore di temperatura deve essere maggiore di 2.2µs, come
possiamo
leggere
nel
paragrafo
12.9
del
Reference
Manual.
Quindi come prima cosa dobbiamo configurare l’ADC come nel paragrafo precedente apportando
qualche correzione.
Impostiamo il canale di acquisizione sul canale 16 modificando il registro ADC1_SQR1 e
inseriamo il valore 16 all’interno della prima sequenza. Pertanto alzeremo il quarto bit di SQ1
(24=16).
Settiamo il Time Sampling tale che sia maggiore di 2.2µs, settando il clock dell’ADC pari a quello
di sistema (72 MHz), ci basta scegliere il periodo di campionamento paria a 181.5 ADC clock.
181.5/72*10-6 s ≈ 2.5µs
Dopo queste operazioni possiamo abilitare il sensore di temperature dal registro ADC1_CCR
alzando il bit TSEN, quest’operazione deve essere eseguita quando il bit ADEN è 0.
31
Successivamente possiamo prelevare il dato da ADC1_DR e applicare la seguente formula per il
calcolo della temperatura:
Temperatura (in °C) = {(V25 – VTS) / Avg_Slope} + 25
Dove VTS è la tensione misurata dal sensore di temperature, V25 e Avg_Slope sono dei parametri
caratteristici che troviamo nel DataSheet.
2.2.1 Codice ADC sensore di temperatura
32
2.3 Acquisizione Temperatura (Hardware Trigger)
La conversione Analogico-Digitale può essere effettuata dall'ADC via software oppure controllata
mediante un hardware trigger proveniente dall'esterno della periferica. Sull'ADC sono disponibili
16 external triggers.
Se è selezionata questa modalità non dovremo più avviare la conversione via software ma una volta
alzato il bit ADSTART questa sarà avviata una sola volta (CONT=0) oppure ciclicamente
(CONT=1). Attraverso un multiplexer controllato dai bit EXTSEL[3:0] del registro CFGR
dell'ADC selezioniamo l'evento di trigger desiderato. I possibili eventi di trigger per esempio per
l'ADC1 e l'ADC2 sono riportati nella tabella 35 del Reference Manual.
33
L'evento esterno fissa di fatto la frequenza di campionamento dell'ADC nel caso in cui il bit
CONT=0. Configuriamo il Timer2 per generare un Update Event ogni secondo e dare il via ad una
conversione della temperatura. Per dire quindi all'ADC che la conversione inizia all'arrivo
dell'Event Update generato dal Timer2 dobbiamo settare i bit EXTSEL[3:0] del registro CFGR con
la sequenza di bit '1011', così come evidenziato in tabella. Affinchè l'evento sia rilevato dall'ADC
dobbiamo configurare anche i bit EXTEN[1:0] del registro CFGR. Se selezioniamo la sequenza '00'
allora l'ADC ignora il trigger esterno, se selezioniamo '01' si accorge della transizione 0->1(salita)
del trigger, '10' della transizione 1->0 (discesa), '11' di entrambe.
Per settare i Timer 2 dobbiamo conoscere la frequenza con cui lavora, dato che si trova sul bus
APB1 il TIM2 lavora ad una frequenza di 36MHz quindi dobbiamo settare il registro TIM2 autoreload a 36 000 000. Non approfondiamo di più la configurazione del Timer perché non è oggetto di
questa tesi.
2.3.1 Codice acquisizione temperatura (Hardware Trigger)
34
35
2.4 Calcolo valore medio della tensione con utilizzo del DMA
In questo paragrafo vedremo come utilizzare la periferica DMA (Direct Memory Access) per
gestire automaticamente la Look-Up Table (LUT) senza l'utilizzo di un contatore e operando
direttamente in hardware. Sul microcontrollore sono presenti 2 periferiche DMA che in totale
possono gestire 12 richieste di servizio provenienti da altrettante periferiche per trasferire
velocemente dati dalle periferiche alla memoria e viceversa. In questo modo possiamo realizzare dei
trasferimenti di dati dalla memoria alla periferiche o dalle periferiche alla memoria rapidamente e
senza impiegare risorse della CPU, che può realizzare altre operazioni mentre avvengono questi
trasferimenti. Il DMA deve conoscere l'indirizzo del registro della periferica al/dal quale
trasferire/prelevare il dato, l'indirizzo della prima locazione di memoria in cui inserire/prelevare il
dato, la dimensione dell'array in memoria.
Su ciascun canale del DMA soltanto una richiesta alla volta, proveniente dalle periferiche
(TIMx(x=1...4, 6, 7, 15..17), ADC1 , SPI1, SPI2/I2S2, I2Cx(x=1,2), DAC_Channel[1,2], e
USARTx (x=1..3)), può essere abilitata. Le richieste verso il DMA possono essere
indipendentemente attivate o disattivate programmando il DMA control bit nel corrispondente
registro della periferica.
La tabella 26 del Reference Manual riassume le richieste disponibili per ciascun canale del DMA1.
Dato che noi vogliamo trasferire le acquisizioni effettuate dall’ADC1 in un area di memoria,
osserviamo che questa richiesta arriva sul canale 1 del DMA1.
Come nel capitolo precedente non ci soffermeremo sulla configurazione del DMA, vedremo solo
come configurare l’ADC.
36
Per abilitare la collaborazione dell’ADC con il DMA, andiamo nel registro ADC_CFGR e settiamo
i bit DMAEN e DMACFG.
Il resto della configurazione è uguale a quella dell’esempio precedente, tranne per le interruzioni
esterne dato che in questo caso non useremo il TIMER2 come fonte di interruzione.
2.4.1 Codice calcolo valore medio
37
38
Capitolo 3: Gestione delle interruzioni
L’unità delle interruzioni ha 19 linee di interruzione le quali sono connesse al vettore delle
interruzioni attraverso NVIC. Sedici di queste linee sono connesse ai pin GPIO e possono generare
interruzioni sul fronte di salita, di discesa o entrambi.
Le restanti 3 linee sono connesse a RTC allarm interrupt, USB wake up e all’unita di rilevamento
alimentazione.
NVIC fornisce vettori di interruzioni individuali per le linee EXTI 0-4, l’allarme RTC, USB wake
up e all’unita di rilevamento alimentazione. Le restanti linee EXTI sono collegate in gruppi di linee
5-9 e 10-15. EXTI e importante per il controllo dell’alimentazione su STM32.
Le 16 linee EXTI dedicate ai pin GPIO possono essere associate a qualsiasi combinazione di pin
della porta, questo è realizzato attraverso quattro registri di configurazione. In questi registri ad ogni
campo EXTI si associano 4 bit, questo campo permette ad ogni linea EXTI di essere mappata su
una delle 5 porte.
3.1 Nested Vectored Interrupt Controller (NVIC)
Il dispositivo STM32F3 incorpora un Nested Vectored Interrupt Controller in grado di gestire fino a
66 canali di interruzione mascherabili e 16 livelli di priorità.
I vantaggi del NVIC sono:

Bassa latenza delle interruzioni

L’indirizzo del Interrupt entry vector table è passato direttamente al core

Trattamento precoce delle interruzioni

Stato del processore salvato automaticamente
39
NVIC e l’interfaccia del core sono strettamente accoppiati, questo accoppiamento stretto
consente al processo di interruzione di avere una bassa latenza e di trattare efficientemente le
interruzioni in ritardo.
Questa bassa latenza viene realizata grazie all’utilizzo di uno stack, il processore all’ingresso di
un interruzione salva automaticamente nello stack il suo stato e rimuove lo stato dallo stack
quando l’interruzione termina.
L’implementazione hardware dei registri NVIC la troviamo a p.193 del Program Manual:
3.2 Extended interrupts and events controller (EXTI)
L’ EXTI gestisce le interruzioni asincrone esterne ed interne, genera una richiesta di evento alle
CPU/Interrupt Controller e una richiesta di risveglio al Power Manager.
EXTI gestisce 28 linee di eventi esterni e 8 linee di eventi interni. Il fronte di attivazione di ogni
linea esterna può essere scelto indipendentemente, mentre per le interruzioni interne la scelta del
fronte è limitata a quello di salita.
Un interruzione potrebbe essere messa in attesa, la gestione in questo caso e diversa a seconda se
l’interruzione sia esterna o interna. Nel caso di un interruzione esterna, viene istanziato un registro
che indica la fonte dell’interruzione, quando l’interruzione è interna lo stato sospeso è garantito
dalla periferica, quindi non è necessario un flag specifico.
40
41
Conclusioni
In conclusione abbiamo visto come si sono evoluti i microcontrollori, partendo dal primo computeron-chip di Intel uscito nel 1975 fino ad arrivare all’STM32.
Quest’ultimo microcontrollore ha avuto un enorme successo, successo dovuto alle sue performance
elevate e al suo basso costo. Oggi del microcontrollore ne viene fatto un uso massiccio in svariati
campi industriali, dall’automotive agli elettrodomestici, questo ci fa capire come il microcontrollore
sia un oggetto fondamentale e quindi bisogna adattarlo ai più svariati settori. Come abbiamo
constatato nel caso dell’STM32, questa specifica famiglia di board sono facilmente programmabili,
la facilita di programmabilità, non solo di questa specifica board, fa si che questi component siano
usati dentro e fuori le nostre case automatizzando processi delicati che hanno bisogno di un elevata
precisione. Siamo circondati da microcontrollori nella vita quotidiana senza che ce ne rendiamo
conto.
42
Bibliografia
[1] STMicroelectronics, RM0316 Reference Manual
[2] STMicroelectonics, UM1570 User Manual
[3] STMicroelectronics, STM32F302xx/STM32F303xx Datasheet
[4] STMicroelectronics, PM0214 Program Manual
[5] Hitex Development Tools, The Insider’s Guide To The STM32 ARM® Based
Microcontroller
43
Scarica

Elaborato Bossa Aniello N46-1174