Jak korzystać z SPI na Arduino?


Odpowiedzi:


80

Wprowadzenie do SPI

Interfejs szeregowej magistrali interfejsu peryferyjnego (SPI) służy do komunikacji między wieloma urządzeniami na krótkich dystansach i z dużą prędkością.

Zwykle jest to jedno „urządzenie nadrzędne”, które inicjuje komunikację i dostarcza zegar sterujący szybkością przesyłania danych. Może być jeden lub więcej niewolników. W przypadku więcej niż jednego urządzenia podrzędnego każdy ma własny sygnał „wyboru urządzenia podrzędnego”, opisany później.


Sygnały SPI

W pełnym systemie SPI będziesz mieć cztery linie sygnałowe:

  • Master Out, Slave In ( MOSI ) - czyli dane przesyłane z mastera do slave
  • Master In, Slave Out ( MISO ) - czyli dane przesyłane z slave do master
  • Zegar szeregowy ( SCK ) - kiedy to przełącza próbkę master i slave w następnym bicie
  • Slave Select ( SS ) - informuje określonego niewolnika, aby przejść na „aktywny”

Kiedy do urządzenia MISO podłączonych jest wiele urządzeń podrzędnych, oczekuje się, że potróją (utrzymują wysoką impedancję) tę linię MISO, dopóki nie zostaną wybrane przez potwierdzenie Slave Select. Normalnie Slave Select (SS) przechodzi w stan niski, aby go potwierdzić. Oznacza to, że jest niski. Po wybraniu określonego urządzenia podrzędnego powinien on skonfigurować linię MISO jako wyjście, aby mógł wysyłać dane do urządzenia nadrzędnego.

Ten obraz pokazuje sposób wymiany danych podczas wysyłania jednego bajtu:

Protokół SPI pokazujący 4 sygnały

Zauważ, że trzy sygnały są wyjściami z urządzenia nadrzędnego (MOSI, SCK, SS), a jeden to wejście (MISO).


wyczucie czasu

Sekwencja zdarzeń jest następująca:

  • SS idzie nisko, aby to potwierdzić i aktywować niewolnika
  • SCKLinia przełącza się wskazywać, kiedy linie danych należy pobrać próbki
  • Dane są próbkowane zarówno przez urządzenie nadrzędne, jak i podrzędne na zboczu wiodącymSCK (przy użyciu domyślnej fazy zegara)
  • Zarówno master, jak i slave przygotowują się do następnego bitu na końcowej krawędzi SCK(używając domyślnej fazy zegara), zmieniając MISO/ w MOSIrazie potrzeby
  • Po zakończeniu transmisji (być może po wysłaniu wielu bajtów) następuje przejście SSdo stanu wysokiego, aby anulować potwierdzenie

Uwaga:

  • Najpoważniejszy bit jest wysyłany jako pierwszy (domyślnie)
  • Dane są wysyłane i odbierane w tym samym momencie (pełny dupleks)

Ponieważ dane są wysyłane i odbierane w tym samym impulsie zegarowym, urządzenie podrzędne nie może natychmiast zareagować na urządzenie nadrzędne. Protokoły SPI zwykle oczekują, że master zażąda danych podczas jednej transmisji i otrzyma odpowiedź na kolejną.

Korzystając z biblioteki SPI na Arduino, pojedynczy transfer wygląda tak:

 byte outgoing = 0xAB;
 byte incoming = SPI.transfer (outgoing);

Przykładowy kod

Przykład tylko wysyłania (ignorowanie jakichkolwiek przychodzących danych):

#include <SPI.h>

void setup (void)
  {
  digitalWrite(SS, HIGH);  // ensure SS stays high
  SPI.begin ();
  } // end of setup

void loop (void)
  {
  byte c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Fab" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (100);
  } // end of loop

Okablowanie dla SPI tylko wyjściowego

Powyższy kod (który wysyła tylko) może być użyty do sterowania wyjściowym szeregowym rejestrem przesuwnym. Są to urządzenia tylko wyjściowe, więc nie musimy się martwić o przychodzące dane. W ich przypadku pin SS może być nazywany pinem „store” lub „zatrzask”.

Protokół SPI pokazujący 3 sygnały

Przykładem tego jest szeregowy rejestr przesuwny 74HC595 i różne paski LED, żeby wymienić tylko kilka. Na przykład ten 64-pikselowy wyświetlacz LED napędzany przez układ MAX7219:

64-pikselowy wyświetlacz LED

W tym przypadku widać, że twórca płyty użył nieco innych nazw sygnałów:

  • DIN (Data In) to MOSI (Master Out, Slave In)
  • CS (Chip Select) to SS (Slave Select)
  • CLK (zegar) to SCK (zegar szeregowy)

Większość desek będzie miała podobny wzór. Czasami DIN to po prostu DI (Data In).

Oto kolejny przykład, tym razem 7-segmentowy wyświetlacz LED (również oparty na układzie MAX7219):

7-segmentowy wyświetlacz LED

Używa dokładnie takich samych nazw sygnałów, jak na drugiej płycie. W obu tych przypadkach widać, że płytka potrzebuje tylko 5 przewodów, trzy do SPI, plus moc i uziemienie.


Faza zegara i polaryzacja

Istnieją cztery sposoby próbkowania zegara SPI.

Protokół SPI pozwala na zmianę polaryzacji impulsów zegara. CPOL jest polaryzacją zegara, a CPHA jest fazą zegara.

  • Tryb 0 (domyślny) - zegar jest normalnie niski (CPOL = 0), a dane są próbkowane przy przejściu z niskiego do wysokiego (krawędź wiodąca) (CPHA = 0)
  • Tryb 1 - zegar jest normalnie niski (CPOL = 0), a dane są próbkowane przy przejściu z wysokiego na niski (zbocze opadające) (CPHA = 1)
  • Tryb 2 - zegar jest zwykle wysoki (CPOL = 1), a dane są próbkowane przy przejściu z wysokiego do niskiego (zbocze wiodące) (CPHA = 0)
  • Tryb 3 - zegar jest normalnie wysoki (CPOL = 1), a dane są próbkowane przy przejściu od niskiego do wysokiego (zbocze opadające) (CPHA = 1)

Są one zilustrowane na tej grafice:

Faza i polaryzacja zegara SPI

Aby uzyskać prawidłową fazę i polaryzację, należy zapoznać się z arkuszem danych urządzenia. Zwykle jest schemat pokazujący, jak próbkować zegar. Na przykład z arkusza danych dla układu 74HC595:

Zegar 74HC595

Jak widać zegar jest normalnie niski (CPOL = 0) i jest próbkowany na zboczu wiodącym (CPHA = 0), więc jest to tryb SPI 0.

Możesz zmienić polaryzację zegara i fazę w kodzie w ten sposób (oczywiście wybierz tylko jedną):

SPI.setDataMode (SPI_MODE0);
SPI.setDataMode (SPI_MODE1);
SPI.setDataMode (SPI_MODE2);
SPI.setDataMode (SPI_MODE3);

Ta metoda jest przestarzała w wersjach 1.6.0 Arduino IDE. W przypadku najnowszych wersji zmieniasz tryb zegara w SPI.beginTransactionrozmowie, w ten sposób:

SPI.beginTransaction (SPISettings (2000000, MSBFIRST, SPI_MODE0));  // 2 MHz clock, MSB first, mode 0

Kolejność danych

Domyślnie jest to bit najbardziej znaczący jako pierwszy, jednak można powiedzieć sprzętowi, aby najpierw przetworzył bit o najmniejszym znaczeniu:

SPI.setBitOrder (LSBFIRST);   // least significant bit first
SPI.setBitOrder (MSBFIRST);   // most significant bit first

Ponownie jest to przestarzałe w wersjach 1.6.0 Arduino IDE. W przypadku najnowszych wersji zmieniasz kolejność bitów w SPI.beginTransactionwywołaniu, w następujący sposób:

SPI.beginTransaction (SPISettings (1000000, LSBFIRST, SPI_MODE2));  // 1 MHz clock, LSB first, mode 2

Prędkość

Domyślnym ustawieniem dla SPI jest użycie szybkości zegara systemowego podzielonej przez cztery, to znaczy jeden impuls zegarowy SPI co 250 ns, przy założeniu zegara procesora 16 MHz. Możesz zmienić dzielnik zegara, używając setClockDividernastępującego sposobu:

SPI.setClockDivider (divider);

Gdzie „dzielnik” jest jednym z:

  • SPI_CLOCK_DIV2
  • SPI_CLOCK_DIV4
  • SPI_CLOCK_DIV8
  • SPI_CLOCK_DIV16
  • SPI_CLOCK_DIV32
  • SPI_CLOCK_DIV64
  • SPI_CLOCK_DIV128

Najszybsza szybkość to „dzielenie przez 2” lub jeden impuls zegarowy SPI co 125 ns, przy założeniu zegara procesora 16 MHz. W związku z tym przesłanie jednego bajtu wymagałoby 8 * 125 ns lub 1 µs.

Ta metoda jest przestarzała w wersjach 1.6.0 Arduino IDE. W przypadku najnowszych wersji zmieniasz szybkość przesyłania w SPI.beginTransactionrozmowie, w ten sposób:

SPI.beginTransaction (SPISettings (4000000, MSBFIRST, SPI_MODE0));  // 4 MHz clock, MSB first, mode 0

Jednak testy empiryczne pokazują, że konieczne jest posiadanie dwóch impulsów zegarowych między bajtami, więc maksymalna szybkość, z jaką bajty mogą zostać wyrejestrowane, wynosi 1,125 µs każdy (z dzielnikiem zegara 2).

Podsumowując, każdy bajt może być wysyłany z maksymalną szybkością 1 na 1,125 µs (z zegarem 16 MHz), co daje teoretyczną maksymalną szybkość transferu 1 / 1,125 µs lub 888,888 bajtów na sekundę (z wyłączeniem narzutu, jak ustawienie niskiego SS i tak dalej na).


Łączenie z Arduino

Arduino Uno

Podłączanie za pomocą pinów cyfrowych 10 do 13:

Piny Arduino Uno SPI

Łączenie za pomocą nagłówka ICSP:

Pinouty ICSP - Uno

Nagłówek ICSP

Arduino Atmega2560

Podłączanie za pomocą pinów cyfrowych od 50 do 52:

Piny Arduino Mega2560 SPI

Możesz także użyć nagłówka ICSP, podobnego do powyższego Uno.

Arduino Leonardo

Leonardo i Micro nie odsłaniają pinów SPI na pinach cyfrowych, w przeciwieństwie do Uno i Mega. Jedyną opcją jest użycie pinów nagłówka ICSP, jak pokazano powyżej dla Uno.


Wielu niewolników

Mistrz może komunikować się z wieloma niewolnikami (jednak tylko jednym naraz). Robi to, zapewniając SS jednemu niewolnikowi i odznaczając go dla wszystkich pozostałych. Slave, który potwierdził SS (zwykle oznacza to LOW) konfiguruje swój pin MISO jako wyjście, aby slave i ten slave sam mogli odpowiedzieć na master. Inni niewolnicy ignorują wszelkie przychodzące impulsy zegara, jeśli SS nie jest zapewnione. Dlatego potrzebujesz jednego dodatkowego sygnału dla każdego urządzenia podrzędnego, takiego jak ten:

Wiele urządzeń podrzędnych SPI

Na tej grafice widać, że MISO, MOSI, SCK są współużytkowane przez oba urządzenia podrzędne, jednak każde urządzenie podrzędne ma własny sygnał SS (wybór urządzenia podrzędnego).


Protokoły

Specyfikacja SPI nie określa protokołów jako takich, więc ustalenie znaczenia danych zależy od indywidualnych par master / slave. Chociaż możesz wysyłać i odbierać bajty jednocześnie, odebrany bajt nie może być bezpośrednią odpowiedzią na wysłany bajt (ponieważ są one składane jednocześnie).

Byłoby więc bardziej logiczne, aby jeden koniec wysłał żądanie (np. 4 może oznaczać „wylistuj katalog dysku”), a następnie wykonać transfery (być może po prostu wysyłając zera na zewnątrz), aż otrzyma pełną odpowiedź. Odpowiedź może zakończyć się znakiem nowej linii lub znakiem 0x00.

Przeczytaj arkusz danych dla urządzenia slave, aby zobaczyć, jakich sekwencji protokołów oczekuje.


Jak zrobić SPI slave

Wcześniejszy przykład pokazuje Arduino jako urządzenie nadrzędne, wysyłające dane do urządzenia podrzędnego. Ten przykład pokazuje, jak Arduino może być niewolnikiem.

Konfiguracja sprzętu

Połącz dwa Arduino Unos razem z następującymi pinami połączonymi ze sobą:

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

  • + 5 V (jeśli wymagane)

  • GND (dla powrotu sygnału)

W Arduino Mega piny to 50 (MISO), 51 (MOSI), 52 (SCK) i 53 (SS).

W każdym razie MOSI na jednym końcu jest podłączony do MOSI na drugim, nie zamieniasz ich (to znaczy, że nie masz MOSI <-> MISO). Oprogramowanie konfiguruje jeden koniec MOSI (koniec master) jako wyjście, a drugi koniec (koniec slave) jako wejście.

Przykład wzorcowy

#include <SPI.h>

void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // end of setup


void loop (void)
{

  char c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Hello, world!\n" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay
}  // end of loop

Przykład niewolnika

#include <SPI.h>

char buf [100];
volatile byte pos;
volatile bool process_it;

void setup (void)
{
  Serial.begin (115200);   // debugging

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode (MISO, OUTPUT);

  // get ready for an interrupt
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos < sizeof buf)
    {
    buf [pos++] = c;

    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;

    }  // end of room available
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set

}  // end of loop

Niewolnik jest całkowicie sterowany przerwaniami, więc może robić inne rzeczy. Przychodzące dane SPI są gromadzone w buforze i ustawiana flaga, gdy nadejdzie „znaczący bajt” (w tym przypadku nowa linia). To mówi slave'owi, aby wszedł i zaczął przetwarzać dane.

Przykład podłączenia Master do Slave za pomocą SPI

Arduino SPI master i slave


Jak uzyskać odpowiedź od niewolnika

Kontynuując powyższy kod, który wysyła dane z Master SPI do Slave, poniższy przykład pokazuje wysyłanie danych do Slave, każąc mu coś z tym zrobić i zwrócić odpowiedź.

Mistrz jest podobny do powyższego przykładu. Ważną kwestią jest jednak to, że musimy dodać niewielkie opóźnienie (około 20 mikrosekund). W przeciwnym razie urządzenie podrzędne nie ma szansy zareagować na przychodzące dane i coś z tym zrobić.

Przykład pokazuje wysłanie „polecenia”. W tym przypadku „a” (dodaj coś) lub „s” (odejmij coś). Ma to pokazać, że slave faktycznie robi coś z danymi.

Po potwierdzeniu wyboru slave (SS) w celu zainicjowania transakcji, master wysyła polecenie, a następnie dowolną liczbę bajtów, a następnie podnosi SS, aby zakończyć transakcję.

Bardzo ważną kwestią jest to, że niewolnik nie może odpowiedzieć na nadchodzący bajt w tym samym momencie. Odpowiedź musi być w następnym bajcie. Wynika to z faktu, że wysyłane bity i odbierane bity są wysyłane jednocześnie. Aby dodać coś do czterech liczb, potrzebujemy pięciu przelewów, takich jak to:

transferAndWait ('a');  // add command
transferAndWait (10);
a = transferAndWait (17);
b = transferAndWait (33);
c = transferAndWait (42);
d = transferAndWait (0);

Najpierw prosimy o działanie na numer 10. Ale nie otrzymujemy odpowiedzi do następnego przelewu (ten dla 17). Jednak „a” zostanie ustawione na odpowiedź na 10. W końcu wysyłamy „manekina” numer 0, aby uzyskać odpowiedź za 42.

Master (przykład)

  #include <SPI.h>

  void setup (void)
    {
    Serial.begin (115200);
    Serial.println ();

    digitalWrite(SS, HIGH);  // ensure SS stays high for now
    SPI.begin ();

    // Slow down the master a bit
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    }  // end of setup

  byte transferAndWait (const byte what)
    {
    byte a = SPI.transfer (what);
    delayMicroseconds (20);
    return a;
    } // end of transferAndWait

  void loop (void)
    {

    byte a, b, c, d;

    // enable Slave Select
    digitalWrite(SS, LOW);

    transferAndWait ('a');  // add command
    transferAndWait (10);
    a = transferAndWait (17);
    b = transferAndWait (33);
    c = transferAndWait (42);
    d = transferAndWait (0);

    // disable Slave Select
    digitalWrite(SS, HIGH);

    Serial.println ("Adding results:");
    Serial.println (a, DEC);
    Serial.println (b, DEC);
    Serial.println (c, DEC);
    Serial.println (d, DEC);

    // enable Slave Select
    digitalWrite(SS, LOW);

    transferAndWait ('s');  // subtract command
    transferAndWait (10);
    a = transferAndWait (17);
    b = transferAndWait (33);
    c = transferAndWait (42);
    d = transferAndWait (0);

    // disable Slave Select
    digitalWrite(SS, HIGH);

    Serial.println ("Subtracting results:");
    Serial.println (a, DEC);
    Serial.println (b, DEC);
    Serial.println (c, DEC);
    Serial.println (d, DEC);

    delay (1000);  // 1 second delay
    }  // end of loop

Kod dla urządzenia podrzędnego w zasadzie robi prawie wszystko w procedurze przerwania (wywoływanej, gdy nadchodzą przychodzące dane SPI). Pobiera przychodzący bajt i dodaje lub odejmuje zgodnie z zapamiętanym „bajtem polecenia”. Zauważ, że odpowiedź zostanie „zebrana” następnym razem przez pętlę. Dlatego mistrz musi wysłać jeden końcowy „fałszywy” transfer, aby uzyskać ostateczną odpowiedź.

W moim przykładzie używam pętli głównej, aby po prostu wykryć, kiedy SS idzie w górę, i wyczyścić zapisane polecenie. W ten sposób, gdy SS ponownie zostanie obniżone do następnej transakcji, pierwszy bajt jest uważany za bajt polecenia.

Bardziej niezawodnie można to zrobić z przerwą. Oznacza to, że fizycznie podłączysz SS do jednego z wejść przerwań (np. Na Uno, podłączysz pin 10 (SS) do pinu 2 (wejście przerwania) lub użyjesz przerwania zmiany pin na pinie 10.

Następnie przerwanie może być wykorzystane do zauważenia, kiedy SS jest ściągane na niskie lub wysokie.

Slave (przykład)

// what to do with incoming data
volatile byte command = 0;

void setup (void)
  {

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  }  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
  {
  byte c = SPDR;

  switch (command)
    {
    // no command? then this is the command
    case 0:
      command = c;
      SPDR = 0;
      break;

    // add to incoming byte, return result
    case 'a':
      SPDR = c + 15;  // add 15
      break;

    // subtract from incoming byte, return result
    case 's':
      SPDR = c - 8;  // subtract 8
      break;

    } // end of switch

  }  // end of interrupt service routine (ISR) SPI_STC_vect

void loop (void)
  {

  // if SPI not active, clear current command
  if (digitalRead (SS) == HIGH)
    command = 0;
  }  // end of loop

Przykładowe dane wyjściowe

Adding results:
25
32
48
57
Subtracting results:
2
9
25
34
Adding results:
25
32
48
57
Subtracting results:
2
9
25
34

Wyjście analizatora logicznego

To pokazuje czas pomiędzy wysłaniem a odbiorem w powyższym kodzie:

Czasy główne i podrzędne SPI


Nowa funkcjonalność w IDE 1.6.0 i nowszych

Wersja 1.6.0 IDE do pewnego stopnia zmieniła sposób działania SPI. Państwo nadal trzeba zrobić SPI.begin() przed użyciem SPI. To konfiguruje sprzęt SPI. Jednak teraz, kiedy masz zamiar zacząć komunikować się z niewolnika Państwo również zrobić SPI.beginTransaction(), aby skonfigurować SPI (w tym slave) z popraw:

  • Szybkośc zegara
  • Zamówienie bitowe
  • Faza zegara i polaryzacja

Kiedy skończysz komunikować się z niewolnikiem, zadzwonisz SPI.endTransaction(). Na przykład:

SPI.beginTransaction (SPISettings (2000000, MSBFIRST, SPI_MODE0));
digitalWrite (SS, LOW);        // assert Slave Select
byte foo = SPI.transfer (42);  // do a transfer
digitalWrite (SS, HIGH);       // de-assert Slave Select
SPI.endTransaction ();         // transaction over

Dlaczego warto korzystać z SPI?

Dodałbym jedno wstępne pytanie: kiedy / dlaczego miałbyś używać SPI? Potrzeba konfiguracji multi-master lub bardzo dużej liczby slaveów przechyliłaby skalę w kierunku I2C.

To doskonałe pytanie. Moje odpowiedzi to:

  • Niektóre urządzenia (całkiem sporo) obsługują tylko metodę przesyłania SPI. Na przykład rejestr przesuwny wyjściowy 74HC595, rejestr przesuwny wejściowy 74HC165, sterownik LED MAX7219 i całkiem sporo pasków LED, które widziałem. Możesz go użyć, ponieważ urządzenie docelowe obsługuje go tylko.
  • SPI jest naprawdę najszybszą metodą dostępną na chipach Atmega328 (i podobnych). Najszybsza podana szybkość to 888,888 bajtów na sekundę. Używając I 2 C, możesz uzyskać tylko około 40 000 bajtów na sekundę. Obciążenie I 2 C jest dość znaczne, a jeśli próbujesz naprawdę szybko interfejsować, SPI jest preferowanym wyborem. Dość kilka rodzin układów (np. MCP23017 i MCP23S17) faktycznie obsługuje zarówno I 2 C, jak i SPI, więc często możesz wybierać między szybkością a możliwością posiadania wielu urządzeń na jednej magistrali.
  • Urządzenia SPI i I 2 C są obsługiwane sprzętowo w Atmega328, więc możliwe jest, że możesz przesyłać dane przez SPI jednocześnie z I 2 C, co dałoby ci przyspieszenie.

Obie metody mają swoje miejsce. I 2 C pozwala podłączyć wiele urządzeń do jednej magistrali (dwa przewody plus uziemienie), więc byłby to preferowany wybór, gdybyś potrzebował przesłuchać znaczną liczbę urządzeń, być może dość rzadko. Jednak szybkość SPI może być bardziej istotna w sytuacjach, w których trzeba szybko wysyłać dane (np. Pasek LED) lub szybko (np. Konwerter ADC).


Bibliografia


Czy zamierzasz opisać dziwność, jaką jest SPI Due? Gdzie konfiguracja portu SPI jest powiązana z zastosowanym stykiem SS, a do portu SPI przypisane są 4 sprzętowe szpilki SS?
Majenko

Inna kwestia dotycząca wyboru: czasami naprawdę nie masz wyboru, ponieważ czujnik, którego chcesz / musisz użyć, jest dostępny tylko jako I2C.
Igor Stoppa

Are you going to cover the weirdness that is the Due's SPI?- Nic nie wiem o interfejsie SP Due (oprócz założenia, że ​​ogólny protokół jest taki sam). Możesz dodać odpowiedź dotyczącą tego aspektu.
Nick Gammon

Kiedy pojawi się audiobook z odpowiedzią i czy sam ją przeczytasz;)
AMADANON Inc.

1
@AMADANONInc. Być może teledysk? Lub animacja? Nie jestem pewien, czy mój australijski akcent byłby zrozumiały. : P
Nick Gammon
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.