Conectar dos Arduinos SPI http://www.electroensaimada.com/spi.html Este trabajo está hecho en base al del link de arriba. SPI (Serial Peripheral Interface) es básicamente un bus de comunicación a nivel de circuitos integrados. La transmisión de datos se realiza en serie, es decir un bit después de otro. El bus SPI se define mediante 4 pines: SCLK o SCK : Señal de reloj del bus. Esta señal rige la velocidad a la que se transmite cada bit. MISO(Master Input Slave Output): Es la señal de entrada a nuestro dispositivo, por aquí se reciben los datos desde el otro integrado. MOSI(Master Output Slave Input): Transmisión de datos hacia el otro integrado. SS o CS: Chip Select o Slave Select, habilita el integrado hacia el que se envían los datos. Esta señal es opcional y en algunos casos no se usa, por ejemplo con un solo Slave, programando sin interrupciones. Imagen de la conexión SPI. Fuente Wikipedia. A diferencia de otros buses el SPI no implementa el nivel del enlace entre dispositivos, es decir no hay un campo para la dirección ni un campo para ACK, etc. El SPI se comporta como un shift register donde a cada golpe de clock se captura un bit. En parte no es necesaria hacer un direccionamiento de los chips ya que mediante la señal Chip select, habilitamos al integrado al que queremos enviar los datos. El funcionamiento para un envío de un Master es el siguiente: Se habilita el chip al que hay que enviar la información mediante el CS (Opcional). Se carga en el buffer de salida el byte a enviar. La linea de Clock empieza a generar la señal cuadrada donde normalmente por cada flanco de bajada se pone un bit en MOSI (Salida de datos) El receptor normalmente en cada flanco de subida captura el bit de la linea MISO y lo incorpora en el buffer. Se repite el proceso 8 veces y se ha transmitido un byte. Si se ha terminado de transmitir se vuelve a poner la linea CS en reposo. Hay que tener en cuenta que a la vez que el Master esta enviando un dato también lo recibe así que si el Slave ha depositado algún byte en el buffer de salida, este también sera enviado y recibido por el Master. A continuación vamos a ver una transmision típica en SPI. En este caso se ha enviado el byte 0x52 que en binario seria 0101 0010 1 Figura: Envio de un byte mediante SPI. Las dosfiguras muestran el mismo código. Visto como se envia un byte en SPI vamos a ver sus principales ventajas. Comunicación Full-Duplex, es decir es capaz de enviar y recibir datos al mismo tiempo. Muy simple y usado en los integrados. Velocidades de comunicación relativamente elevadas. En el caso de Arduino de hasta 8 Mhz. Completo control sobre la trama de bits al no exigir direccionamiento ni ACK. Como todo también tiene sus desventajas que son las siguientes: No hay control del flujo por hardware. No hay confirmación de la recepción como si ocurre en I2C con el ACK. Es decir no sabemos si el mensaje ha llegado al destino. Usa mas pines que otros buses, ya que necesita uno por cada esclavo. Eso implica que no hay direccionamiento en la propia trama. A menos que se diseñe por software. Funcionamiento a distancias cortas Uso en Arduino Para experimentar, vamos a usar dos Arduinos, uno como Master y otro como Slave El Master mandará un mensaje al Slave, quien para poder realizar la lectura necesita hacer uso de las interrupciones de este modo cuando le llegue un byte saltara a la interrupción y allí haremos el tratamiento del dato recibido. A continuación podemos ver los dos programas. Programa Master // MASTER #include <SPI.h> 2 void setup (void) { Serial.begin(9600); digitalWrite(SS, HIGH); SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV16); // Elegimos esta velocidad para poder ver bien en el osciloscopio el caracter transmitido // Se puede poner 4, 8, 16, 32, 64 o 128. Mayor número menor velocidad. } // FIN del void setup (void) void loop (void) { char c; digitalWrite(SS, LOW); //Habilitamos el Slave en el pin 10 for (const char * string = "X131Y345Z786\n" ; c = *string; string++) { // Recorremos toda la cadena // Va a transmitir los valores de X,Y,Z, para que sean procesados en el Slave. // La cadena se puede armar antes, con los valores medidos. No olvidar “\n” // Es el fin de línea y/o línea nueva. SPI.transfer (c); //Enviamos caracter a caracter Serial.print(c); } digitalWrite(SS, HIGH);//Deshabilitamos el Slave delay (1000); // Para enviar un dato por segundo. } // FIN del void loop (void) Este programa está en el archivo ZIP como SPI_Master.ino Programa Slave // SLAVE #include <SPI.h> char buf [150]; volatile byte pos; volatile boolean recibido; void setup (void) { Serial.begin (9600); 3 pinMode(MISO, OUTPUT);//Configuramos el Miso como salida ya que el Master recibira por aqui. SPCR |= _BV(SPE);//Activamos el modo Slave pos = 0; // Posicion 0 de los bytes recibidos recibido = false; //Inicializamos que no hemos recibido. SPI.attachInterrupt();//Activamos la interrupcion del SPI } // FIN del void setup (void) ISR (SPI_STC_vect) // Interrupcion SPI { byte c = SPDR; //Obtenemos el byte buf [pos++] = c; if (c == '\n') // Espera encontrar el "\n" recibido = true; } // FIN del ISR (SPI_STC_vect) void loop (void) { if (recibido) { buf [pos] = 0; Serial.println (buf); pos = 0; recibido = false; } } // FIN del void loop (void) Finalmente pasamos el programa a cada placa con las conexiones descriptas arriba y si conectamos por USB el Slave solamente, podemos ver el mensaje recibido por SPI. Tener en cuenta las conexiones de MISO y MOSI ya que los cables van con la misma nomenclatura y no cruzados, es decir MISO con MISO y MOSI con MOSI. No olvidar el cable de tierra. 4 Esta es la salida Serial del Slave, con el programa mostrado. En caso de que crean que pueden tener problemas con SPI.h, la librería está en el archivo ZIP. (Yo los tuve) 5 6