Arduino - Interface Periférica Serial

Um barramento de interface periférica serial (SPI) é um sistema para comunicação serial, que usa até quatro condutores, geralmente três. Um condutor é usado para receber dados, um para enviar dados, um para sincronização e um alternativamente para selecionar um dispositivo com o qual se comunicar. É uma conexão full duplex, o que significa que os dados são enviados e recebidos simultaneamente. A taxa de transmissão máxima é maior do que no sistema de comunicação I2C.

Pinos SPI da placa

SPI usa os seguintes quatro fios -

  • SCK - Este é o relógio serial acionado pelo mestre.

  • MOSI - Esta é a saída mestre / entrada escrava controlada pelo mestre.

  • MISO - Esta é a entrada mestre / saída escrava conduzida pelo mestre.

  • SS - Este é o fio de seleção do escravo.

As seguintes funções são usadas. Você tem que incluir o SPI.h.

  • SPI.begin() - Inicializa o barramento SPI configurando SCK, MOSI e SS para as saídas, puxando SCK e MOSI para baixo e SS para alto.

  • SPI.setClockDivider(divider)- Para definir o divisor de relógio SPI em relação ao relógio do sistema. Em placas baseadas em AVR, os divisores disponíveis são 2, 4, 8, 16, 32, 64 ou 128. A configuração padrão é SPI_CLOCK_DIV4, que define o relógio SPI para um quarto da frequência do relógio do sistema (5 Mhz para placas a 20 MHz).

  • Divider - Pode 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) - A transferência SPI é baseada em um envio e recebimento simultâneos: os dados recebidos são retornados em receivedVal.

  • SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) - speedMaximum é o relógio, dataOrder (MSBFIRST ou LSBFIRST), dataMode (SPI_MODE0, SPI_MODE1, SPI_MODE2 ou SPI_MODE3).

Temos quatro modos de operação no SPI como segue -

  • Mode 0 (the default) - O relógio é normalmente baixo (CPOL = 0) e os dados são amostrados na transição de baixo para alto (borda de ataque) (CPHA = 0).

  • Mode 1 - O relógio é normalmente baixo (CPOL = 0) e os dados são amostrados na transição de alto para baixo (borda de fuga) (CPHA = 1).

  • Mode 2 - O clock é normalmente alto (CPOL = 1) e os dados são amostrados na transição de alto para baixo (borda de ataque) (CPHA = 0).

  • Mode 3 - O clock é normalmente alto (CPOL = 1) e os dados são amostrados na transição de baixo para alto (borda de fuga) (CPHA = 1).

  • SPI.attachInterrupt(handler) - Função a ser chamada quando um dispositivo escravo recebe dados do mestre.

Agora, conectaremos duas placas Arduino UNO; um como mestre e o outro como escravo.

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

O terreno é comum. A seguir está a representação esquemática da conexão entre as duas placas -

Vejamos exemplos de SPI como Master e SPI como Slave.

SPI como MASTER

Exemplo

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

Exemplo

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