6. Il Firmware
6.1.4 Utilizzo dell’interfaccia SPI
Con 10bit quindi si ha una rappresentazione con valori che vanno da 0 a 1024; mentre utilizzando 8bit (cioè utilizzando i valori del solo registro ADCL) è possibile rappresentare il risultato su 256 valori.
6.1.4 Utilizzo dell’interfaccia SPI
Nel prototipo realizzato il dispositivo configurato come master, capace quindi di generare il clock, è il microcontrollore mentre l’unico dispositivo slave presente nel sistema è il sensore d’accelerazione. I registri che permettono di configurare e monitorare il trasferimento tramite SPI sono SPCR e SPSR, i dati ricevuti o da trasmettere sono contenuti nel registro SPDR.
Figura 79
Tramite il bit7 si abilita l’interruzione mentre mettendo a 1 il bit6 si abilita la porta l’SPI. Quando il bit5 (DORS) è posto a uno il primo bit della trasmissione è il bit LSB se posto a 0 il primo bit trasmesso è MSB; il bit4 consente di impostare il
microcontrollore come master o slave. I bit3-2 consentono di stabilire la polarità del clock come mostrato in figura 80 e in figura 81.
Figura 80 Trasferimento SPI con CPHA=0
Per ottenere una corretta comunicazione con lo Slave è fondamentale settare
correttamente questi bit, per sapere quale modalità va impiegata è necessario consultare il datasheet del componente Slave. Nel cado dell’accelerometro impiegato per il
prototipo è stato necessario impostare la modalità CPHA=1, CPOL=1 questo per
rendere la trasmissione compatibile con le temporizzazioni riportate nel paragrafo 5.3.2.
Tramite i bit1-0 e il bit SPI2x del registro SPSR si imposta la frequenza di trasmissione secondo i valori riportarti in tabella.
Tabella 8
Il bit7 (SPIF) è un bit di flag che ci consente di controllare quando il trasferimento è ultimato; infatti questo bit resta a 0 per tutta la durata del trasferimento dati e torna a 1 al termine.
Figura 82
La funzione SPI_init( ) sotto riporta, imposta i piedini per la linea SPI e configura il registro SPCR ponendo il bit PSE=1 per abilitare l’SPI, DORD=0 per trasmettere come primo bit LSB MSTR=1 configurando il microcontrollore come Master, CPOL e CPOH=1 per sincronizzare l’invio dei dati sul fronte di salita del clock come richiesto dall’accelerometro e i bit SPR1 e SPR0 per avere un fattore di prescalar pari a fck/16 cioè 500KHz. Fortunatamente i registri per la gestione dell’SPI dell’ ATmega128L e ATmaga16L sono identici, questo semplifica notevolmente al sezione di preprocessor dedicata che si riduce ad assegnare a DDR_SPI, SPIDI, SPICLK, SPIDO, SPICS i
rispettivi pin delle porteB a seconda del microcontrollore utilizzato (vedi paragrafo 6.2.6).
//--- //Funzione setup SPI
//_________________________________
void SPI_init(void) {
cbi(DDR_SPI, SPIDI); // PBx come SPI data input (MISO)
sbi(DDR_SPI, SPICLK); // PBx come SPI clock output
sbi(DDR_SPI, SPIDO); // PBx come SPI data out (MOSI)
sbi(DDR_SPI, SPICS); // PBx come uscita di chip select
outp((1 << SPE) | (0<<DORD) | (1 << MSTR) | (0<< SPR1) |( 1<<CPOL) | (1<<CPHA) | (1 << SPR0),SPCR); //frequenza di trasmissione fck/16
sbi(PORTB, 4); // pongo CS a 1 }
La funzione write register( ) consente la scrittura di un registro dell’accelerometro; come mostrato nella temporizzazione riportata in figura nel paragrafo 5.3.2 per accedere ad un registro dell’accelerometro in scrittura è necessario inviare per primo un byte nel quale il bit0 (RW) sia 0 ad indicare che si sta accedendo per effettuare una scrittura il bit1 (MS) va posto a 1 o a 0 a seconda che si voglia far incrementare l’indirizzo del registro in maniera automatica o meno e nei restati sei bit (bit2-7) deve essere indicato l’indirizzo del registro nel quale il bit2 corrisponde al MDB e il bit7 al LSB.
Alla funzione di scrittura vengono passate dall’esterno le variabile che contengono l’indirizzo del registro (register_name ) e il dato che si desidera scrivere (data ).
La funzione inserisce l’indirizzo nel registro SPCR partendo dal bit0 con LSB mettendo RW nel MSB; per ottenere l’invio partendo dal MSB è necessario porre a 1 il bit5 (DORS) del registro SPCR. Il termine dell’invio si ha quando il bit di flag (SPIF) torna a 1 a questo punto viene caricato nel registro SPDR il dato da inviare, una volta che i dati sono stati inviati e si è ricevuta conferma dal flag SPIF la funzione riporta CS a 1 per indicare la fine della comunicazione con l’accelerometro.
// --- // scrittura in un registro dell' accelerometro //__________________________________
void write register(char register_name, char data) {
// pone a 0 il bit 0 per indicare che stiamo scrivendo nell'accelerometro
cbi(register_name,7);
cbi(register_name,6);//pone a 0 il bit1 per non incrementare gli indirizzi
cbi(PORTB, 4); // pongo CS a 0 quindi attivo l'accelerometro
SPDR= register_name;
while (!(SPSR & (1<<SPIF))) {};//aspetto che il trasferimento degli 8 bit sia terminato
// invio i dati da mettere nel registro
SPDR = data; //scrivo i dati nel registro di trasferimento SPDR
while (!(SPSR & (1<<SPIF))) {};//aspetto che il trasferimento degli 8 bit sia terminato
sbi(PORTB, 4); // pongo CS a 1 fine della trasmissione
}
La funzione che permette la lettura di un registro dell’accelerometro è la spi_read( ) alla quale viene passato dall’esterno l’indirizzo del registro a cui accedere e al termine della lettura restituisce il valore contenuto in tale registro “return (dato_ricevuto)”.
Per accedere ad un registro dell’accelerometro in lettura è necessario inviare un byte nel quale il bit0 (RW) sia 1 ad indicare che si sta accedendo per effettuare una lettura, il bit1 (MS) va posto a 1 o a 0 a seconda che si voglia far incrementare l’indirizzo del registro in maniera automatica o meno e nei restati sei bit (bit2-7) viene messo l’indirizzo del registro del cui vogliamo leggere il contenuto; nel quale il bit2 corrisponde al MDB e il bit7 al LSB. Una volta inviato il byte con l’indirizzo
l’accelerometro mette il valore contenuto in tale registro nel registro di trasmissione che comunica con il microcontrollore, quindi è necessario un nuovo ciclo di lettura per fare in modo che gli shift register si scambino i valori e quindi che venga “ciclato” nel registro SPDR il contenuto di nostro interesse. Al termine di questa operazione il contenuto di tale registro viene copiato nella variabile “dato_ricevuto” che lo riporta all’esterno della funzione.
//--- // lettura di un registro dell' accelerometro //________________________________
char spi_read(char register_name) {
char dato_ricevuto = 0;
// invio l'indirizzo del registro
//pone a 1 il bit 0 per indicare che stiamo leggendo nell'accelerometro
sbi(register_name,7);
cbi(register_name,6); //pone a 0 il bit1 per non incrementare gli indirizzi
SPDR= register_name;
while (!(SPSR & (1<<SPIF))) {}; // si attende il termine dell'invio del byte //dell'indirizzo
SPDR=0; // nova trasmissione per far shiftare i dati del
//registro che si vuole leggere nel registro SPDR
while (!(SPSR & (1<<SPIF))) {}; // si attende il termine dell'invio del byte
//dell'indirizzo6
dato_ricevuto = SPDR; return (dato_ricevuto); }