Serial Peripheral Interface (SPI) został opracowany przez Motorolę, aby umożliwić jej chipy komunikować się ze sobą, podobnie jak Philips opracował magistralę szeregową I2C dla własnych układów scalonych. Podczas gdy te dwie magistrale wykonują w dużej mierze tę samą pracę, obie stały się prawie równie powszechne, a wiele urządzeń peryferyjnych używa jednego lub drugiego do komunikacji z mikrokontrolerem hosta. Ta wszechobecność jest powodem, dla którego chochliki wspierają ich oboje.
SPI ma pewne zalety w stosunku do I2C, w szczególności obsługę wyższej szybkości transferu danych., SPI ma również funkcję dupleksu, co sprawia, że jest szczególnie odpowiedni dla tych aplikacji, które wymagają jednoczesnej dwukierunkowej komunikacji.
z drugiej strony SPI wymaga co najmniej trzech przewodów, współdzielonych przez wszystkie urządzenia na magistrali, oraz szeregu linii wyboru urządzeń, po jednej dla każdego urządzenia peryferyjnego podłączonego do urządzenia sterującego. Natomiast I2C wymaga tylko dwóch przewodów; wykorzystuje unikalne adresy do identyfikacji wszystkich urządzeń na magistrali., To sprawia, że praca z wieloma urządzeniami jest prostsza niż podejście bez adresu SPI, chociaż niektórzy programiści wolą używać sprzętu do wyboru urządzenia, a nie danych adresowych.
kontrolery i urządzenia peryferyjne
SPI dzieli urządzenia na „kontrolery” i „urządzenia peryferyjne”. Tylko jedno urządzenie może wysyłać impulsy czasowe w celu synchronizacji transferów danych, a to jest ten wybrany jako kontroler. Wszystkie pozostałe, które synchronizują swoje timingi ze sterownikiem, są uważane za pomocnicze urządzenia peryferyjne., Kontroler-który w Twoim produkcie Musi być obecnie jego imp – i jego urządzenia peryferyjne mogą Wszystkie transmitować i odbierać dane, ale tylko kontroler może ustalić wzór taktowania, do którego wszystkie działają. To ustanowienie stałego schematu rozrządu sprawia, że SPI, podobnie jak I2C, jest magistralą „synchroniczną”.
fizyczna Magistrala
implementacja SPI imp ma cztery linie:
- SCLK, szeregowy sygnał zegara z kontrolera.
- COPI, skrót od 'Controller Out, Peripherical In' (czasami oznaczany MOSI w starych arkuszach danych).,
- CIPO, skrót od „Controller In, Peripheral Out” (czasami oznaczany jako MISO).
- CS, skrót od 'Chip Select' (czasami oznaczany jako SS, nSS lub SYNC)
COPI i CIPO są liniami transmisji danych.
imp001 i imp002 nie zapewniają dedykowanych pinów CS: zamiast tego możesz użyć dowolnego z tych imp innych pinów GPIO. Imp003 i nowsze zapewniają dedykowane piny CS jako część ich autobusów SPI, oznaczonych na stronie Imp pin mux.
Uwaga imp005 zapewnia dedykowany Chip select pin na każdej z dwóch magistrali SPI. Dla spiBCAD jest to pin D; dla spi0 jest to pin CS0., The Imp API metoda chipselect () móc używać the assertion i De-assertion te chip select Szpilki (proszę widzieć The metoda dokumentacja dla więcej informacja).
SPI na imp: maksymalnie cztery linie łączą się z jednym urządzeniem peryferyjnym
to podejście jest zgodne z definicją SPI Motorola: że każda transakcja magistrali — zasadniczo partia bajtów danych — powinny być połączone do określonego urządzenia peryferyjnego., Texas Instruments zmodyfikował specyfikację SPI, aby umożliwić wysyłanie każdego bajtu do określonego urządzenia peryferyjnego, choć wymaga to dedykowanej linii CS. Ten tryb nie jest obecnie obsługiwany przez żadną imp.
Sygnalizacja
zakładając, że do kontrolera podłączony jest pojedynczy Obwód, komunikacja inicjowana jest przez kontroler ciągnący linię CS nisko. Mówi peryferii, aby przygotować się do rozmowy. Teraz kontroler zaczyna wysyłać impulsy zegarowe wzdłuż linii SCLK; zazwyczaj transmisje danych są kierowane do rosnącej krawędzi każdego impulsu, choć nie zawsze tak jest.,
Taktowanie danych in and out: the imp wysyła polecenie, the peripheral returns data
the controller will now transmitted data on the Copi line, Active driving the line high to signal a 1 or low for a 0. Urządzenie peryferyjne odczyta sygnał — co może być na przykład poleceniem do wysłania odczytu czujnika — i zwróci tę informację na linii CIPO, ponownie kierując linię, aby pozostać wysoko, aby sygnalizować 1 lub kierując ją nisko, aby przesłać 0., Wymaganie, aby linia była aktywnie napędzana wysoko lub nisko, a raczej pozwalając jej osiąść do jednego lub drugiego stanu poprzez podłączenie rezystora, jest powodem, dla którego SPI może obsługiwać wyższe prędkości niż I2C. I2C traci czas transmisji, podczas gdy jego rezystor pull-up przywraca linię do wysokiej wartości.
To powiedziawszy, jest to jednak dobra praktyka, aby mieć podciąganie na linii CS, aby zapewnić, że idzie wysoko, gdy imp jest uruchamiany lub śpi, a zatem nie jest w stanie prowadzić linii ręcznie. Utrzymanie wysokiej linii zapewnia, że Peryferia zignorują wszelkie usterki na liniach danych i zegarów.,
gdy kontroler ma to, czego chce, raz jeszcze napędza linię CS wysoko, a Peryferia mogą odpocząć.
opcje IMP SPI
każdy imp ma szereg niezależnych szyn SPI, dostępnych jako właściwości obiektu sprzętowego urządzenia, który jest inicjowany przy starcie. Każdy Imp ' s pin MUX table pokazuje, że istnieje wiele opcji, w zależności od tego, jakiego typu imp używasz w swoim produkcie. Ten dokument zakłada, że używasz imp001, więc powinieneś skonsultować się z tabelą pin mux, jeśli pracujesz z innym imp., Dwie magistrale SPI imp001 są zarówno trójprzewodowymi implementacjami magistrali, jak i podłączonymi odpowiednio do pinów 1, 8 i 9 oraz 2, 5 i 7. Piny 1 i 5 to SCLK; 8 i 7 COPI; oraz 9 i 2 CIPO. Niezależnie od tego, z których dwóch autobusów korzystasz, dobrą praktyką jest aliasowanie go na początku:
spi1 <- hardware.spi257;spi2 <- hardware.spi189;
Konfigurowanie obu do użycia jest po prostu kwestią poinformowania imp, jak szybko chcesz, aby autobus działał, i dostarczenie zestawu stałych, które razem określają, jak autobus będzie działał:
spi1.configure(modeFlags, speed);
Po pierwsze, prędkość., This is simply an integer value giving the throughput in kiloHertz (kHz):
The specific SPI data rates available (in kHz) are as follows:
imp001, imp002 | imp003 | imp004m | imp005 | imp006 | |
spi189 | spi257 | spiEBCA spiLGDK |
spiAHSR spiGJKL |
spiBCAD spi0 |
spiXTUVW |
15,000 | 30,000 | 18,000 | 24,000 | The SPI data rates available range from 5KHz to 22.,8MHz The SPI is clocked by dividing 160MHz by any integer from 7 to 32,000 inclusive |
Min. 187KHz, max. 750KHz |
7500 | 15,000 | 9000 | 12,000 | ||
3750 | 7500 | 4500 | 6000 | ||
1875 | 3750 | 2250 | 3000 | All others | |
937.50 | 1875 | 1125 | 1500 | Min. 187KHz, theoretical max. 24MHz |
|
468.75 | 937.50 | 562.50 | 750 | ||
234.,375 | 468.75 | 281.25 | 375 | ||
117.1875 | 234.375 | 140.,g) edge | |||
Msb_first | Wyślij najpierw najbardziej znaczący bit (domyślnie) | ||||
najpierw Wyślij najmniej znaczący bit | |||||
no_sclk | pin SCLK nie jest używany | ||||
use_cs_l | włącz użycie dedykowanego pinu Chip select (tylko imp005) |
można je łączyć, jeśli potrzebujesz, używając logicznego lub operatora,|
, choć niektóre wzajemnie się wykluczają, więc nie należy ich łączyć: na przykład simplex_tx i simplex_rx., Aby na przykład użyć zarówno CLOCK_IDLE_LOW, jak i CLOCK_2ND_EDGE, zamiast wprowadzać pojedynczą stałą jako parametr w metodzie configure (), należy podać obie, oddzielone symbolem |
:
spi1.configure(SIMPLEX_TX | MSB_FIRST | CLOCK_IDLE_LOW, 400);
kombinacje mogą być konieczne, jeśli są określone przez arkusz danych peryferyjnych, chociaż może to nie być natychmiast oczywiste dla użytkownika.nowicjusz. Arkusze danych mogą mówić o „trybie SPI” urządzenia lub jego wartościach CPOL (Polaryzacja zegara) i CPHA (Faza zegara)., CPOL i CPHA określają, które krawędzie sygnału zegara są używane do napędu i próbkowania sygnałów danych. Każdy z tych dwóch parametrów ma dwa możliwe Stany, dla wszystkich czterech możliwych kombinacji:
tryby SPI
tryby SPI po prostu indeksują te kombinacje, a nie oddzielne wartości CPOL i CPHA. Sterownik i peryferia muszą komunikować się przy użyciu tych samych wartości CPOL i CPHA, a więc w tym samym trybie., Wiele urządzeń peryferyjnych może oznaczać różne konfiguracje, więc kontroler będzie musiał ponownie skonfigurować się za każdym razem, gdy będzie musiał komunikować się z określonym urządzeniem peryferyjnym.,poniższa tabela:
Odczyt i Zapis danych
Po skonfigurowaniu magistrali SPI użyj metody write (), aby wysłać łańcuch bajtów do urządzenia peryferyjnego:
spi1.write("This is an LCD display");
użycie ciągu jest opcjonalne: możesz również wysłać blob nieprzetworzonych bajtów danych:
local blob = blob(4); // Create a four-byte blob...blob.writen(0xDEADBEEF, 'i'); // ...and write a 32-bit value to itspi1.write(blob);
czy you want to read a string or a blob, you need one of the imp API ' s two SPI read methods:
local bytes = spi1.readblob(8);local inputString = spi1.readstring(16);
the integer value passed as a parameter is, odpowiednio, the number of bajts to be read into the blob and the number of characters to be put into the string., Oczywiście, ponieważ jeden znak zajmuje jeden bajt, te dwie metody są równoważne. Ten ostatni po prostu konwertuje blob na string dla Ciebie.
ze względu na „pełny dupleks” charakter magistrali SPI, zapis i odczyt zawsze występują jednocześnie. Dzięki poleceniom odczytu i zapisu, które widzieliśmy do tej pory, dane poruszające się w przeciwnym kierunku niż te, które nas interesują, są ignorowane lub zerowane. Tak, gdy ty pisać ciąg, powiedzmy, jakaś dane przybywający do imp od The peryferyjny ignorować., Podczas jednej z dwóch operacji odczytu, na obwodzie zapisywany jest pasujący rozmiar „atrapy” bajtów zerowych: jeśli odczytasz osiem bajtów, powiedzmy, osiem 0 zapisywanych jest automatycznie.
to manage this simultaneous two-way communication, the imp API has a fourth method which combines reads and writes:
local inputString = spi1.writeread(outputString);
So, as the string outputString is being send out along the Copi line, the zmienna inputString is being filled by the data bytes coming on on CIPO. Można wysyłać i odbierać ciągi lub obiekty BLOB, ale zarówno wejście, jak i wyjście muszą być tego samego typu., Niezależnie od tego, jak duży jest obiekt blob wyjściowy, obiekt blob wejściowy będzie tego samego rozmiaru. Podobnie, ciągi wejściowe i wyjściowe będą tej samej długości.
full duplex może być również używany z urządzeniami, które nie spodziewają się działać w ten sposób — tymi, które wymagają odczytu i zapisu 'atrapy' bajtów, aby były konkretną, niezerową wartością. Wymóg ten wyklucza użycie zwykłych metod write (), readblob () i readstring (), ale writeread () może być użyte w ich miejsce, aby upewnić się, że używane są preferowane wartości atrapy urządzenia.,
przykładowy kod
poniższy kod współpracuje z cyfrowym akcelerometrem Analog Devices ADXL345, częścią, która wykorzystuje SPI do komunikacji z mikrokontrolerem hosta. Obsługuje również I2C, a piny na tej płycie Adafruit breakout, która jest oparta na chipie, są odpowiednio oznakowane. Kartę danych Chipa można pobrać ze strony internetowej Analog Devices.
jak działa kod
używamy szyny spi257 imp001, aliasowanej na początku listy jako spi. Nazywamy również pin 8 jako linię CS. Funkcja spiWriteReg () pokazuje, w jaki sposób są one używane., Transakcja zapisu jest sygnalizowane przez przełączenie linii CS low. Następnie adres rejestru, na który chcemy zapisać, jest konwertowany z 32-bitowej liczby całkowitej podpisanej wiewiórką na wartość 8-bitową, zapisując ją do obiektu blob. Ten blob jest następnie zapisywany do magistrali SPI. Robimy to samo z wartością, którą chcemy umieścić ADXL345 w tym rejestrze, a następnie ponownie ustawiamy linię CS high, aby zasygnalizować koniec transakcji.,
Adafruit/Analog Devices ADXL345
funkcja spiReadReg() działa w ten sam sposób, tylko tym razem odczytujemy Dane wartości z magistrali po zapisaniu adresu rejestru źródłowego. ADXL345 wymaga wprowadzenia pewnych zmian w adresie rejestru w tym przypadku: bit 7 musi być ustawiony, aby oznaczyć transakcję jako operację odczytu, a bit 6 musi być ustawiony, aby powiedzieć układowi, że oczekujemy więcej niż jednego bajtu do wysłania z powrotem.,
gdzie program się uruchamia, konfigurujemy magistralę SPI imp tak, aby pasowała do wymagań układu ADXL345. Korzysta z trybu SPI 3-czyli zarówno CPOL, jak i CPHA powinny być ustawione – więc używamy równoważnego parametru imp: CLOCK_IDLE_HIGH | CLOCK_2ND_EDGE w wywołaniu configure (). Ustawiamy również prędkość na 100kHz. Następnie pin imp 8, który działa tutaj jako pin CS, jest skonfigurowany jako wyjście cyfrowe i ustawiony wysoko.
Podłączanie ADXL345
Inne funkcje w programie inicjalizują ADXL345 samodzielnie, a nie magistralę SPI., ADXL345 jest inicjalizowany, a kod odczytuje wartość z adresu rejestru 0x00
aby upewnić się, że urządzenie jest obecne na magistrali. Układ ma tryb autotestu, który umożliwia wykonanie serii odczytów kalibracyjnych; robimy to i przechowujemy wyniki. Później, w funkcji loop (), wartości te są używane do regulacji końcowych odczytów z akcelerometru.,
ADXL345 zapisuje próbki osi x, y i z jako wartości 16-bitowe, każda w dwóch 8 – bitowych rejestrach; loop() używa funkcji spiReadReg() do uzyskania dwóch składników każdej wartości, a następnie przekształca je w pojedyncze wartości przez pomnożenie najbardziej znaczącego bajtu przez 256 i dodanie do wyniku wartości najmniej znaczącego bajtu.