Nell’articolo vengono presentati alcuni esempi di configurazione dell’interfaccia SPI per i micro Fujitsu. Si dice che l’SPI sia una semplice comunicazione seriale tra due dispositivi digitali, tuttavia la mancanza di un formato standard non lo rende affatto semplice. Questo articolo descrive i più comuni formati SPI e come implementarli sui Fujitsu a otto e sedici bit.
Alcuni formati SPI
L’SPI è una comunicazione seriale tra un singolo dispositivo master e un singolo dispositivo slave. Ciascun bit di da ti da e per il master ha il suo proprio impulso di clock. Perciò l’SPI usa almeno tre diversi segnali:
» SCK clock seriale;
» SI input seriale, ovvero i dati dallo Slave verso il Master;
» SO output seriale, ovvero i dati dal Master verso lo Slave.
Alcuni formati SPI usano un quarto segnale chiamato “Chip Select” (CS) che avvia la comunicazione da parte del master. Questo segnale può essere attivo a livello logico alto o basso. Dal momento che non esiste nessuna specifica SPI, la temporizzazione del segnale di clock dipende dal dispositivo e così ogni produttore ne adotta una sua. Per la maggior parte dei protocolli SPI sono possibili quattro diversi settaggi, i quali si possono stabilire attraverso i controlli CPOL (polarità di clock) e CPHA (fase di clock):
» CPOL definisce lo stato attivo del segnale di clock seriale;
» CPHA permette di definire la fase del clock rispetto al segnale SO.
Non c’è nessuna classificazione dei protocolli e dei dispositivi SPI che definisca le impostazioni di CPOL e CPHA da adottare per ottenere un determinato protocollo. In questo articolo esse verranno definiti come segue:
» CPOL = 0 il clock SPI ha il suo livello attivo “1”;
» CPOL = 1 il clock SPI ha il suo livello attivo “0”;
» CPHA = 0 il clock SPI è sincrono con il segnale SO;
» CPHA = 1 il clock SPI è ritardato di mezzo periodo rispetto al segnale SO. Nella maggior parte dei protocolli SPI si adotta la convenzione per cui si scrive prima il MSB (Most significant byte). La velocità della comunicazione SPI dipende dall’hardware stesso; essa varia in un intervallo di valori compreso tra i Kbits/s e alcuni Mbits/s.
Protocolli SPI
In questa sezione vengono descritte le temporizzazioni dei più comuni protocolli SPI:
» CPOL = 0, CPHA =0
Questo formato SPI è in accordo con il formato seriale sincrono standard (figura 1).
» CPOL = 1, CPHA =0
Questo formato SPI è in accordo con il formato seriale sincrono standard con il clock invertito (figura 2).
» CPOL = 0, CPHA =1
In questo formato SPI il segnale di clock è ritardato di mezzo periodo rispetto allo standard sincrono standard (figura 3).
Da notare che in questo formato il primo bit del data-byte deve essere settato nel segnale SO prima del primo impulso di clock.
» CPOL = 1, CPHA =1
In questo formato SPI il segnale di clock è ritardato di mezzo periodo rispetto allo standard sincrono standard e il clock è invertito (figura 4). Come nel caso precedente il primo bit del data-byte va settato prima del primo impulso di clock.
Implementazione della comunicazione SPIMaster
In questa parte dell’articolo viene descritto come implementare i differenti formati SPI:
SPI con CPHA=0 e CPOL=0
Questo formato SPI è disponibile per tutte le interfacce SIO. Gli UARTs Fujitsu in modalità sincrona possono gestire questo formato.
SPI con CPHA=0 e CPOL=1
Questo formato SPI è disponibile per tutte le interfacce Fujitsu SIO con inversione del clock seriale. Gli UARTs Fujitsu in modalità sincrona e inversione del clock seriale possono gestire questo formato. Formati SPI con CPHA=1
Questo formato è disponibile per i LIN_UART a partire dalle serie MB90340. Per implementare questo il programmatore deve usare il modo sincrono e SCDE = 1 (Serial Clock Delay Enable) e SCES = x ( Serial Clock Edge Select e CPOL = x). SPI con SIO e CPHA=1, CPOL=0
L’interfaccia SIO può gestire normalmente solo formati con il CPHA = 0. Il seguente codice C mostra un esempio di implementazione di questo formato. Si può notare che la massima velocità nella comunicazione dipende dal tempo di esecuzione delle istruzioni e l’esecuzione della funzione SPI_Byte non deve essere interrotta da interrupt (listato 1 e 2). SPI con SIO e CPHA=1, CPOL=1
void InitSIO (void) { PDR4 = 0x80; // SCK2 port 47 pin MB90540 series DDR4 = 0x80; // SCK2 set to “1” SMCS_SOE = 1; // Serial Output enable SMCS_SCOE = 0; // Internal serial clock disable SES2_NEG = 1; // Invert clock SMCS_STOP = 0; // Reset STOPC SMCS_SMD = 0x05; // External shift clock mode SMCS_BDS = 1; // Set MSB first
Listato 1 |
unsigned char SPI_Byte(data) { SDR = data; // Write data to shifter SMCS_STRT = 1; // Set communication start SES2_NEG = 0; // Generate “internal clock” pulse SES2_NEG = 1; // to set first data bit on SOT2 PDR4_P47 = 0; // generate 8 clock pulses on SCK2 PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; SES2_NEG = 0; // “internal clock” pulse to fulfill SES2_NEG = 1; // SIO communication data = SDR; // read shifter return data; }
Listato 2 |
La procedura per implementare il formato con CPOL=1 è molto simile a quella appena riportata. Per essa valgono le stesse considerazioni sopra riportate (vedi l’esempio in C riportato nei listati 3 e 4).
void InitSIO (void) { PDR4 = 0x00; // SCK2 port 47 pin MB90540 series DDR4 = 0x80; // SCK2 set to “0” SMCS_SOE = 1; // Serial Output enable SMCS_SCOE = 0; // Internal serial clock disable SES2_NEG = 0; // Normal clock SMCS_STOP = 0; // Reset STOP SMCS_SMD = 0x05; // External shift clock mode SMCS_BDS = 1; // Set MSB first }
Listato 3 |
unsigned char SPI_Byte(data) { SDR = data; // Write data to shifter SMCS_STRT = 1; // Set communication start SES2_NEG = 1; // Generate “internal clock” pulse SES2_NEG = 0; // to set first data bit on SOT2 PDR4_P47 = 1; // generate 8 clock pulses on SCK2 PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; PDR4_P47 = 1; PDR4_P47 = 0; SES2_NEG = 1; // “internal clock” pulse to fulfill SES2_NEG = 0; // SIO communication data = SDR; // read shifter
Listato 4 |
SPI con UART in modalità sincrona e CPHA=1, CPOL=0
Il metodo per l’SPI tramite UART in modalità sincrona è simile al metodo usato con l’interfacia SIO. In quest’esempio il clock dell’ UART viene generato internamente “togglando” il NEG-Bit. Da notare che l’esempio riportato sotto funziona solo con UARTs che supportano una modalità seriale sincrona e un prescaler. Tali UARTs sono identificabili tramite il registro CDC (Clock Division Control) (listato 5).
void InitUART(void) { SMR1_MD1 = 1; // Set synchronous mode SMR1_MD0 = 0; SMR1_CS2 = 1; // Set external clock source SMR1_CS1 = 1; SMR1_CS0 = 1; SMR1_SCKE = 0; // External clock SMR1_SOE = 1; // Serial Output Enable SES1_NEG = 1; // Invert Clock SCR1_TXE = 1; // Transmission Enable PDR4 = 0x10; // SCK1 Port 44 pin on MB90540 series DDR4 = 0x10; // SCK1 set to “1” } unsigned char SPI_Byte(data) { SODR1 = data; // Write data to transmission register DI(); // Disable all interrupts SES1_NEG = 0; // Generate “internal clock” pulse SES1_NEG = 1; // to set first data bit on SOT1 PDR4_P44 = 0; // generate 8 clock pulses on SCK1 PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; PDR4_P44 = 0; PDR4_P44 = 1; SES1_NEG = 0; // “internal clock” pulse to fulfill SES1_NEG = 1; // serial task EI(); // Enable all interrupts (optional) data = SIDR; // read from reception register return data; }
Listato 5 |
SPI con UART in modalità sincrona e CPHA=1, CPOL=0
Implementazione della comunicazione SPI-Slave
La tabella di figura 5, mostra i settaggi del LIN-U(S)ART (presenti, per esempio nelle serie MB90340).
I bit di controllo TXE e RXE del registro di comunicazione seriale (SCR) dovrebbero essere settati per ultimi nella procedura di inizializzazione pena il malfunzionamento del LIN-U(S)ART. La tabella in figura 6, mostra le varie possibilità, presenti in diverse famiglie di MCUs, riguardo all’ UART SPI-Master.