Arduino - szeregowy interfejs peryferyjny

Magistrala Serial Peripheral Interface (SPI) to system komunikacji szeregowej, który wykorzystuje do czterech przewodów, zwykle trzech. Jeden przewodnik służy do odbierania danych, jeden do wysyłania danych, jeden do synchronizacji, a drugi do wyboru urządzenia do komunikacji. Jest to połączenie typu full duplex, co oznacza, że ​​dane są wysyłane i odbierane jednocześnie. Maksymalna prędkość transmisji jest wyższa niż w systemie komunikacji I2C.

Piny tablicy SPI

SPI wykorzystuje następujące cztery przewody -

  • SCK - To jest zegar szeregowy sterowany przez mastera.

  • MOSI - To jest wyjście master / wejście slave sterowane przez master.

  • MISO - To jest wejście master / wyjście slave sterowane przez master.

  • SS - To jest przewód wyboru urządzenia podrzędnego.

Używane są następujące funkcje. Musisz dołączyć SPI.h.

  • SPI.begin() - Inicjuje magistralę SPI, ustawiając SCK, MOSI i SS na wyjściach, wyciągając SCK i MOSI w stan niski i wysoki SS.

  • SPI.setClockDivider(divider)- Aby ustawić dzielnik zegara SPI względem zegara systemowego. Na płytach opartych na AVR dostępne są dzielniki 2, 4, 8, 16, 32, 64 lub 128. Domyślne ustawienie to SPI_CLOCK_DIV4, które ustawia zegar SPI na jedną czwartą częstotliwości zegara systemowego (5 MHz dla płyty przy 20 MHz).

  • Divider - Może to być (SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128).

  • SPI.transfer(val) - Transfer SPI opiera się na jednoczesnym wysyłaniu i odbieraniu: odebrane dane są zwracane w formacie receivedVal.

  • SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) - speedMaximum to zegar, dataOrder (MSBFIRST lub LSBFIRST), dataMode (SPI_MODE0, SPI_MODE1, SPI_MODE2 lub SPI_MODE3).

Mamy cztery tryby pracy w SPI w następujący sposób -

  • Mode 0 (the default) - Zegar jest zwykle niski (CPOL = 0), a dane są próbkowane przy przejściu od niskiego do wysokiego (zbocze narastające) (CPHA = 0).

  • Mode 1 - Zegar jest normalnie niski (CPOL = 0), a dane są próbkowane przy przejściu od wysokiego do niskiego (zbocze opadające) (CPHA = 1).

  • Mode 2 - Zegar jest zwykle wysoki (CPOL = 1), a dane są próbkowane przy przejściu od wysokiego do niskiego (zbocze narastające) (CPHA = 0).

  • Mode 3 - Zegar jest zwykle wysoki (CPOL = 1), a dane są próbkowane przy przejściu od niskiego do wysokiego (zbocze opadające) (CPHA = 1).

  • SPI.attachInterrupt(handler) - Funkcja wywoływana, gdy urządzenie slave otrzymuje dane od mastera.

Teraz połączymy ze sobą dwie płyty Arduino UNO; jeden jako pan, a drugi jako niewolnik.

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

Ziemia jest wspólna. Poniżej znajduje się schematyczne przedstawienie połączenia między obiema płytami -

Zobaczmy przykłady SPI jako Master i SPI jako Slave.

SPI jako MASTER

Przykład

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

Przykład

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