Arduino - Interfaccia periferica seriale

Un bus SPI (Serial Peripheral Interface) è un sistema per la comunicazione seriale, che utilizza fino a quattro conduttori, comunemente tre. Un conduttore viene utilizzato per la ricezione dei dati, uno per l'invio dei dati, uno per la sincronizzazione e uno in alternativa per selezionare un dispositivo con cui comunicare. È una connessione full duplex, il che significa che i dati vengono inviati e ricevuti contemporaneamente. La velocità di trasmissione massima è superiore a quella del sistema di comunicazione I2C.

Board SPI Pins

SPI utilizza i seguenti quattro fili:

  • SCK - Questo è l'orologio seriale pilotato dal master.

  • MOSI - Questa è l'uscita master / ingresso slave pilotato dal master.

  • MISO - Questo è l'ingresso master / uscita slave pilotato dal master.

  • SS - Questo è il cavo di selezione degli schiavi.

Vengono utilizzate le seguenti funzioni. Devi includere SPI.h.

  • SPI.begin() - Inizializza il bus SPI impostando SCK, MOSI e SS sulle uscite, portando SCK e MOSI bassi e SS alti.

  • SPI.setClockDivider(divider)- Per impostare il divisore dell'orologio SPI relativo all'orologio di sistema. Sulle schede basate su AVR, i divisori disponibili sono 2, 4, 8, 16, 32, 64 o 128. L'impostazione predefinita è SPI_CLOCK_DIV4, che imposta l'orologio SPI a un quarto della frequenza dell'orologio di sistema (5 Mhz per schede a 20 MHz).

  • Divider - Potrebbe essere (SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128).

  • SPI.transfer(val) - Il trasferimento SPI si basa su un invio e una ricezione simultanei: i dati ricevuti vengono restituiti in receiveVal.

  • SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) - speedMaximum è l'orologio, dataOrder (MSBFIRST o LSBFIRST), dataMode (SPI_MODE0, SPI_MODE1, SPI_MODE2 o SPI_MODE3).

Abbiamo quattro modalità di funzionamento in SPI come segue:

  • Mode 0 (the default) - Il clock è normalmente basso (CPOL = 0) ei dati vengono campionati sulla transizione da basso ad alto (fronte di salita) (CPHA = 0).

  • Mode 1 - Il clock è normalmente basso (CPOL = 0), e i dati vengono campionati sulla transizione da alto a basso (fronte di discesa) (CPHA = 1).

  • Mode 2 - Il clock è normalmente alto (CPOL = 1) e i dati vengono campionati sulla transizione da alto a basso (fronte di salita) (CPHA = 0).

  • Mode 3 - Il clock è normalmente alto (CPOL = 1) e i dati vengono campionati nella transizione da basso ad alto (fronte di discesa) (CPHA = 1).

  • SPI.attachInterrupt(handler) - Funzione da richiamare quando un dispositivo slave riceve dati dal master.

Ora collegheremo insieme due schede Arduino UNO; uno come padrone e l'altro come schiavo.

  • (SS): pin 10
  • (MOSI): pin 11
  • (MISO): pin 12
  • (SCK): pin 13

Il terreno è comune. Di seguito è riportata la rappresentazione schematica della connessione tra le due schede:

Vediamo esempi di SPI come Master e SPI come Slave.

SPI come MASTER

Esempio

#include <SPI.h>

void setup (void) {
   Serial.begin(115200); //set baud rate to 115200 for usart
   digitalWrite(SS, HIGH); // disable Slave Select
   SPI.begin ();
   SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8
}

void loop (void) {
   char c;
   digitalWrite(SS, LOW); // enable Slave Select
   // send test string
   for (const char * p = "Hello, world!\r" ; c = *p; p++) {
      SPI.transfer (c);
      Serial.print(c);
   }
   digitalWrite(SS, HIGH); // disable Slave Select
   delay(2000);
}

SPI come SLAVE

Esempio

#include <SPI.h>
char buff [50];
volatile byte indx;
volatile boolean process;

void setup (void) {
   Serial.begin (115200);
   pinMode(MISO, OUTPUT); // have to send on master in so it set as output
   SPCR |= _BV(SPE); // turn on SPI in slave mode
   indx = 0; // buffer empty
   process = false;
   SPI.attachInterrupt(); // turn on interrupt
}
ISR (SPI_STC_vect) // SPI interrupt routine { 
   byte c = SPDR; // read byte from SPI Data Register
   if (indx < sizeof buff) {
      buff [indx++] = c; // save data in the next index in the array buff
      if (c == '\r') //check for the end of the word
      process = true;
   }
}

void loop (void) {
   if (process) {
      process = false; //reset the process
      Serial.println (buff); //print the array on serial monitor
      indx= 0; //reset button to zero
   }
}