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