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: Protocollo SPI e comunicazione con sensore Anno Accademico 2014/2015 Candidato: Antonio Pagano matr. N46001239 “ Alla nonna Lucia e alla zia Carolina, le quali hanno sempre creduto nelle mie capacità ” Indice Indice .................................................................................................................................................. III Introduzione ......................................................................................................................................... 4 Capitolo 1: Serial Peripheral Interface (SPI) ....................................................................................... 5 1.1 Interfaccia................................................................................................................................... 6 1.2 Configurazione master-slave...................................................................................................... 7 1.3 Struttura interna.......................................................................................................................... 8 1.4 Comunicazione sul bus ............................................................................................................ 10 1.5 Modalità Half-duplex ................................................................................................................... 12 Capitolo 2: SPI (STM32F4xx) ........................................................................................................... 13 2.1 Caratteristiche principali .......................................................................................................... 13 2.2 Registri SPI .............................................................................................................................. 15 2.3 Gestione della trasmissione e della ricezione .............................................................................. 22 Capitolo 3: Comunicazione con il sensore (il Giroscopio) ................................................................ 23 3.1 Attivazione PIN e settaggio della modalità.............................................................................. 24 3.2 Trasmissione tra SPI1 e sensore di Giroscopio ........................................................................ 25 Capitolo 4: Esempio di utilizzo del protocollo SPI e comunicazione con il sensore sul microcontrollore STM32F4xx ........................................................................................................... 27 Bibliografia ........................................................................................................................................ 33 III Introduzione L’utilizzo di microcontrollori è sempre più consistente nella società moderna. Tale successo lo si deve principalmente all’enorme utilizzo che tale componente prevede in molti dispositivi, anche di uso comune, come ad esempio una lavatrice o un caricabatterie. I microcontrollori della famiglia STM32 sono tra i più diffusi e utilizzati sul mercato. Tali dispositivi sono prodotti dalla STMicroelectronics, una società franco-italiana, tra i più grandi produttori di componenti elettronici al mondo. In questo elaborato verrà adoperato proprio un microcontrollore STM32 per studiare e mostrare l’utilizzo di uno dei principali protocolli di comunicazione tra dispositivi: il protocollo Serial Peripheral Interface (SPI). In particolare, la trattazione sarà suddivisa in livelli: si mostreranno le caratteristiche tecniche e teoriche riguardanti il protocollo SPI, per giungere successivamente alla sua applicazione nei microcontrollori STM32. In particolar modo sarà poi mostrata come effettuare la comunicazione tra il microcontrollore e il sensore interno di giroscopio digitale. Viene infine fornito il codice sorgente da caricare sul microcontrollore che consente di ottenere i valori degli assi di rotazione x, y e z. 4 Capitolo 1: Serial Peripherl Interface (SPI) SPI (Serial Peripheral Interface) è un bus di comunicazione seriale sincrono sviluppato da Motorola e utilizzato per comunicazioni tra dispositivi a brevi distanze: tra un microcontrollore e altri circuiti integrati tra più microcontrollori. La trasmissione avviene tra un dispositivo detto master e uno o più slave (letteralmente dall’inglese padrone e schiavo). Il master controlla il bus, cioè ne prende possesso così da evitare che altri dispositivi possano utilizzarlo mentre questo è occupato. Di seguito, emette il segnale di clock e decide quando iniziare e terminare la comunicazione, inviando frames di scrittura/lettura al dispositivo slave. Il protocollo SPI prevede un’architettura single-master multi-slave. Per quanto riguarda la velocità di scambio dei dati, essa dipende fortemente dalla scelta della frequenza di clock, cioè dal numero di impulsi che il segnale di clock genera in un secondo. Ad ogni impulso generato, si effettua la trasmissione di un bit. Risulta evidente quindi che tanto più questi impulsi sono frequenti, tanto più velocemente sarà passato il dato. La frequenza di clock viene settata dal dispositivo master. Non vi è un limite di velocità minimo, in quanto i dispositivi sono statici: se alimentati possono mantenere uno stato logico per un tempo indefinito. Vi è tuttavia un limite massimo che va determinato dai datasheet [1] dei singoli dispositivi connessi. Il bus SPI di definisce full-duplex in quanto il “colloquio” può avvenire contemporaneamente sia in trasmissione che in ricezione. 1 Documentazione che riassume le caratteristiche di un componente, un apparato, un software o anche un composto chimico. Di solito si presenta in formato PDF. 5 1.1 Interfaccia Il generico dispositivo SPI prevede 4 canali: SCLK (SCK): Serial Clock; MOSI: Master Output Slave Input; MISO: Master Input Slave Output; CS (SS): Chip Select (Slave Select); Essendo a 4 canali, il sistema è genericamente detto a 4 fili. Va però tenuto conto che deve esserci una connessione di riferimento (Vref) e che quindi fisicamente i fili sono cinque. Figura 1.1 Nel dettaglio: SCLK (SCK) è il canale del clock, il quale scandisce gli istanti in cui master e slave possono trasmettere e ricevere i bit sul bus. Tale canale è gestito dal master, il quale dunque richiede la trasmissione, di volta in volta, di una “parola”; MOSI è il canale adoperato per trasmettere il dato dal dispositivo master a quello slave; MISO è il canale adoperato per trasmettere il dato dal dispositivo slave a quello master; CS (SS) è il canale attraverso cui il master sceglie con quale dispositivo slave comunicare. Per abilitare la comunicazione è necessario settare il pin SS ad un livello logico basso (come si nota dalla Figura 1.1, il pin SS è negato, dunque nel caso sia settato al livello logico alto esso diventa di livello logico basso, disabilitando la comunicazione). 6 1.2 Configurazioni master-slave Si mostrano di seguito due configurazioni possibili per il collegamento tra master e slave: Dispositivi slave controllati singolarmente Ogni dispositivo slave è collegato ad un pin con il segnale SS del dispositivo master. Il dispositivo master dovrà avere un numero di pin SS pari al numero dispositivi slaves Dunque abilitando di collegati. un determinato pin SSi, verrà attivato lo slave corrispondente a tale pin. Figura 1.2 In definitiva ogni slave si collega al dispositivo master indipendentemente dagli altri slaves. Il numero di dispositivi slaves che si possono connettere al bus è limitato esclusivamente dal numero massimo di linee gestibili dal master. Il vantaggio di tale soluzione è la velocità di comunicazione tra il master e i singoli slave. Di contro, lo svantaggio è l’eccessivo numero di pin SS richiesti per tale architettura. 7 Dispositivi slaves connessi in catena (daisy chain) Il dispositivo master possiede un unico pin SS in uscita ed il segnale che esso pilota è inviato a tutti i dispositivi slave sui relativi pin SS. I dispositivi slave vengono quindi attivati tutti contemporaneamente, ma lavorano in catena: il dispositivo master invia il dato effettivamente solo al primo dispositivo slave, attraverso il canale MOSI. Figura 1.3 Successivamente, i dispositivi slave comunicano tra loro in cascata, utilizzando i canali MISO e MOSI: lo slave i-1 invia il dato attraverso il suo canale MISO, mentre lo slave i riceve il dato sul suo canale MOSI. Tale catena si ripete fino all’ultimo slave, il quale avrà il proprio canale MISO collegato a quello del master. Il vantaggio di tale soluzione è l’abolizione di un numero elevato di pin SS a favore di un unico pin SS che gestisce tutti gli slave. Di contro lo svantaggio è la minore velocità di aggiornamento dei singoli slaves. 1.3 Struttura interna Figura 1.4 Ogni dispositivo SPI possiede un registro a scorrimento utilizzato per inviare e ricevere i dati serializzati. Un registro a scorrimento è un componente molto utilizzato in elettronica 8 digitale: esso è costituito da una serie di flip-flop[2] di tipo D, collegati tra loro in modo tale che l’uscita del precedente sia l’ingresso del successivo. Un flip-flop di tipo D è dotato di un ingresso per il dato (D), di un ingresso per la sincronizzazione (clock) e di un’uscita (Q). Quando riceve il segnale di clock, trasferisce l’ingresso in uscita e lo mantiene finché non cambia l’ingresso. Nella sua versione più semplice il registro a scorrimento ha il seguente funzionamento: ad ogni colpo di clock, ogni flip-flop passa il proprio valore al successivo ed il primo flipflop della catena assume il valore del segnale di ingresso al registro. Il valore precedentemente memorizzato nell'ultimo flip-flop viene assegnato al segnale di uscita del registro a scorrimento. Lo scorrimento può avvenire dal bit più significativo verso quello meno significativo, o viceversa. In SPI, usualmente tale registro ha una dimensione di 8 bit, ma in generale potrebbe avere dimensione arbitraria, a patto che siano di uguali dimensioni il registro del dispositivo master e quello slave. Se si suppone un trasferimento da parte del master verso lo slave, il dato contenuto nell'ultimo flip-flop verrà trasmesso sul canale MOSI. Nel dispositivo slave, a sua volta, il canale MOSI sarà collegato al primo flip-flop del suo registro a scorrimento. I dati avanzano nei due registri a scorrimento utilizzando la sincronizzazione del segnale SCLK inviato dal dispositivo master. L'ultimo flip-flop del registro a scorrimento del dispositivo slave, a sua volta, è collegato al segnale in uscita MISO. I dati pervenuti nel dispositivo master e provenienti dal dispositivo slave, sul segnale MISO, saranno caricati a loro volta nel primo flip-flop del registro a scorrimento del master. L'architettura interna composta dai registri a scorrimento, unita alla configurazione delle interconnessioni dei segnali MISO e MOSI, consentono di realizzare un anello chiuso. 2 Circuito elettronico sequenziale utilizzato in elettronica digitale come cella di memoria elementare 9 Proprio tale architettura ad anello permette ai dispositivi SPI di effettuare una comunicazione di tipo full-duplex. Nei dispositivi commerciali è possibile configurare la direzione dei dati trasmessi dal registro a scorrimento: in un caso si ha che il primo bit ad essere trasmesso è quello più significativo, viceversa si ha quello meno significativo. 1.4 Comunicazione sul bus La comunicazione tra master e slave avviene seguendo nell’ordine le seguenti operazioni: 1. Il dispositivo master, nel caso in cui il dispositivo slave sia controllato singolarmente, seleziona lo slave con cui comunicare settando il segnale SS corrispondente al livello logico basso (logica 0-Attiva). Nel caso di un’architettura di tipo slaves in catena, il master setta il suo unico segnale SS al livello logico basso; 2. Il master invia il segnale di clock, configurandolo ad una frequenza tale che tutti i dispositivi possano supportarlo; 3. Ad ogni ciclo di clock avviene la comunicazione: il master invia il primo bit del dato attraverso il canale MOSI, insieme al segnale di clock; 4. Il dispositivo slave riceverà il segnale di clock e il primo bit sul canale MOSI, interpretandolo come l’inizio della comunicazione. In contemporanea invierà un altro dato sul canale MISO. Notiamo come la comunicazione tra i due dispositivi sia effettivamente seriale, in quanto sia sul canale MISO che su quello MOSI sarà trasmesso un solo bit alla volta. Tuttavia, i dispositivi compiono effettivamente un tipo di comunicazione in parallelo, in quanto verranno passati due bit in contemporanea: uno sul canale MOSI, uno sul canale MISO. Questo implica che ogni dispositivo invierà il suo bit più significativo (o meno significativo in base alla direzione dello scorrimento del registro) e riceverà in contemporanea un bit che verrà posto come bit meno significativo (o più significativo) sul registro. 10 Si è detto che il dispositivo master setta la frequenza del segnale di clock. Esso deve inoltre configurare la sua polarità, ovvero il valore logico su cui si porta il segnale di clock quando questo è inattivo, e la sua fase, ovvero il fronte di clock in cui il ricevente campiona il segnale in ingresso. Tali attributi sono settabili attraverso due parametri: CPOL per la polarità, CPHA per la fase. Le possibili combinazioni sono le seguenti: 1. CPOL = 0, CPHA = 0: Il dato è catturato sul fronte di salita e propagato sul fronte di discesa del clock 2. CPOL = 0, CPHA = 1: Il dato è catturato sul fronte di discesa e propagato sul fronte di salita del clock 3. CPOL = 1, CPHA = 0: Il dato è catturato sul fronte di discesa e propagato sul fronte di salita del clock 4. CPOL = 1, CPHA = 1: Il dato è catturato sul fronte di salita e propagato sul fronte di discesa del clock Figura 1.5 11 1.5 Modalità Half-duplex Come si è detto, il protocollo SPI implementa implicitamente la modalità full-duplex. Tuttavia alcune implementazioni dei dispositivi supportano la modalità half-duplex: il dispositivo master e il dispositivo slave comunicano tra loro su un unico canale detto SISO (Slave input Slave output), il quale può essere bidirezionale in presenza di un dispositivo slave che trasmette dati verso il master oppure no. 12 Capitolo 2: SPI (STM32F4xx) I SoC[3] della famiglia STM32F4xx, prodotti da ST Microelectronics, supportano e implementano il bus SPI. Essi posseggono 3 periferiche per l’utilizzo di SPI: SPI1, SPI2, SPI3. Il dispositivo indicato con SPI1 è connesso al bus APB2 a 84MHz, mentre gli altri due (SPI2 e SPI3) sono connessi al bus APB1 a 42MHz. Tramite l’interfaccia di tali dispositivi è possibile la trasmissione seriale sincrona dei dati verso i dispositivi esterni al System-on-a-Chip. Oltre alla modalità full-duplex, è supportata anche la modalità halfduplex. 2.1 Caratteristiche principali Attraverso l’interfaccia SPI dei dispositivi forniti dalla famiglia STM32F4xx, è possibile settare le seguenti caratteristiche: Modalità full-duplex per la trasmissione dei dati utilizzando tre canali (SCK, MISO e MOSI); Modalità half-duplex per la trasmissione monodirezionale o bidirezionale su due canali; 3 Lunghezza delle frame di 8-bit o 16-bit; Modalità operative master o slave; 8 prescaler per la regolazione del baud rate (fPCLK/2 max); Selezione del dispositivo slave in hardware o software (NSS); Configurazione in software dei parametri CPOL e CPHA; System-on-a-chip (sistema su circuito integrato), è un circuito integrato in cui un solo chip contiene un intero sistema. 13 Configurazione in software della direzione di trasferimenti dei dati (prima il bit più significativo, o prima quello meno significativo); Flag nei registri di stati dedicati alle interruzioni; Generazione e controllo in hardware del CRC[4]; Controllo degli errori con flag e interruzioni (master mode fault, overrun e CRC). L'interfaccia possiede 4 canali principali: 1. MOSI: Linea dati per la trasmissione dei dati dal dispositivo master a quello slave; 2. MISO: Linea dati per la trasmissione dei dati dal dispositivo slave a quello master; 3. SCK: Serial clock inviato dal dispositivo master a quello slave; 4. NSS: Linea di controllo utilizzata per la selezione del dispositivo slave. La struttura di SPI su STM32F4xx è fornito dal seguente diagramma a blocchi: Figura 2.1 4 Cyclic redundancy check (controllo a ridondanza ciclica), metodo per il calcolo delle somme di controllo (checksum). Utilizzato per il controllo sulla trasmissione dei dati. 14 2.2 Registri SPI Nel seguito saranno mostrati come settare i registri del microcontrollore STM32F4xx riguardanti SPI, per configurare le varie caratteristiche. In particolare verranno utilizzati i seguenti registri: SPI_CR1 SPI_CR2 SPI_SR Selezione del dispositivo in modalità master o slave Il dispositivo seleziona la sua modalità di master o di slave attraverso la configurazione del bit MSTR del registro SPI_CR1. Settando tale bit al livello logico 1, il dispositivo opererà in modalità master; settato al livello logico 0, il dispositivo sarà configurato in modalità slave. Gestione della selezione dello slave (NSS) La selezione del dispositivo slave può avvenire sia in hardware che in software. Tale scelta si effettua configurando il bit SSM (Software Slave Management) nel registro SPI_CR1: se il bit viene settato al valore logico 1, la selezione dello slave è fatta in software, se settato a 0, la selezione è fatta in hardware. Se la selezione è fatta in software, il valore del bit SSI (Internal Slave Select) viene forzato sul pin NSS, ignorando il valore che quest’ultimo possedeva: in questo modo, dunque, il dispositivo (che opererà in modalità 15 slave) verrà selezionato in base alla configurazione software presente nel bit SSI. Ricordiamo che per essere attivo, lo slave deve avere livello logico basso su SS, per cui il bit SSI deve essere settato a 0 per attivarlo. Il valore del bit SSI viene ignorato nel caso in cui il bit SSM non sia stato settato. Se la selezione è fatta in hardware, invece, il pin NSS può essere configurato come input o output, a seconda che si tratti rispettivamente di un dispositivo slave o master. Se configurato come output (dunque per la modalità master), la periferica piloterà opportunamente questo segnale al livello logico basso (logica 0-attiva) quando è necessario selezionare il dispositivo slave a cui è collegato. A questo punto il dispositivo master è pronto per il trasferimento dei dati e il dispositivo slave agirà da tale, a valle della rilevazione del passaggio del livello logico alto -> basso del segnale NSS. Il segnale NSS dovrà essere al livello logico basso durante tutta la durata della trasmissione della frame. Configurazione baud rate E’ prevista la possibilità di selezionare 8 possibili configurazioni di baud rate attraverso l’interfaccia SPI. Tanto più alto sarà il baud rate, cioè la velocità con cui viaggiano i dati, tanto meno tempo sarà impiegato per la comunicazione. Il baud rate è definito come: fPCLK / 2 max dove fPCLK è la frequenza del segnale di clock (SCK), e max equivale a 2i, con i che varia nell’intervallo [1, 8]. Sono messi a disposizione 3 bit, corrispondenti a BR[2:0], del registro SPI_CR1 (i bit 3, 4 e 5), per selezionare il baud rate desiderato. Le possibili configurazioni sono: 16 Configurazione parametri CPOL e CPHA (clock polarity e clock phase) Al fine di determinare gli istanti temporali di propagazione e cattura del dato sui canali MISO e MOSI, è possibile configurare la polarità e la fase del clock dando luogo a quattro possibili modalità operative differenti, così come visto precedentemente. I due parametri CPOL e CPHA sono configurabili nel registro SPI_CR1, attraverso i bit CPOL e CPHA. Dal settaggio di tali bit, si determinano, dunque, se la lettura del dato deve avvenire sul fronte di salita o discesa e se il livello logico idle del segnale di clock deve essere quello basso oppure alto. Si noti inoltre che siccome il segnale SCK è mappato su un pin in uscita per il master (entrata nel caso dello slave) mediante GPIO, è necessario configurare una resistenza di pull-up nel caso in cui CPOL=1 o una resistenza di pull-down nel caso in cui CPOL=0. Il dispositivo master e quello slave devono configurare questi due parametri allo stesso modo. Lunghezza della frame e direzione L'interfaccia può lavorare con frame di dimensione differenti. È possibile configurare la lunghezza del frame (singola trasmissione) usando il bit DFF del registro SPI_CR1: se impostato a 0, la frame di trasmissione/ricezione sarà di 8-bit, viceversa di 16-bit. La direzione di trasferimento (prima il bit più significativo o prima quello meno significativo) è configurabile, invece, utilizzando il bit LSBFIRST nel registro SPI_CR1: se settato a 0 la trasmissione inizia dal bit più significativo, se settato a 1 dal bit meno significativo. Modalità half-duplex L’interfaccia SPI in STM32F4xx prevede la possibilità di utilizzare la modalità halfduplex. Con tale modalità è possibile utilizzare un unico canale per la trasmissione delle informazioni. Tale trasmissione può essere bidirezionale, cioè i dati possono essere 17 trasferiti dal master allo slave e viceversa, o monodirezionale, ovvero i dati possono essere trasferiti esclusivamente dal master allo slave. Nella modalità half-duplex, inoltre, i canali vengono ridotti da 4 a 3, in quanto si userà un unico canale per la trasmissione: il MOSI se si tratta del dispositivo master, il MISO se si tratta di quello slave. L’interfaccia sarà costituita allora dai canali SCK, MOSI/MISO, NSS. Si mostrano quindi i bit da configurare per la modalità half-duplex di tipo: Bidirezionale: si setta a 1 il bit BIDIMODE del registro SPI_CR1. Si può inoltre configurare la direzione del trasferimento attraverso il bit BIDIOE, sempre del registro SPI_CR1; se posto a 1, la direzione sarà di output per quella periferica (uscente), se posto a 0 sarà di input (entrante). Monodirezionale: si setta il bit BIDIMODE a 0. La direzione del trasferimento viene impostata dal bit RXONLY del registro SPI_CR1; se posto a 0, la trasmissione sarà dal master allo slave, se posto a 1, la trasmissione sarà di sola ricezione, quindi il master sarà in grado esclusivamente di ricevere i dati dallo slave. Si noti che, anche nel caso in cui il master sia in modalità di sola ricezione, lo slave, prima di cominciare la trasmissione, dovrà comunque attendere la selezione sul segnale NSS e rilevare il cambiamento di fronte sul segnale SCK. Data Register (DR) Il registro SPI_DR mantiene i dati ricevuti o da trasmettere durante la comunicazione attraverso SPI. Tale registro è suddiviso in due buffer: uno dedicato alla trasmissione, Trasmission buffer (Tx buffer), e uno dedicato alla ricezione, Receive buffer (Rx buffer). In caso di scrittura su SPI_DR, il dato sarà scritto sul Tx buffer; in caso di lettura su SPI_DR, sarà letto il dato tenuto sul Rx buffer. 18 Tale struttura è chiarita dal particolare dello schema a blocchi di figura 2.1: Figura 2.2 Si ricordi inoltre che SPI prevede la selezione di due formati diversi di frame: 8-bit o 16bit. Nel caso in cui la lunghezza della frame sia di 8-bit, i buffers saranno di soli 8-bit, corrispondenti agli 8 bit meno significativi del registro SPI_DR, e solo tali bit saranno utilizzati per la ricezione/trasmissione. Generazione e controllo del CRC Per garantire trasferimenti affidabili, l'interfaccia SPI nei SoC della famiglia STM32F4xx implementa in hardware il calcolo e la verifica del CRC. Il calcolo avviene serialmente su ogni bit, attraverso l’utilizzo di un polinomio di grado n1, dove n è il numero di bit della frame da verificare. E’ possibile settare il polinomio generatore del codice CRC nel registro SPI_CRCPR. Ricordiamo che le frames possono essere di 8 o 16 bit, dunque il polinomio sarà al massimo di grado 15. La generazione e il controllo del CRC è abilitata settando il bit CRCEN nel registro SPI_CR1. Durante una trasmissione, il codice CRC viene calcolato serialmente e riposto 19 nel registro SPI_TXCRCR. Quindi ad ogni bit trasmesso, si calcolerà il corrispettivo CRC, il quale verrà memorizzato nell’apposita locazione del registro SPI_TXCRCR. Quando si è in procinto di trasferire l'ultimo byte della sequenza dei dati, se i trasferimenti sono gestiti dalla CPU e non da un dispositivo DMA, il software dovrà settare il bit CRCNEXT sul registro SPI_CR1 e, in hardware, verrà caricato lo shift-register (registro a scorrimento) con il codice CRC calcolato fino ad allora e riposto nel registro SPI_TXCRCR. In questo modo, dunque, il codice CRC viene trasmesso come ultimo byte (se il formato della frame è su 8-bit) dopo aver trasmesso i dati. In maniera del tutto analoga avviene la fase di ricezione e controllo del CRC: alla ricezione dell'ultimo byte, se la ricezione è gestita dalla CPU e non da un dispositivo DMA, sarà necessario settare in software il bit CRCNEXT. Dopodiché l'hardware controllerà se il codice CRC ricevuto come ultimo byte è uguale a quello generato in ricezione e riposto nel registro SPI_RXCRCR. Eventuali errori scaturiti dal fallimento del controllo, ricezioni o trasferimenti errati del CRC verranno indicati dall'hardware attraverso il flag CRCERR del registro SPI_SR. Opzionalmente è possibile abilitare un'interruzione nel caso si manifestino errori settando il bit ERRIE nel registro SPI_CR2. 20 Interruzioni L'interfaccia SPI presenta sette eventi interrompenti, ognuno indicato da appositi flag del registro SPI_SR. Gli eventi interrompenti sono i seguenti: TXE: il buffer in trasmissione (Tx buffer) è stato svuotato ed è possibile caricare altri dati; RXNE: il buffer in ricezione (Rx buffer) è stato caricato con un nuovo dato e può essere letto; MODF: master mode fault event. Può accadere quando il dispositivo è impostato come master e il segnale NSS viene settato a 0 (in modalità di selezione dello slave in hardware) o quando il bit SSI è settato a 0 (in modalità di selezione dello slave in software); OVR: errore di overrun. Può accadere quando sono stati ricevuti nuovi dati e il flag RXNE è ancora alto, ovvero il buffer in ricezione non è stato ancora letto dal software mediante il registro SPI_DR; CRCERR: errore di controllo o ricezione/trasferimento errato del codice CRC; BSY: busy flag. Si verifica quando il bus SPI è occupato oppure se il buffer Tx (buffer di trasmissione) non è vuoto; FRE: frame format error. Errore scatenato da un formato di frame non supportato. Si noti che i bit UDR e CHSIDE del registro SPI_SR non sono utilizzati dal SPI. 21 2.3 Gestione della trasmissione e della ricezione Di seguito si mostrano gli eventi caratterizzanti la trasmissione e la ricezione attraverso SPI. Trasmissione: 1. Il dato è caricato (in parallelo) dal bus APB al Tx buffer interno; 2. Il bit più significativo del Tx buffer (o quello meno significativo) è posto sul segnale in uscita; 3. La trasmissione comincia appena il dispositivo slave ha ricevuto la variazione del segnale SCK; 4. I restanti 7 bits (se la frame è impostata su 8-bit) o 15 bits (se la frame è impostata su 16-bit) vengono caricati nello shift-register e inviati uno per volta sul segnale in uscita; 5. Quando i dati dal Tx buffer vengono caricati nello shift-register, viene settato il flag TXE nel registro SPI_SR ad indicare che il buffer è vuoto ed è possibile caricare altri bit nel buffer per la trasmissione successiva; 6. Opzionalmente, se settato il bit TXEIE nel registro SPI_CR2, verrà lanciata la relativa interruzione Ricezione: 1. Quando il trasferimento è completo, i dati vengono trasferiti dallo shift- register al Rx buffer; 2. Dopo l'ultimo bit ricevuto, viene settato il flag RXNE nel registro SPI_SR ad indicare che il buffer in ricezione non è vuoto; 3. Opzionalmente, se settato il bit RXNEIE nel registro SPI_CR2, verrà lanciata la relativa interruzione; 4. I dati ricevuti possono essere letti dalla periferica con un'operazione di lettura sul registro SPI_DR. Ciò provocherà, in hardware, il reset del flag RXNE. 22 Capitolo 3: Comunicazione con il sensore (il Giroscopio) Un giroscopio è un dispositivo che usa la gravità terrestre per determinare l’orientamento. Esso è costituito da un disco a forma toroidale, chiamato rotore, libero di ruotare intorno ad un asse di simmetria che lo attraversa centralmente e che termina con due punte che fungono da perni di rotazione. Tali perni sono inseriti in due fori presenti in un giunto cardanico[5]. Tramite un sistema di giunti cardanici, vengono collegati all’asse di rotazione 3 anelli metallici, disposti perpendicolarmente tra loro. Tali giunti permettono al giroscopio di effettuare qualsiasi movimento, mantenendo però fisso il baricentro. Il principio su cui si basa il funzionamento di un giroscopio è quello secondo il quale, in assenza di momenti di forze esterne, il vettore momento angolare[6] si conserva[7] e ciò comporta che l’orientamento nello spazio dell’asse di rotazione rimanga invariato. Tale comportamento prende nome di inerzia giroscopica. Se il dispositivo è messo in rapida rotazione con una cordicella, avvolta lungo l’asse di rotazione, si osserva che tale asse mantiene invariata la direzione per la notevole inerzia 5 Il giunto cardanico o giunto di Cardano è un quadrilatero articolato spaziale. Esso permette di trasmettere il moto tra due assi in rotazione i cui prolungamenti sono incidenti in un punto. 6 Grandezza di tipo vettoriale, legata alle rotazioni spaziali. 7 Principio fisico che afferma che il momento angolare è costante nel tempo se è nullo il momento delle forze esterne che agiscono su esso. 23 del giroscopio. Inoltre, se si sollecita un giroscopio in rotazione con una forza, il suo asse non si muove nella direzione della forza, ma tende a muoversi in una direzione ad essa perpendicolare. Per tali motivi, il giroscopio è utilizzato per misurare e mantenere l’orientamento. Applicazioni tecnologiche del giroscopio si riscontrano nelle bussole giroscopiche (girobussole) presenti a bordo di aerei o di navi, attraverso le quali si riescono a stabilizzare i mezzi sui quali si trovano quando questi cambiano direzione. Sono alla base inoltre dei modellini radiocomandati (ad esempio droni), in cui prevedono l’uso di un giroscopio montato nella ruota motrice, così da poter mantenere l’equilibrio. Inoltre è spesso presente negli smartphone, i quali sfruttano la sua capacità di captare ogni minimo movimento del dispositivo per svariate applicazioni (sicurezza, giochi, etc…). I microcontrollori della famiglia STM32F4xx, prevedono un sensore interno di giroscopio digitale, capace di fornire le misurazioni delle rotazioni rispetto all’asse x, y e z. La comunicazione tra il microcontrollore del SoC con tale sensore viene effettuata attraverso il protocollo SPI. 3.1 Attivazione PIN e settaggio della modalità Si è detto che i microcontrollori STM32F4xx prevedono 3 bus SPI: SPI1, SPI2, SPI3. Supponiamo da ora in poi di utilizzare SPI1. In generale SPI necessita la configurazione di 4 PIN, uno per ogni canale (SCK, MISO, MOSI, NSS). Nel caso specifico in cui la comunicazione deve avvenire tra il microcontrollore e il sensore di giroscopio, si setta come master il microcontrollore stesso, mentre si setta come slave il sensore. La comunicazione tra microcontrollore e sensore avverrà attraverso il PIN PE3, settato in modalità di output. Tale PIN fungerà da NSS: infatti settandolo a 0 si abiliterà la trasmissione (logica 0-attiva), settandolo a 1 si disabiliterà. Inoltre, è necessario settare i PIN di SPI1 così da avere un canale MISO, un canale MOSI e un canale SCK. 24 In particolare è necessario settare i PIN PA5, PA6, PA7 nella modalità alternativa AF05, così come mostrato nella seguente tabella: Figura 3.1 3.2 Trasmissione tra SPI1 e sensore di Giroscopio La trasmissione tra SPI1 e Giroscopio funziona nel seguente modo: 1- Abilito il canale di comunicazione attraverso il pin P3 per avviare la trasmissione; 2- SPI1 aspetta che possa mandare la richiesta. Invia quindi la richiesta del registro del Giroscopio da cui vuole ricevere i dati; 3- Il giroscopio invia un messaggio di conferma; 4- SPI1 riceve tale messaggio e risponde con un altro messaggio di conferma; 5- Il giroscopio manda il dato effettivo; 6- SPI1 riceve il dato, il quale viene salvato in un’apposita variabile; 7- Si termina la comunicazione bloccando il canale di comunicazione. Tale processo deve essere effettuato due volte per ogni asse. Il sensore del giroscopio, infatti, memorizza ogni asse in due registri: ad esempio la rotazione sull’asse x è memorizzata nei registri OUT_X_L e OUT_X_H. Questo implica che per ottenere i valori degli assi x, y e z sarà necessario effettuare i passi da 1 a 7 per sei volte. 25 I registri a cui accedere per ottenere i valori degli assi sono mostrati nella seguente tabella: Figura 3.2 Si noti inoltre che la modalità con cui si deve accedere ai registri deve essere in lettura; per ottenere ciò è necessario effettuare una or tra il registro a cui si accedere e il valore esadecimale 0x80. 26 Capitolo 4: Esempio di utilizzo del protocollo SPI e comunicazione con il sensore sul microcontrollore STM32F4xx Di seguito è mostrato il codice sorgente riguardante la programmazione del microcontrollore STM32F4xx con il quale si utilizza il protocollo SPI per ottenere i valori degli assi di rotazione x, y e z, attraverso la comunicazione con il sensore del giroscopio. #include "stm32f4xx.h" short int data; short int cont = 8; short x; short y; short z; #define N 1000 #define CS_LO (uint16_t) 0x8 //Definizione abilitazioni #define GPIOACKEN (uint32_t) 0x1 #define GPIOECKEN (uint32_t) (1<<4) #define SPI1CKEN (uint32_t) (1<<12) // Definizione porte GPIOA #define PA7_AF (uint32_t) (1<<15) #define PA6_AF (uint32_t) (1<<13) #define PA5_AF (uint32_t) (1<<11) 27 #define PA5_SCK (uint32_t) (5<<20) #define PA6_MOSI (uint32_t) (5<<24) #define PA7_MISO (uint32_t) (5<<28) #define PA5_50MHZ (uint32_t) (1<<15) #define PA6_50MHZ (uint32_t) (1<<13) #define PA7_50MHZ (uint32_t) (1<<11) #define PA5_PD (uint32_t) (1<<15) #define PA6_PD (uint32_t) (1<<13) #define PA7_PD (uint32_t) (1<<11) // Definizione porte GPIOE #define PE3_DO (uint32_t) (1<<6) int main (void){ // Abilitazione periferiche RCC->AHB1ENR |= (GPIOACKEN|GPIOECKEN); //attiva porta A e porta E RCC->APB2RSTR |= SPI1CKEN; //il registro APB2RSTR è un registro di reset. Si setta a 1 il bit di SPI1 per resettarlo RCC->APB2RSTR &= !((uint32_t)SPI1CKEN); //abbassa il bit dell'SPI1 a 0 così non avverrà più il reset RCC->APB2ENR |= SPI1CKEN; //attiva l'ISP1 // Configurazione GPIOA GPIOA->MODER |= (PA5_AF|PA6_AF|PA7_AF); //setta i PIN PA5 PA6 PA7 in modalità alternata GPIOA->AFR[0] |= (PA5_SCK|PA6_MOSI|PA7_MISO); //setta la configurazione delle funzioni alternate. AFR[0] corrisponde al registro AFRL. Setta per ogni PIN i corrispondenti bit a 0101, impostando la configurazione AF05. Importando la configurazione AF05 per ogni PIN si imposta la modalità da usare sull'SPI, come si può verificare dal DataSheet GPIOA->OSPEEDR |= (PA5_50MHZ|PA6_50MHZ|PA7_50MHZ); //setta la velocità di ogni PIN a 50MH 28 GPIOA->PUPDR |= (PA5_PD|PA6_PD|PA7_PD); //setta i PIN in Pull- Down // Configurazione GPIOE GPIOE->MODER |= PE3_DO; //seleziona il PIN PE3 come output // Configurazione SPI1 SPI1->CR1 |=1<<9; //SSM=1; si abilita la selezione dello slave via software SPI1->CR1 |=1<<8; //setta a 1 il bit SSI (se si imposta SSM=1, SSI deve essere settato a 1) SPI1->CR1 |= 0x18; //si imposta il baud rate a 1/16 (più è alto il baud rate più velocemente riceve/trasmette) SPI1->CR1 |=1<<2; //si abilita il bit MSTR, in pratica si imposta il microcontrollore in modalità master SPI1->CR1 |= 1<<6; //SPI attivo while(1){ //lettura di X GPIOE->ODR &= !(CS_LO); // setta a 0 il CH SELECT while(((SPI1->SR)&0x2)==0); //attende che il buffer di trasmissione sia vuoto SPI1->DR = (uint16_t) (0x80|0x28); //"punta" il registro OUT_X_L del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); //attende che il buffer di ricezione sia vuoto data = SPI1->DR; //legge il dato ricevuto. Il dato letto non ha rilevanza, ma è necessario eseguire tale istruzione altrimenti il buffer di ricezione non si libera while(((SPI1->SR)&0x2)==0); //attende che il buffer di trasmissione sia vuoto 29 SPI1->DR = (uint16_t) 0x1; //invia un dummy while(((SPI1->SR)&0x1)==0); //attende che il buffer di ricezione sia vuoto data = SPI1->DR; //riceve il valore X_L GPIOE->ODR |= CS_LO; //setta a 1 il CH SELECT x =( uint16_t)data; //copia il dato letto da X_L sui bit da 0 a 7 della variabile x GPIOE->ODR &= !(CS_LO); while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) (0x80|0x29); //"punta" il registro OUT_X_H del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) 0x1; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; //riceve il valore X_H GPIOE->ODR |= CS_LO; x|=(uint16_t)data<<8; //copia il dato letto da X_H sui bit da 8 a 15 della variabile x //lettura di Y GPIOE->ODR &= !(CS_LO); while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) (0x80|0x2A); //"punta" il registro OUT_Y_L del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); 30 data = SPI1->DR; while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) 0x1; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; //riceve il valore Y_L GPIOE->ODR |= CS_LO; y=(uint16_t)data; GPIOE->ODR &= !(CS_LO); while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) (0x80|0x2B); //"punta" il registro OUT_Y_H del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) 0x1; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; //riceve il valore Y_H GPIOE->ODR |= CS_LO; y|=(uint16_t)data<<8; //lettura di Z GPIOE->ODR &= !(CS_LO); while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) (0x80|0x2C); //"punta" il registro OUT_Z_L del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; 31 while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) 0x1; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; //riceve il valore Z_L GPIOE->ODR |= CS_LO; z=(uint16_t)data; GPIOE->ODR &= !(CS_LO); while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) (0x80|0x2D); //"punta" il registro OUT_Z_H del giroscopio in modalità lettura; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; while(((SPI1->SR)&0x2)==0); SPI1->DR = (uint16_t) 0x1; while(((SPI1->SR)&0x1)==0); data = SPI1->DR; //riceve il valore Z_H GPIOE->ODR |= CS_LO; z|=(uint16_t)data<<8; } } 32 Bibliografia [1] STMicroelectronics group, RM0368 Reference manual, 835, 2014 [2] STMicroelectronics group, PM0214 Programming manual, 245, 2014 [3] STMicroelectronics group, MEMS motion sensor: three-axis digital output gyroscope, 44, 2012 33