I²C jest dwuprzewodową, synchroniczną magistralą do łączenia mikrokontrolera z czujnikami i układami konfiguracyjnymi na jednej płytce lub w niewielkim module. W kontrolerze lotu obsługuje zwykle barometr, magnetometr, pamięć EEPROM, czujniki temperatury i wolniejsze IMU. Oszczędza wyprowadzenia, ale jej pojemnościowy charakter, wspólna domena awarii oraz słaba diagnostyka błędów sprawiają, że wymaga bardziej świadomego projektu niż sugeruje prosty schemat SDA–SCL.

Spis treści#

Warstwa elektryczna#

SDA przenosi dane, a SCL zegar. Wyjścia zgodne z podstawowym I²C są typu open-drain: układ może aktywnie ściągnąć linię do zera albo ją zwolnić, lecz nie wymusza jedynki. Stan wysoki tworzą zewnętrzne rezystory podciągające. Dzięki temu wiele urządzeń może współdzielić przewody bez zwarcia wyjścia wysokiego z niskim, a dominujący stan niski umożliwia arbitraż.

To rozwiązanie ma istotną konsekwencję. Zbocze opadające może być szybkie, natomiast zbocze narastające wynika z ładowania całkowitej pojemności magistrali przez rezystor. W pierwszym przybliżeniu:

t_r ≈ 0,8473 · R_p · C_b

gdzie R_p jest rezystancją podciągania, a C_b obejmuje ścieżki, przewody, złącza, wejścia wszystkich układów i pojemności pasożytnicze. Rzeczywisty dobór trzeba sprawdzić względem granic czasu narastania w UM10204 oraz prądu, który urządzenie potrafi w stanie niskim bez przekroczenia V_OL.

I²C nie jest po prostu „dwoma GPIO”. Piny muszą tolerować właściwe napięcie, mieć poprawny tryb open-drain, a filtry analogowe/cyfrowe i progi wejściowe zależą od MCU. Wewnętrzne podciąganie rzędu dziesiątek kiloomów jest zwykle zbyt słabe do szybkiej, obciążonej magistrali.

START, STOP i bity danych#

Gdy magistrala jest bezczynna, SDA i SCL są wysokie. Zmiana SDA z wysokiego na niski przy wysokim SCL oznacza START. Zmiana SDA z niskiego na wysoki przy wysokim SCL oznacza STOP. W czasie przesyłania zwykłego bitu SDA ma pozostawać stabilne, gdy SCL jest wysokie.

Bajt przesyła się od najstarszego bitu. Po ośmiu bitach nadający zwalnia SDA, a odbiorca odpowiada dziewiątym taktem ACK, ściągając linię, albo NACK, pozostawiając ją wysoko. Znaczenie NACK zależy od etapu: brak urządzenia pod adresem, odrzucenie danych, zajętość wewnętrznym zapisem albo planowe zakończenie odczytu przez kontroler.

Repeated START rozpoczyna kolejny etap bez wcześniejszego STOP. Jest niezbędny dla wielu transakcji rejestrowych oraz tam, gdzie kontroler nie powinien zwalniać magistrali między zapisem adresu rejestru i odczytem danych.

Adresowanie i ACK#

Najczęstszy adres ma 7 bitów. W pierwszym bajcie adres zajmuje bity 7…1, a bit 0 określa zapis lub odczyt. Datasheet może niestety podawać adres jako wartość 7-bitową albo już przesunięty „adres zapisu/odczytu”. Mieszanie konwencji jest klasyczną przyczyną braku ACK.

Przykład: urządzenie o adresie 7-bitowym 0x68 pojawi się na przewodzie jako 0xD0 dla zapisu i 0xD1 dla odczytu. API sterownika powinno jasno dokumentować, czy przyjmuje 0x68, czy bajt przewodowy. Dobre API przyjmuje adres 7-bitowy i samo dodaje kierunek.

Specyfikacja przewiduje również adresowanie 10-bitowe, lecz jest ono rzadkie w typowym UAV i nie każdy sterownik MCU obsługuje je bez ograniczeń. Część zakresu 7-bitowego jest zarezerwowana; skaner nie powinien traktować każdego numeru jako zwykłego urządzenia.

ACK jest informacją o odbiorze bajtu, nie dowodem poprawności jego znaczenia. I²C nie ma CRC obejmującego ogólną transakcję. Sensor może potwierdzić błędny adres rejestru, a zakłócenie może zmienić dane na inną poprawną wartość bitową.

Odczyt rejestru z repeated START#

Typowy odczyt dwóch bajtów ma postać:

START
[adres 7-bit + W] ACK
[adres rejestru]  ACK
REPEATED START
[adres 7-bit + R] ACK
[dane MSB]        ACK
[dane LSB]        NACK
STOP

NACK po ostatnim bajcie pochodzi od kontrolera i mówi urządzeniu, że odczyt się kończy. Automaty peryferiów I²C mają historycznie różne wymagania dotyczące ustawienia NACK/STOP dla jednego, dwóch i wielu bajtów. Kod przeniesiony między rodzinami STM32 bez przeczytania reference manual może tracić ostatni bajt lub wygenerować STOP za wcześnie.

Nie wszystkie sensory używają jednego bajtu adresu rejestru. Spotyka się adresy 16-bitowe, osobne komendy, auto-increment wymagający ustawienia bitu oraz dane little-endian lub big-endian. Warstwa magistrali powinna znać tylko sekwencję segmentów, a sterownik urządzenia — format konkretnego układu.

Arbitraż i rozciąganie zegara#

W systemie z wieloma kontrolerami każdy nadający obserwuje SDA. Jeżeli próbuje wysłać jedynkę, czyli zwalnia linię, lecz odczytuje zero, przegrał arbitraż i musi zaprzestać nadawania. Arbitraż nie uszkadza ramki zwycięzcy, o ile wszystkie urządzenia zachowują się zgodnie ze specyfikacją.

Większość flight controllerów wykorzystuje jednego kontrolera. Mimo to własność magistrali musi być serializowana między przerwaniami, zadaniami RTOS i DMA. Dwa moduły rozpoczynające transakcję przez to samo peryferium nie tworzą poprawnego multi-controller I²C — tworzą wyścig programowy.

Urządzenie może przytrzymać SCL nisko, aby opóźnić następny bit; to clock stretching. Kontroler musi go obsługiwać albo projekt musi gwarantować, że żaden target go nie używa. Timeout jest konieczny, ponieważ nieskończone rozciąganie i fizyczne zwarcie wyglądają dla prostego sterownika podobnie.

Arbitraż i clock stretching opierają się na rzeczywistym odczycie linii, dlatego bufor, translator poziomów lub izolator musi poprawnie przenosić stan w obu kierunkach. Nie każdy „dwukierunkowy konwerter logiczny” nadaje się do wszystkich trybów i prędkości I²C.

Tryby prędkości#

Podstawowe klasy to Standard-mode do 100 kbit/s, Fast-mode do 400 kbit/s i Fast-mode Plus do 1 Mbit/s. High-speed mode osiąga 3,4 Mbit/s, ale wymaga dodatkowych zasad elektrycznych i protokołowych i rzadko jest praktycznym wyborem w kontrolerze lotu. Nazwa prędkości nie gwarantuje, że konkretne urządzenie, translator i wszystkie elementy magistrali ją obsłużą.

Przepustowość użytkowa jest mniejsza od częstotliwości SCL. Do danych dochodzą adres, kierunek, ACK, adres rejestru, START/STOP i ewentualne przełączenie kierunku. Odczyt sześciu bajtów IMU może wymagać kilkudziesięciu taktów, nie 48.

Budżet okresu próbkowania powinien obejmować najgorszy czas oczekiwania na inne urządzenia i stretching. Dla regulatora 1 kHz wspólna magistrala 400 kbit/s z długim odczytem barometru może być niewłaściwa nawet wtedy, gdy średnia liczba bitów „mieści się” w sekundzie.

Rezystory podciągające#

Zbyt duża rezystancja daje wolne zbocze, późne przekroczenie progu i błędy przy wysokiej częstotliwości. Zbyt mała zwiększa prąd w stanie niskim, może przekroczyć zdolność wyjścia i podnosi V_OL. Nie istnieje jedna uniwersalna wartość 4,7 kΩ.

Dolna granica wynika z:

R_p(min) = (V_DD - V_OL(max)) / I_OL

Górna zależy od dopuszczalnego t_r i C_b. Po zmontowaniu prototypu czas narastania należy zmierzyć oscyloskopem przy najgorszej konfiguracji złączy. Równoległe pull-upy na kilku modułach zmniejszają rezystancję zastępczą; cztery płytki po 4,7 kΩ dają około 1,18 kΩ.

Podciąganie do różnych szyn, na przykład 3,3 V i 5 V, jest błędem, dopóki nie ma świadomie zaprojektowanego translatora. Trzeba też sprawdzić, czy piny MCU są 5-V tolerant w trybie używanym przez peryferium.

Pojemność, długość i topologia#

I²C projektowano jako magistralę na płytce. Długi przewód w ramie drona zwiększa pojemność, tworzy pętlę podatną na EMI i zbiera zakłócenia od ESC, silników oraz przetwornic. Przy open-drain nie ma silnego aktywnego zbocza narastającego ani naturalnej odporności pary różnicowej.

Najbezpieczniejsza topologia jest krótka, z małymi odgałęzieniami i ciągłą referencją masy. Gwiazda o długich ramionach utrudnia kontrolę pojemności i odbić. Skręcenie SDA z SCL nie tworzy transmisji różnicowej; jeśli przewód musi istnieć, korzystniejsze bywa prowadzenie każdej linii z przewodem powrotnym/masą i obniżenie prędkości.

Magnetometr umieszczony daleko od prądów napędu często łączy się przewodem. To konflikt wymagań: separacja magnetyczna poprawia pomiar, ale wydłuża I²C. Rozwiązaniem może być lokalny MCU i odporniejszy link CAN/RS-485, odpowiedni bufor I²C albo sensor z SPI — wybór trzeba zweryfikować pomiarowo.

Konflikty adresów#

Dwa urządzenia o tym samym adresie nie mogą być niezależnie adresowane na wspólnym segmencie. Jeżeli oba odpowiadają na odczyt, mogą jednocześnie wymuszać różne bity. Nie jest to poprawne „broadcast read”.

Możliwe rozwiązania:

  • alternatywny adres wybierany pinem, OTP lub rejestrem zachowywanym po resecie;
  • osobne peryferia I²C MCU;
  • multiplekser/przełącznik I²C z oddzielnymi kanałami;
  • kontrolowane zasilanie lub reset umożliwiające kolejno nadać adresy dynamiczne;
  • zmiana interfejsu jednego urządzenia na SPI.

Multiplekser usuwa konflikt, lecz staje się elementem wspólnym i dodaje stan konfiguracyjny. Po brownoucie jego wybrany kanał może nie odpowiadać założeniom oprogramowania, więc inicjalizacja powinna ustawiać go jawnie.

Translacja poziomów#

Popularny translator z dwoma MOSFET-ami wykorzystuje charakter open-drain, ale jego poprawność zależy od napięć progowych, pojemności i rezystorów po obu stronach. Nie należy traktować przypadkowego modułu „logic level converter” jako przeźroczystego elementu przy 1 MHz.

Bufory aktywne mogą rozdzielić pojemności segmentów i wspierać hot-swap, lecz wprowadzają własne offsety stanu niskiego, opóźnienia i reguły łączenia. Niektórych buforów nie wolno kaskadować dowolnie. Izolatory wymagają rozwiązania problemu dwukierunkowości bez sprzężenia zwrotnego.

Najprostszy kontroler lotu zwykle unika translacji: MCU i sensory pracują z tej samej szyny 3,3 V. Jeżeli domeny muszą być różne, część dobiera się na podstawie datasheetu i mierzy pełny budżet timingowy.

Zasilanie i back-powering#

Jeżeli sensor jest wyłączony, a SDA/SCL pozostają wysokie, prąd może płynąć przez diody ochronne wejść do jego domeny zasilania. Powoduje to częściowe zasilanie, nieokreślony reset, nadmierny prąd lub blokadę linii. Datasheet powinien określać zachowanie pinów przy VDD = 0.

Sekwencja startowa powinna uwzględniać czas stabilizacji zasilania i wewnętrzny boot sensora. NACK przez pierwsze milisekundy nie zawsze oznacza usterkę. Zamiast nieskończonego retry stosuje się ograniczoną liczbę prób, deadline uruchomienia oraz osobny stan „urządzenie nieobecne”.

W systemie z przełączaną szyną sensora pull-up powinien należeć do właściwej domeny albo zostać odizolowany. Odcięcie tylko VDD, pozostawienie sygnałów, nie jest pełnym power-cycle.

Magistrala zajęta i recovery#

Reset MCU w połowie odczytu może pozostawić urządzenie oczekujące na kolejne takty i trzymające SDA nisko. Kontroler widzi wtedy BUSY jeszcze przed wygenerowaniem START. Sam reset peryferium MCU nie uwolni zewnętrznego targetu.

Kontrolowana procedura recovery może:

  1. wyłączyć peryferium I²C i przełączyć SCL/SDA na open-drain GPIO;
  2. sprawdzić rzeczywiste poziomy obu linii;
  3. przy wysokim SDA wygenerować STOP lub wrócić do inicjalizacji;
  4. przy niskim SDA wygenerować do dziewięciu bezpiecznych impulsów SCL, obserwując SDA;
  5. wygenerować STOP, kiedy SDA zostanie zwolnione;
  6. ponownie skonfigurować peryferium i urządzenia;
  7. jeśli linia nadal jest niska, zresetować lub odłączyć domenę sensora i zgłosić trwałą awarię.

Dziewięć impulsów wynika z maksymalnie ośmiu bitów oraz fazy ACK, ale nie jest gwarancją dla każdego układu. Impulsów nie wolno generować bez sprawdzenia, czy SCL rzeczywiście może wzrosnąć i czy inne urządzenie nie prowadzi legalnej transakcji w systemie multi-controller.

Każda transakcja musi mieć timeout. Blokowanie w przerwaniu „aż BUSY zniknie” może zatrzymać pętlę sterowania. Recovery wykonuje się w kontrolowanym kontekście, z licznikami przyczyn i limitem restartów, aby uszkodzony czujnik nie tworzył reset storm.

Sterownik nieblokujący#

Sterownik czasu rzeczywistego reprezentuje transakcję jako stan: START, adres, zapis prefiksu, repeated START, odbiór, STOP, complete/error. Klient przekazuje bufor, długość, deadline i callback lub obiekt completion. Własność bufora trwa do zakończenia.

Kolejka powinna rozróżniać priorytet i maksymalny czas zajęcia. Długi odczyt EEPROM nie może opóźnić próbki sensora krytycznego. Jednocześnie nie wolno przerwać transakcji w dowolnym bajcie; preempcja następuje między transakcjami albo w miejscach dozwolonych przez protokół urządzenia.

Przy RTOS mutex chroni konfigurację peryferium, ale zwykły mutex bez priority inheritance może powodować priority inversion. Jeszcze ważniejsze jest ograniczenie czasu transakcji niskiego priorytetu.

Wynik powinien odróżniać NACK adresu, NACK danych, arbitration lost, bus error, overrun, timeout i bus stuck. Sprowadzenie wszystkiego do false utrudnia diagnostykę w locie.

DMA i ograniczenia peryferium#

DMA zmniejsza obciążenie CPU, ale nie rozwiązuje START/STOP, repeated START i szczególnych sekwencji ostatniego bajtu. Część peryferiów wymaga obsługi zdarzeń kontrolnych przerwaniem, podczas gdy DMA przesuwa tylko dane.

Zakończenie DMA RX oznacza zapisanie zadanej liczby bajtów, lecz trzeba jeszcze potwierdzić poprawny STOP i brak błędu magistrali. W systemie z cache bufor wymaga spójności tak samo jak przy SPI. Deskryptor nie może wskazywać na stos funkcji, która już wróciła.

Małe transakcje dwu- lub trzybajtowe mogą kosztować więcej konfiguracji DMA niż obsługa przerwaniowa. Kryterium stanowi jitter pętli i całkowity czas CPU, nie samo hasło „DMA jest szybsze”.

Integralność danych#

Podstawowy I²C wykrywa brak ACK, ale nie chroni payloadu sumą kontrolną. Jeśli urządzenie udostępnia CRC/PEC, warto je włączyć. Jeśli nie, sterownik może sprawdzać:

  • identyfikator układu i wartości rejestrów konfiguracyjnych;
  • zakres fizyczny i ciągłość próbek;
  • licznik próbek lub znacznik data-ready;
  • stałe bity zarezerwowane;
  • zgodność duplikowanych pomiarów;
  • tempo błędów i resetów.

Ponowny zapis konfiguracji bez odczytu zwrotnego nie dowodzi, że sensor ją przyjął. Rejestry krytyczne odczytuje się po konfiguracji i okresowo audytuje, o ile datasheet pozwala.

Timestamp powinien opisywać chwilę próbki. Znacznik utworzony dopiero w callbacku I²C zawiera zmienne oczekiwanie na kolejkę. Lepszy jest pin data-ready podłączony do timera capture albo rekonstrukcja czasu z FIFO i licznika próbek.

Dobór I²C albo SPI#

I²C jest racjonalne dla małej liczby przewodów, umiarkowanego rate i urządzeń z gotowym, dobrze działającym interfejsem. SPI daje zwykle większą przepustowość, pełny dupleks, osobne CS i silnie sterowane zbocza, dlatego jest preferowane dla głównego IMU o wysokim ODR.

Awaria jednego targetu trzymającego SDA może zatrzymać wszystkie urządzenia I²C. Osobne CS w SPI ogranicza część awarii logicznych, choć wspólne MISO nadal może zostać zwarte przez wadliwy układ. Dwa redundantne sensory na jednej magistrali nie tworzą pełnej redundancji.

Wybór obejmuje również wyprowadzenia, pobór mocy, zakłócenia, dostępność sterownika i wymagania mechaniczne. Nie należy wybierać I²C wyłącznie dlatego, że płytka demonstracyjna ma cztery piny.

Diagnostyka#

Oscyloskop odpowiada na pytania elektryczne: czy stan wysoki osiąga próg na czas, jaki jest V_OL, czy występuje ringing, czy zasilanie sensora zapada. Analizator logiczny pomaga zdekodować adresy, ACK i repeated START, ale jego cyfrowy próg może ukryć marginalne zbocze.

Praktyczna kolejność:

  1. zmierz napięcie idle SDA/SCL i zasilanie każdego układu;
  2. przy wyłączonym zasilaniu policz rzeczywistą rezystancję pull-up;
  3. uruchom 100 kbit/s i odczytaj identyfikator jednego urządzenia;
  4. porównaj adres 7-bitowy z przebiegiem przewodowym;
  5. sprawdź ACK po każdym bajcie i sekwencję końcowego NACK;
  6. zmierz czas narastania przy pełnym okablowaniu;
  7. zwiększ prędkość i uruchom równoległe obciążenie systemu;
  8. testuj reset MCU w każdym etapie transakcji;
  9. odłącz lub zewrzyj kontrolowany sensor na stanowisku i oceń recovery;
  10. sprawdź liczniki błędów, degradację i reakcję pętli sterowania.

Skaner adresów jest narzędziem pomocniczym. Może zmienić stan urządzenia, które interpretuje sam adres lub pierwszy bajt jako komendę, a brak odpowiedzi nie odróżnia złego napięcia od złego adresu.

Lista uruchomieniowa#

  • Wszystkie układy mają zgodne poziomy i wspólną referencję.
  • Adresy są zapisane konsekwentnie jako 7-bitowe.
  • Rezystory wynikają z C_b, t_r i I_OL, a nie z przyzwyczajenia.
  • Równoległe pull-upy na modułach zostały policzone.
  • Clock stretching jest obsługiwany albo wykluczony przez datasheet.
  • Każda operacja ma deadline i rozróżnialny kod błędu.
  • BUSY po resecie ma procedurę recovery i limit prób.
  • Główny sensor nie współdzieli domeny awarii bez świadomej decyzji.
  • Odczyt wielobajtowy ma poprawny repeated START, ACK/NACK i endianowość.
  • Konfiguracja jest odczytywana zwrotnie.
  • Timestamp nie jest utożsamiany z przypadkowym czasem callbacku.
  • Test obejmuje EMI, brownout, odłączenie sensora i obciążenie CPU.

Powiązane tematy#

Przypisy#

  1. NXP Semiconductors, UM10204: I²C-bus specification and user manual — warstwa elektryczna, format transferu, tryby prędkości, arbitraż i timing.
  2. Bosch Sensortec, BMI088 — przykład sensora z interfejsem I²C/SPI i ograniczeniami urządzenia.
  3. TDK InvenSense, ICM‑42688‑P — przykład rejestrów, FIFO i interfejsów nowoczesnego IMU.

Utworzono: 15 sierpnia 2026. Ostatnia aktualizacja: 15 sierpnia 2026. Źródła zweryfikowano: 15 sierpnia 2026.

Źródła z centralnego rejestru

  1. NXP UM10204 Rev. 7: I²C-bus specification and user manual [specyfikacja pierwotna magistrali]
  2. Bosch Sensortec: BMP390 datasheet [datasheet]
  3. Bosch Sensortec: BMM350 magnetometer [dokumentacja producenta]