Gdy do mikrokontrolera trzeba podłączyć kilka czujników, pamięć EEPROM, zegar czasu rzeczywistego albo mały wyświetlacz, liczba potrzebnych przewodów szybko zaczyna mieć znaczenie. Właśnie dlatego magistrala i2c jest tak popularna: pozwala komunikować wiele układów za pomocą zaledwie dwóch linii. Wyjaśniam, jak działa, jak ją poprawnie podłączyć, jak wygląda transmisja oraz jakie ograniczenia trzeba uwzględnić w praktycznym projekcie.
Dwie linie wystarczą do obsługi wielu układów
- SDA i SCL przenoszą odpowiednio dane oraz sygnał zegarowy.
- Każde urządzenie ma adres, dzięki któremu kontroler może wybrać konkretny układ.
- Linie wymagają rezystorów podciągających, zwykle o wartości od 2,2 kΩ do 10 kΩ.
- Najczęściej stosowane prędkości to 100 kHz i 400 kHz.
- Najczęstsze problemy powodują złe adresy, brak wspólnej masy, różne napięcia i zbyt długie przewody.

Co to jest I2C i do czego służy
I2C, czyli Inter-Integrated Circuit, to synchroniczny protokół komunikacji szeregowej przeznaczony przede wszystkim do łączenia układów scalonych na jednej płytce lub w niewielkiej odległości. W praktyce jeden mikrokontroler może obsługiwać wiele urządzeń bez osobnego przewodu danych dla każdego z nich.
Do transmisji służą dwie linie. SDA przenosi dane, a SCL dostarcza sygnał zegarowy. Oprócz nich potrzebne są przewody zasilania i wspólnej masy, dlatego w typowym połączeniu modułów spotyka się cztery przewody: VCC, GND, SDA i SCL.
Protokół jest półdupleksowy, czyli w danym momencie dane płyną tylko w jednym kierunku. W klasycznym układzie mikrokontroler pełni funkcję kontrolera, a czujnik, pamięć lub ekspander portów jest urządzeniem docelowym. Standard dopuszcza także kilku kontrolerów na jednej magistrali, choć w prostych projektach rzadko ma to praktyczne znaczenie.
Gdzie spotyka się ten interfejs
I2C dobrze sprawdza się tam, gdzie liczy się mała liczba wyprowadzeń, a szybkość transmisji nie musi być bardzo wysoka. Sam korzystam z niego najczęściej przy czujnikach temperatury i wilgotności, układach RTC, wyświetlaczach OLED, przetwornikach, pamięciach EEPROM oraz ekspanderach GPIO.
Nie jest to interfejs do przesyłania dużych bloków danych. Do obrazu, dźwięku albo szybkiej komunikacji z kartą pamięci lepiej wybrać SPI, USB lub inny interfejs o większej przepustowości. I2C wygrywa za to prostotą okablowania i możliwością współdzielenia jednej magistrali przez wiele układów.
Jak przebiega transmisja danych
Transmisja rozpoczyna się od warunku START. Kontroler zmienia stan SDA z wysokiego na niski, gdy SCL pozostaje w stanie wysokim. Ten charakterystyczny sygnał informuje wszystkie urządzenia, że rozpoczyna się nowa ramka.
Potem wysyłany jest adres urządzenia. W najczęściej spotykanym wariancie ma on 7 bitów, a ósmy bit określa kierunek operacji: zapis albo odczyt. Po każdym bajcie odbiornik odpowiada bitem ACK, czyli potwierdzeniem odebrania danych. Brak potwierdzenia oznacza NACK i może wskazywać między innymi na błędny adres lub niedostępne urządzenie.
Po przesłaniu wszystkich danych kontroler generuje warunek STOP. To zmiana stanu SDA z niskiego na wysoki przy wysokim poziomie SCL. Od tej chwili magistrala jest wolna i może rozpocząć się kolejna transakcja.
| Element transmisji | Znaczenie |
|---|---|
| START | Rozpoczęcie komunikacji |
| Adres | Wybór konkretnego urządzenia |
| Bit R/W | Określenie zapisu lub odczytu |
| ACK/NACK | Potwierdzenie albo odrzucenie bajtu |
| Dane | Właściwa informacja przesyłana między układami |
| STOP | Zakończenie transakcji |
Odczyt często wymaga dwóch etapów
Odczyt z czujnika lub pamięci nie zawsze polega na prostym wysłaniu polecenia „czytaj”. Często kontroler najpierw wysyła numer rejestru, z którego chce odczytać dane, a potem wykonuje ponowny START i zmienia kierunek transmisji.
Przykładowo odczyt temperatury może wyglądać tak: adres czujnika, numer rejestru pomiarowego, ponowny START, ponownie adres, tym razem z bitem odczytu, a na końcu dwa bajty wyniku. Repeated START pozwala wykonać tę operację bez zwalniania magistrali pomiędzy etapami.
Połączenie elektryczne wymaga uwagi
Największa pułapka nie znajduje się w kodzie, tylko w warstwie elektrycznej. Wyjścia SDA i SCL działają zwykle jako open-drain albo open-collector. Urządzenie potrafi aktywnie wymusić stan niski, ale nie podaje samodzielnie logicznej jedynki. Za powrót linii do stanu wysokiego odpowiada rezystor podciągający.
Rezystory łączy się między SDA i napięciem zasilania oraz między SCL i tym samym napięciem. Typowe wartości to 4,7 kΩ dla krótkich połączeń i umiarkowanej prędkości. Przy małej pojemności magistrali można spotkać 10 kΩ, natomiast przy 400 kHz, większej liczbie modułów lub dłuższych ścieżkach często lepiej sprawdzą się wartości 2,2-3,3 kΩ.
Nie należy bezmyślnie montować rezystorów z każdego modułu. Jeśli pięć płytek ma już własne podciąganie 4,7 kΩ, ich równoległe połączenie da około 940 Ω. To może wymusić zbyt duży prąd w stanie niskim i przeciążyć wyjścia układów. Przed połączeniem kilku gotowych modułów sprawdzam, czy ich rezystory można odłączyć zworką albo usunąć.
Napięcie i wspólna masa
Wszystkie urządzenia muszą rozumieć poziomy logiczne panujące na magistrali. Połączenie modułu 5 V z układem 3,3 V bywa możliwe, ale tylko wtedy, gdy karta katalogowa dopuszcza takie poziomy lub zastosowano konwerter poziomów logicznych.
Trzeba też połączyć masy wszystkich urządzeń. Bez wspólnego punktu odniesienia nawet poprawnie ustawione SDA i SCL mogą być odczytywane jako przypadkowe stany. W praktyce brak wspólnej masy jest jednym z pierwszych punktów, które sprawdzam, gdy skaner I2C nie wykrywa żadnego modułu.
Adresy, prędkości i liczba urządzeń
Każde urządzenie odpowiada na przypisany adres. Wariant 7-bitowy daje teoretycznie 128 wartości, ale część przestrzeni jest zarezerwowana, a wiele układów ma adres ustalony przez producenta. Zwykle kilka najmłodszych bitów można zmieniać za pomocą zworek lub podłączenia pinów ADDR.
Problem pojawia się wtedy, gdy dwa identyczne moduły mają ten sam adres. Kontroler nie potrafi wtedy rozmawiać z nimi niezależnie, bo oba odpowiedzą na tę samą ramkę. Rozwiązaniem może być zmiana adresu, użycie multipleksera I2C albo osobne sterowanie wejściem aktywującym jednego z układów.
| Tryb | Maksymalna częstotliwość SCL | Typowe zastosowanie |
|---|---|---|
| Standard-mode | 100 kHz | Czujniki, RTC, proste układy sterujące |
| Fast-mode | 400 kHz | Wyświetlacze, szybsze odczyty i większa liczba danych |
| Fast-mode Plus | 1 MHz | Układy zgodne z rozszerzonymi wymaganiami elektrycznymi |
| High-speed mode | 3,4 MHz | Specjalistyczne urządzenia i kontrolery |
Wartości z tabeli opisują możliwości trybu, a nie gwarantowaną szybkość całego projektu. Ostateczne ograniczenie wynika z pojemności przewodów, liczby wejść oraz rezystorów podciągających. 100 kHz jest bezpiecznym punktem startowym, a 400 kHz warto włączać dopiero po sprawdzeniu, czy przebiegi na oscyloskopie są poprawne.
Jak uruchomić magistralę krok po kroku
Najpierw sprawdzam dokumentację każdego modułu i zapisuję jego adres, napięcie zasilania oraz wymagany sposób inicjalizacji. To drobiazg, który oszczędza dużo czasu, bo adres nadrukowany w przykładzie biblioteki może różnić się od adresu konkretnej wersji płytki.
- Połącz GND mikrokontrolera z masą wszystkich modułów.
- Połącz SDA z SDA oraz SCL z SCL.
- Sprawdź, czy na obu liniach znajdują się rezystory podciągające.
- Ustaw bezpieczną prędkość 100 kHz.
- Uruchom skaner adresów i sprawdź, czy urządzenie odpowiada.
- Przetestuj najprostszą operację, na przykład odczyt identyfikatora układu.
Prosty skaner nie potwierdza, że moduł działa poprawnie. Pokazuje tylko, że coś odpowiedziało na dany adres. Jeśli urządzenie jest wykrywane, ale zwraca błędne dane, przyczyny trzeba szukać w kolejności rejestrów, formacie liczby, wymaganym opóźnieniu albo konfiguracji czujnika.
// Przykład ideowy dla biblioteki Wire
Wire.beginTransmission(adres);
Wire.write(numerRejestru);
Wire.endTransmission(false); // ponowny START
Wire.requestFrom(adres, 2);
uint8_t starszy = Wire.read();
uint8_t mlodszy = Wire.read();
Ten fragment pokazuje typowy odczyt dwóch bajtów, ale nie jest uniwersalnym kodem dla każdego układu. Producent może wymagać innej kolejności, dodatkowego bajtu kontrolnego albo jednorazowego wybudzenia czujnika. Karta katalogowa urządzenia jest ważniejsza niż przykład z biblioteki.
Najczęstsze problemy i ich diagnozowanie
Brak odpowiedzi na każdym adresie
W pierwszej kolejności sprawdzam zasilanie, wspólną masę, zamianę linii SDA z SCL oraz obecność podciągania. Pomaga też pomiar napięcia na obu liniach przy bezczynnej magistrali. Powinny znajdować się w stanie wysokim, blisko napięcia logicznego układów.
Urządzenie blokuje magistralę
Jeśli SDA pozostaje w stanie niskim, urządzenie mogło zostać przerwane w połowie transmisji albo kontroler został zresetowany, gdy układ docelowy nadal czekał na zegar. Czasem pomaga wygenerowanie około 9 impulsów SCL, wysłanie warunku STOP i ponowna inicjalizacja peryferium.
Działa przy 100 kHz, ale nie przy 400 kHz
To zwykle sygnał zbyt wolnych zboczy, zbyt dużej pojemności magistrali albo za słabych rezystorów podciągających. Pomaga skrócenie przewodów, zmniejszenie wartości rezystorów i ograniczenie liczby modułów. Trzeba jednak zachować rozsądny kompromis, ponieważ zbyt mały rezystor zwiększa prąd w stanie niskim.
Przeczytaj również: Komunikacja radiowa - Jak działa i co naprawdę decyduje o zasięgu?
Odczyty są przesunięte albo pozornie losowe
Częsty błąd polega na pomyleniu adresu 7-bitowego z adresem zapisanym w dokumentacji jako bajt adresowy. Niektóre biblioteki oczekują wartości 7-bitowej, a inne przykłady podają już adres przesunięty o jeden bit razem z flagą odczytu i zapisu. Zanim zmienisz okablowanie, sprawdź właśnie tę różnicę.
Kiedy wybrać I2C, a kiedy inny interfejs
Największą zaletą tego rozwiązania jest oszczędność pinów i łatwe dokładanie kolejnych układów. Wadą pozostają niższa przepustowość, wspólna magistrala oraz wrażliwość na pojemność przewodów. Dla krótkich połączeń na płytce jest to bardzo wygodny standard, ale nie traktowałbym go jako zamiennika każdego interfejsu.
| Cecha | I2C | SPI | UART |
|---|---|---|---|
| Liczba podstawowych linii | 2 | 3-4 plus osobny CS dla urządzenia | 2 |
| Wiele urządzeń | Tak, przez adresy | Tak, przez linie CS | Zwykle nie bez dodatkowej logiki |
| Prędkość | Mała lub średnia | Wysoka | Mała lub średnia |
| Najlepsze zastosowanie | Czujniki i układy sterujące | Pamięci, wyświetlacze, szybkie przetworniki | Połączenie punkt-punkt |
Do kilku czujników temperatury, enkodera, zegara RTC i wyświetlacza OLED wybrałbym I2C bez większego namysłu. Gdy potrzebuję przesyłać duże ilości danych lub uzyskać możliwie małe opóźnienia, lepiej sięgnąć po SPI. Przy dłuższym połączeniu między osobnymi urządzeniami rozważyłbym natomiast RS-485 albo magistralę zaprojektowaną specjalnie do pracy z większą odległością.
Najlepsza praktyka przed uruchomieniem projektu
Najbezpieczniej zacząć od jednego urządzenia, krótkich przewodów, 100 kHz i pomiaru stanów logicznych. Dopiero gdy podstawowa komunikacja działa, dodaję kolejne moduły, zwiększam szybkość i sprawdzam zachowanie całej magistrali.
Jeżeli projekt ma trafić do urządzenia pracującego długo i bez nadzoru, sam skan adresów nie wystarczy. Dobrze przewidzieć limit czasu transmisji, obsługę NACK, możliwość resetu peryferium oraz procedurę odblokowania linii. Takie drobne zabezpieczenia często robią większą różnicę niż sama zmiana mikrokontrolera.
I2C pozostaje świetnym wyborem, gdy potrzebujesz prostego połączenia wielu układów na krótkim dystansie. Najważniejsze są nie efektowne ustawienia maksymalnej prędkości, lecz poprawne podciąganie linii, zgodność napięć, wolne adresy i kontrola jakości sygnału. W tych warunkach dwuprzewodowy interfejs jest tani, przewidywalny i wyjątkowo wygodny w elektronice, robotyce oraz projektach embedded.