(edytuj: Żeby było jasne, wiele z poniższych obaw dotyczy integralności sygnału spowodowanej używaniem urządzeń I2C / SPI z płyty na płytę, jak słusznie zauważa Olin).
O ile nie masz ograniczeń, które silnie popychają cię w kierunku mniejszej liczby przewodów (mieliśmy jeden projekt z hermetycznie zamkniętym złączem, że każdy dodatkowy styk był dość drogi), unikaj I2C, jeśli to możliwe, i trzymaj się SPI.
SPI jest dość łatwe w obsłudze pod względem sprzętowym i programowym. W sprzęcie istnieją dwie współdzielone linie danych: Master In Slave Out (MISO lub SOMI) i Master Out Slave In (MOSI lub SIMO), wspólny zegar generowany przez urządzenie master i jeden układ na urządzenie. Linia CS przechodzi w stan niski, zegar cyklicznie i zasadniczo przesuwa bity wejściowe i przesuwa bity wyjściowe, aż do zakończenia transakcji, w którym to momencie linia CS przechodzi w stan wysoki. Gdy ich linia CS jest wysoka, urządzenia podrzędne nie komunikują się: ignorują linie CLK i MOSI i ustawiają pin MISO w stan wysokiej impedancji, aby pozwolić komuś innemu z niego korzystać.
Jeśli masz mikrokontroler korzystający z kilku urządzeń SPI i ma on wbudowane urządzenie peryferyjne SPI, wyślij wyjście CS mikrokontrolera do demultipleksera (np. 74HC138) i kontroluj linie adresowe, aby wybrać urządzenie między transakcjami SPI; piszesz słowa do rejestru, aby umieścić je w kolejce do wyjścia, i odczytujesz je po podniesieniu szpilki CS.
Ponieważ wszystkie sygnały SPI są jednokierunkowe, mogą być buforowane, używane przez barierę izolacyjną z cyfrowymi izolatorami i mogą być przesyłane z płyty na kartę za pomocą sterowników liniowych, takich jak LVDS. Jedyne, o co musisz się martwić, to opóźnienie propagacji w obie strony, które ograniczy Twoją maksymalną częstotliwość.
I2C to zupełnie inna historia. O ile jest to znacznie prostsze z punktu widzenia okablowania, z tylko dwoma przewodami SCL i SDA, obie te linie są wspólnymi liniami dwukierunkowymi, które wykorzystują urządzenia typu open-drain z zewnętrznym podciąganiem. Istnieje protokół dla I2C, który zaczyna się od przesłania adresu urządzenia, dzięki czemu można używać wielu urządzeń, jeśli każde ma własny adres.
Z punktu widzenia sprzętowego bardzo trudno jest używać I2C w systemach, w których występuje znaczny hałas. Aby buforować lub izolować linie I2C, musisz uciekać się do egzotycznych układów scalonych - tak, istnieją, ale nie ma ich wielu: wykorzystaliśmy jeden na jeden projekt i zdaliśmy sobie sprawę, że możesz użyć jednego izolatora, ale nie możesz użyj dwóch w szeregu - użył małych spadków napięcia, aby dowiedzieć się, po której stronie był napędzający koniec rzeczy, a dwa szeregi spadły o dwa razy.
Progi poziomu logicznego I2C zależą od Vcc, więc musisz być bardzo ostrożny, jeśli używasz urządzeń 3 V / 3,3 V i 5 V w tym samym systemie.
Wszelkie sygnały korzystające z kabla dłuższego niż dwa lub dwa stopy muszą martwić się o pojemność kabla. Pojemność 100pf / metr nie jest niczym niezwykłym w przypadku kabla wielożyłowego. Powoduje to, że musisz spowolnić magistralę lub użyć niższych rezystorów podciągających, aby móc odpowiednio obsłużyć dodatkową pojemność i spełnić wymagania dotyczące czasu narastania.
Powiedzmy, że masz system, który Twoim zdaniem dobrze zaprojektowałeś i możesz poradzić sobie z większością problemów z integralnością sygnału, a szum jest rzadki (ale nadal obecny). O co musisz się martwić?
Istnieje kilka warunków błędów, które należy przygotować:
Urządzenie podrzędne nie potwierdza określonego bajtu. Musisz to wykryć, zatrzymać i ponownie uruchomić sekwencję komunikacji. (Dzięki SPI zwykle możesz odczytać przesłane dane, jeśli chcesz mieć pewność, że zostały one odebrane bez błędów).
Odczytujesz bajt danych z urządzenia podrzędnego, a urządzenie jest „zahipnotyzowane” z powodu szumu na linii zegara: Wysłano wymagane 8 zegarów, aby odczytać ten bajt, ale z powodu szumu urządzenie podrzędne uważa, że to odebrał 7 zegarów i nadal przesyła zero na linii danych. Gdyby urządzenie otrzymało ósmy zegar, zwolniłoby linię danych wysoko, aby master mógł podnieść lub obniżyć linię danych, aby przesłać bit ACK lub NACK, lub master mógłby przesłać warunek zatrzymania (P). Ale slave wciąż utrzymuje linię danych na niskim poziomie, na próżno czekając na kolejny zegar. Jeśli urządzenie nadrzędne nie jest przygotowane do wypróbowania dodatkowych zegarów, magistrala I2C utknie w martwym punkcie. Chociaż użyłem kilku mikrokontrolerów, które obsługują normalne warunki ACK / NACK,
Naprawdę okropny jest przypadek, gdy master zapisuje dane do jednego urządzenia slave, a inny slave nieprawidłowo interpretuje adres urządzenia i uważa, że przesyłane dane są do niego przeznaczone. Mieliśmy urządzenia I2C (ekspandery I / O), które czasami mają niepoprawnie ustawione rejestry z tego powodu. Wykrywanie tego przypadku jest prawie niemożliwe, a aby być odpornym na zakłócenia, należy okresowo ustawiać wszystkie rejestry, aby jeśli wystąpił ten błąd, przynajmniej zostanie on naprawiony po krótkim czasie. (SPI nigdy nie ma tego problemu - jeśli zdarzy się, że masz usterkę w linii CS, to nigdy nie utrzyma się długo i nie dostaniesz danych przypadkowo odczytanych przez niewłaściwe urządzenie podrzędne.)
Wiele z tych warunków można by poprawnie obsłużyć w protokole, gdyby wykryto błąd (kody CRC), ale ma to kilka urządzeń.
Uważam, że muszę zbudować złożone oprogramowanie w moim urządzeniu głównym I2C, aby poradzić sobie z tymi warunkami. Moim zdaniem po prostu nie warto, chyba że ograniczenia okablowania zmuszają nas do używania I2C, a nie SPI.