La Serial Peripheral Interface (SPI) è stata sviluppata da Motorola per consentire ai suoi chip di comunicare tra loro, proprio come Philips ha ideato il bus seriale I2C per i propri circuiti integrati. Mentre questi due bus fanno in gran parte lo stesso lavoro, entrambi sono diventati quasi ugualmente comuni, e molti dispositivi periferici utilizzano l’uno o l’altro per comunicare con un microcontrollore host. Questa ubiquità è il motivo per cui gli IMP li supportano entrambi.

SPI presenta alcuni vantaggi rispetto a I2C, in particolare il supporto per una maggiore velocità di trasferimento dati., SPI ha anche una capacità duplex che lo rende particolarmente adatto per quelle applicazioni che richiedono la comunicazione bidirezionale simultanea.

D’altra parte, SPI richiede almeno tre fili, condivisi da tutti i dispositivi sul bus, e un numero di linee di selezione del dispositivo, una per ogni periferica collegata al dispositivo di controllo. I2C, al contrario, richiede solo due fili; utilizza indirizzi univoci per identificare tutti i dispositivi sul bus., Ciò rende il lavoro con più dispositivi più semplice rispetto all’approccio senza indirizzi di SPI, anche se alcuni sviluppatori preferiscono utilizzare l’hardware per selezionare un dispositivo piuttosto che i dati degli indirizzi.

Controller e periferiche

SPI separa i dispositivi in ‘controller’ e ‘periferiche’. Solo un dispositivo può inviare impulsi di temporizzazione per sincronizzare i trasferimenti di dati, e questo è quello scelto per essere il controller. Tutti gli altri, che sincronizzano i loro tempi con il controller, sono considerati periferiche sussidiarie., Il controller-che nel tuo prodotto deve essere attualmente il suo imp-e le sue periferiche possono trasmettere e ricevere dati, ma solo il controller può stabilire il modello di temporizzazione a cui operano tutti. Questa creazione di uno schema di temporizzazione fissa è ciò che rende SPI, come I2C, un bus “sincrono”.

Il bus fisico

L’implementazione SPI dell’imp ha quattro linee:

  • SCLK, il segnale di clock seriale dal controller.
  • COPI, abbreviazione di ‘Controller Out, Peripheral In’ (a volte etichettato MOSI nei vecchi datasheet).,
  • CIPO, abbreviazione di ‘Controller In, Peripheral Out’ (a volte etichettato MISO).
  • CS, abbreviazione di ‘Chip Select’ (a volte etichettato SS, nSS o SYNC)

COPI e CIPO sono le linee di trasferimento dati.

imp001 e imp002 non forniscono pin CS dedicati: è invece possibile utilizzare uno qualsiasi degli altri pin GPIO di imp. imp003 e versioni successive forniscono pin CS dedicati come parte dei loro bus SPI, contrassegnati nella pagina imp pin mux.

Nota L’imp005 fornisce un pin di selezione chip dedicato su ciascuno dei suoi due bus SPI. Per spiBCAD questo è pin D; per spi0 questo è pin CS0., Il metodo API imp chipselect() può essere utilizzato per prendere il controllo dell’asserzione e della de-asserzione di questi pin di selezione del chip (consultare la documentazione del metodo per ulteriori informazioni).


SPI sull’imp: fino a quattro linee si collegano a un singolo dispositivo periferico

Questo approccio segue la definizione di SPI di Motorola: che ogni transazione bus — essenzialmente un batch di byte di dati — dovrebbe essere collegata a una periferica specifica., Texas Instruments ha modificato la specifica SPI per consentire a ciascun byte di essere inviato a una periferica specifica, anche se ciò richiede una linea CS dedicata. Questa modalità non è attualmente supportata da alcun imp.

Segnalazione

Supponendo di avere una singola periferica collegata al controller, le comunicazioni vengono avviate dal controller tirando la linea CS bassa. Il dice alla periferica di prepararsi a conversare. Ora il controller inizia a inviare impulsi di clock lungo la linea SCLK; in genere le trasmissioni di dati vengono digitate sul bordo di salita di ciascun impulso, anche se non è sempre così.,


Clocking dei dati in e out: l’imp invia un comando, la periferica restituisce i dati

Il controller trasmetterà ora i dati sulla linea COPI, guidando attivamente la linea alta per segnalare un 1 o basso per uno 0. La periferica leggerà il segnale-che potrebbe essere un comando per una lettura del sensore da inviare, per esempio — e restituirà quell’informazione sulla linea CIPO, di nuovo guidando la linea a rimanere alta per segnalare un 1 o guidandola bassa per trasmettere uno 0., Questo requisito che la linea sia attivamente guidata alta o bassa, piuttosto lasciandola stabilirsi in uno stato o nell’altro collegando un resistore, è il motivo per cui SPI può supportare velocità più elevate di I2C. I2C perde tempo di trasmissione mentre la sua resistenza di pull-up restituisce la linea ad alta.

Detto questo, è comunque buona norma avere anche un pull-up su una linea CS per garantire che vada in alto quando l’imp si avvia o dorme e quindi non è in grado di guidare la linea in alto manualmente. Mantenendo la linea alta assicura che la periferica ignorerà eventuali difetti sulle linee di dati e di clock.,

Quando il controller ha quello che vuole, guida la linea CS alta ancora una volta e la periferica può riposare.

Opzioni SPI imp

Ogni imp ha un numero di bus SPI indipendenti, accessibili come proprietà dell’oggetto hardware del dispositivo, che viene istanziato all’avvio. La tabella pin mux di ogni imp mostra che ci sono molte scelte, a seconda del tipo di imp che si sta utilizzando nel prodotto. Questo documento presuppone che tu stia usando un imp001, quindi dovresti consultare la tabella pin mux se stai lavorando con un imp diverso., I due bus SPI di imp001 sono entrambi implementazioni a tre fili del bus e collegati rispettivamente ai pin 1, 8 e 9 e 2, 5 e 7. Pin 1 e 5 sono SCLK; 8 e 7 COPI; e 9 e 2 CIPO. A seconda di quale dei due autobus si utilizza, è buona pratica alias sin da principio:

spi1 <- hardware.spi257;spi2 <- hardware.spi189;

Configurare per l’uso, è semplicemente una questione di dire imp quanto velocemente si desidera che il bus per l’esecuzione, e di fornire una serie di costanti che, insieme, determinano come il bus che vi operano:

spi1.configure(modeFlags, speed);

in Primo luogo, la velocità., This is simply an integer value giving the throughput in kiloHertz (kHz):

The specific SPI data rates available (in kHz) are as follows:

imp001, imp002 imp003 imp004m imp005 imp006
spi189 spi257 spiEBCA
spiLGDK
spiAHSR
spiGJKL
spiBCAD
spi0
spiXTUVW
15,000 30,000 18,000 24,000 The SPI data rates
available range
from 5KHz to 22.,8MHz
The SPI is clocked
by dividing 160MHz
by any integer
from 7 to 32,000
inclusive
Min. 187KHz, max. 750KHz
7500 15,000 9000 12,000
3750 7500 4500 6000
1875 3750 2250 3000 All others
937.50 1875 1125 1500 Min. 187KHz,
theoretical max. 24MHz
468.75 937.50 562.50 750
234.,375 468.75 281.25 375
117.1875 234.375 140.,g) edge
MSB_FIRST Invia il bit più significativo prima (impostazione predefinita)
LSB_FIRST Invia il bit meno significativo di prima
NO_SCLK SCLK pin non viene utilizzato
USE_CS_L Abilita l’utilizzo del chip dedicato selezionare pin (imp005 solo)

Questi possono essere uniti, se necessario, utilizzando l’operatore logico or, |, anche se alcuni si escludono a vicenda, quindi non dovrebbe essere combinato: SIMPLEX_TX e SIMPLEX_RX, per esempio., Per utilizzare entrambi i CLOCK_IDLE_LOW e CLOCK_2ND_EDGE, per esempio, invece di entrare in un unica costante come parametro nel metodo configure() si dovrebbe includere entrambi, separati da | simbolo

spi1.configure(SIMPLEX_TX | MSB_FIRST | CLOCK_IDLE_LOW, 400);

le Combinazioni possono essere necessari se sono specificati da periferiche del foglio dati, anche se questo potrebbe non essere immediatamente evidente per il nuovo arrivato. Le schede tecniche possono parlare della “modalità SPI” di un dispositivo o dei suoi valori CPOL (Polarità dell’orologio) e CPHA (fase dell’orologio)., CPOL e CPHA determinano quali bordi del segnale di clock vengono utilizzati per guidare e campionare i segnali di dati. Ognuno di questi due parametri ha due possibili stati, per quattro possibili combinazioni in tutto:


Modalità SPI

Le modalità SPI indicizzano semplicemente quelle combinazioni piuttosto che i valori CPOL e CPHA separati. Il controller e la periferica devono comunicare utilizzando gli stessi valori CPOL e CPHA, e quindi la stessa Modalità., Più periferiche potrebbero significare configurazioni diverse, quindi il controller dovrà riconfigurarsi ogni volta che deve comunicare con una periferica specifica.,la tabella seguente:

la Lettura E la Scrittura dei Dati

dopo Aver configurato il bus SPI, utilizzare il metodo write() per inviare una stringa di byte per la periferica:

spi1.write("This is an LCD display");

Utilizzo di una stringa è facoltativo: è possibile anche inviare un blob di materie prime byte di dati:

local blob = blob(4); // Create a four-byte blob...blob.writen(0xDEADBEEF, 'i'); // ...and write a 32-bit value to itspi1.write(blob);

Se si desidera leggere una stringa o un blob, avete bisogno di uno di imp, API, due SPI metodi di lettura:

local bytes = spi1.readblob(8);local inputString = spi1.readstring(16);

Il valore intero passato come parametro è, rispettivamente, il numero di byte da leggere nel blob e il numero di caratteri da mettere nella stringa., Naturalmente, poiché un carattere occupa un byte, questi due metodi sono equivalenti. Quest’ultimo converte semplicemente blob in stringa per te.

A causa della natura ‘full duplex’ del bus SPI, le scritture e le letture avvengono sempre simultaneamente. Con i comandi di lettura e scrittura che abbiamo visto finora, i dati che si muovono nella direzione opposta a quella a cui siamo interessati vengono ignorati o azzerati. Quindi, quando scrivi una stringa, ad esempio, tutti i dati che arrivano all’imp dalla periferica vengono ignorati., Durante una delle due operazioni di lettura, una dimensione corrispondente di zero byte “fittizi” viene scritta sulla periferica: se si leggono otto byte, ad esempio, otto 0 vengono scritti automaticamente.

Per gestire questa comunicazione bidirezionale simultanea, l’API imp ha un quarto metodo che combina letture e scritture:

local inputString = spi1.writeread(outputString);

Quindi, mentre la stringa outputString viene inviata lungo la linea COPI, la variabile inputString viene riempita dai byte di dati in arrivo su CIPO. È possibile inviare e ricevere stringhe o blob, ma sia l’input che l’output devono essere dello stesso tipo., Per quanto grande sia il tuo blob di output, il tuo blob di input sarà della stessa dimensione. Allo stesso modo, le stringhe di input e output avranno la stessa lunghezza.

Il funzionamento full duplex può essere utilizzato anche con dispositivi che non prevedono di operare in questo modo, quelli che richiedono che i byte “fittizi” di lettura e scrittura siano un valore specifico diverso da zero. Questo requisito esclude l’utilizzo dei normali metodi write(), readblob() e readstring (), ma writeread() può essere utilizzato al loro posto per assicurarsi che vengano utilizzati i valori fittizi preferiti del dispositivo.,

Codice di esempio

Il seguente codice funziona con l’accelerometro digitale Analog Devices ADXL345, una parte che utilizza SPI per comunicare con il suo microcontrollore host. Supporta anche I2C e i pin di questa scheda breakout Adafruit, basata sul chip, sono etichettati di conseguenza. La scheda tecnica del chip può essere scaricata dal sito web di Analog Devices.

Come funziona il codice

Usiamo un bus spi257 di imp001, alias vicino all’inizio dell’elenco come spi. Abbiamo anche alias pin 8 come la linea CS. La funzione spiWriteReg () mostra come questi vengono utilizzati., Una transazione di scrittura viene segnalata commutando la linea CS bassa. Successivamente l’indirizzo del registro su cui vogliamo scrivere viene convertito da un intero con segno a 32 bit di scoiattolo a un valore a 8 bit scrivendolo in un blob. Questo blob viene quindi scritto sul bus SPI. Facciamo la stessa cosa con il valore che vogliamo che ADXL345 inserisca in quel registro, quindi impostiamo nuovamente la linea CS alta per segnalare la fine della transazione.,


I dispositivi Adafruit/Analog ADXL345

La funzione spiReadReg() funziona allo stesso modo, solo che questa volta leggiamo i dati del valore dal bus dopo aver scritto l’indirizzo del registro di origine. L’ADXL345 richiede alcune modifiche da apportare all’indirizzo del registro in questo caso: bit 7 deve essere impostato per contrassegnare la transazione come un’operazione di lettura, e bit 6 deve essere impostato per dire al chip che ci aspettiamo più di un singolo byte da inviare indietro.,

Dove inizia il programma corretto, configuriamo il bus SPI dell’imp per soddisfare i requisiti del chip ADXL345. Esso utilizza la modalità SPI 3-ie. sia CPOL che CPHA dovrebbero essere impostati, quindi usiamo il parametro imp equivalente: CLOCK_IDLE_HIGH / CLOCK_2ND_EDGE nella chiamata configure (). Abbiamo anche impostato la velocità su 100kHz. Successivamente, il pin 8 dell’imp, che funziona qui come pin CS, viene configurato come uscita digitale e impostato in alto.


Cablaggio dell’ADXL345

Altre funzioni del programma inizializzano l’ADXL345 stesso anziché il bus SPI., L’ADXL345 viene inizializzato e il codice legge il valore dall’indirizzo del registro 0x00 per garantire che il dispositivo sia presente sul bus. Il chip ha una modalità di auto-test che permette una serie di letture di calibrazione da prendere; questo facciamo e memorizzare i risultati. Successivamente, nella funzione loop (), questi valori vengono utilizzati per regolare le letture finali dall’accelerometro.,

L’ADXL345 salva i suoi campioni degli assi x, y e z come valori a 16 bit, ciascuno in due registri a 8 bit; loop() utilizza la funzione spiReadReg() per acquisire i due componenti di ciascun valore e quindi li converte in singoli valori moltiplicando il byte più significativo per 256 e aggiungendo al risultato il valore del byte meno significativo.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *