Arduino - Interfaz de periféricos en serie

Un bus de interfaz periférica en serie (SPI) es un sistema para la comunicación en serie, que utiliza hasta cuatro conductores, normalmente tres. Un conductor se utiliza para la recepción de datos, uno para el envío de datos, uno para la sincronización y uno alternativamente para seleccionar un dispositivo con el que comunicarse. Es una conexión full duplex, lo que significa que los datos se envían y reciben simultáneamente. La velocidad máxima en baudios es superior a la del sistema de comunicación I2C.

Pines de tablero SPI

SPI utiliza los siguientes cuatro cables:

  • SCK - Este es el reloj serial impulsado por el maestro.

  • MOSI - Esta es la salida maestra / entrada esclava impulsada por el maestro.

  • MISO - Esta es la entrada maestra / salida esclava impulsada por el maestro.

  • SS - Este es el cable de selección de esclavos.

Se utilizan las siguientes funciones. Tienes que incluir el SPI.h.

  • SPI.begin() - Inicializa el bus SPI configurando SCK, MOSI y SS en las salidas, bajando SCK y MOSI y SS alto.

  • SPI.setClockDivider(divider)- Para configurar el divisor de reloj SPI en relación con el reloj del sistema. En las tarjetas basadas en AVR, los divisores disponibles son 2, 4, 8, 16, 32, 64 o 128. La configuración predeterminada es SPI_CLOCK_DIV4, que establece el reloj SPI en un cuarto de la frecuencia del reloj del sistema (5 Mhz para placas a 20 MHz).

  • Divider - Podría ser (SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128).

  • SPI.transfer(val) - La transferencia SPI se basa en un envío y recepción simultáneos: los datos recibidos se devuelven en selectedVal.

  • SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) - speedMaximum es el reloj, dataOrder (MSBFIRST o LSBFIRST), dataMode (SPI_MODE0, SPI_MODE1, SPI_MODE2 o SPI_MODE3).

Tenemos cuatro modos de operación en SPI de la siguiente manera:

  • Mode 0 (the default) - El reloj es normalmente bajo (CPOL = 0) y los datos se muestrean en la transición de bajo a alto (borde de entrada) (CPHA = 0).

  • Mode 1 - El reloj es normalmente bajo (CPOL = 0), y los datos se muestrean en la transición de alto a bajo (borde de salida) (CPHA = 1).

  • Mode 2 - El reloj es normalmente alto (CPOL = 1) y los datos se muestrean en la transición de alto a bajo (borde de entrada) (CPHA = 0).

  • Mode 3 - El reloj es normalmente alto (CPOL = 1) y los datos se muestrean en la transición de bajo a alto (borde de salida) (CPHA = 1).

  • SPI.attachInterrupt(handler) - Función que se llamará cuando un dispositivo esclavo reciba datos del maestro.

Ahora, conectaremos dos placas Arduino UNO juntas; uno como amo y el otro como esclavo.

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

El suelo es común. A continuación se muestra la representación esquemática de la conexión entre ambas placas:

Veamos ejemplos de SPI como maestro y SPI como esclavo.

SPI como MAESTRO

Ejemplo

#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 como esclavo

Ejemplo

#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
   }
}