Elektronika     Skaner magistrali I2C (ATtiny24)        




Jest to prosty skaner magistrali I2C, wykrywający podłączone do niej urządzenia w całym zakresie
adresowym 0-127 ($00-$7F). Może być zasilany stabilizowanym napięciem Vcc=2.7-5.5V, które
pochodzi z badanej magistrali. Wynik skanowania jest prezentowany w postaci graficznej na jednym
ekranie monochromatycznego wyświetlacza OLED (sterownik SSD1306, magistrala I2C), o rozdziel-
czości 128x64 pikseli i adresie $78 ($3C) lub $7A ($3D). Skaner można wykorzystać do sprawdzania
obecności urządzeń na magistrali I2C i monitorowania stanu jej linii SCL/SDA.

1. Wstęp
2. Działanie
3. Szczegóły
4. Uruchomienie

1. Wstęp

Niedawno napisałem w asemblerze własne procedury do obsługi magistrali I2C i wyświetlacza OLED. Szukałem
sposobu, aby je wykorzystać w jakimś praktycznym urządzeniu i tak powstał pomysł zrobienia tego skanera I2C.
Użyłem w nim mikrokontrolera ATtiny44 w obudowie SO14, bo akurat mam ich bardzo dużo z demontażu.
Sercem skanera jest popularny mikrokontroler ATtiny24(A/V). Zamiast niego można użyć modeli ATtiny44(A/V)/84(A/V),
które różnią się jedynie większą ilością pamięci. Program sterujący napisałem w asemblerze i jest on identyczny dla
każdego z wymienionych mikrokontrolerów (zajmuje 1182-1188 bajtów pamięci FLASH). Kompiluje się warunkowo,
w zależności od zdefiniowanej częstotliwości pracy CLK mikrokontrolera, która musi mieć parzystą wartość z zakresu
4-20 MHz. Dlatego w archiwum w katalogu "wsad", znajdują się osobne wsady skompilowane dla każdej możliwej
częstotliwości CLK.
Mikrokontroler w wersji "A"/"V" wyróżnia się tym, że może pracować przy napięciu zasilania 1.8-5.5V z maksymalną
częstotliwością taktowania 20/10 MHz. Oznacza to, że po użyciu mikrokontrolera ATtiny24A/V/44A/V/84A/V, skaner
będzie działał przy minimalnym napięciu Vcc=1.8V, ale tylko przy częstotliwości CLK = 4 MHz. Jest to spowodowane
tym, że im mniejsze napięcie zasilania Vcc, tym niższa jest maksymalna częstotliwość z jaką może pracować mikro-
kontroler. Dla Vcc=1.8V maksymalna częstotliwość taktowania wynosi 4 MHz, dla Vcc=2.7V wynosi ona 10 MHz,
a dla Vcc=4.5-5.5V jest to 20 MHz (nie dotyczy wersji "V"). Poniższy wykres przedstawia zależność maksymalnej
częstotliwości taktowania Fmax mikrokontrolera od jego napięcia zasilania Vcc.



2. Działanie

Po włączeniu zasilania skaner ciągle monitoruje linie SCL/SDA magistrali I2C i pokazuje na wyświetlaczu napisy
"SCL: x" | "SDA: x" z ich aktualnymi stanami ("0" = LOW, "1" = HIGH) logicznymi (rysunek 1). Umożliwia to szybkie
wykrycie uszkodzonej linii (np. zwartej do masy). Po krótkim naciśnięciu przycisku S1 (SCAN), skaner rozpocznie
próbę skanowania magistrali I2C przez proste sprawdzenie, czy jest ona dostępna. Jeśli w ciągu ok. 50ms na linii
SCL/SDA zostanie wykryty niski stan logiczny (linia jest zajęta), to skaner nie rozpocznie swojego działania, na
wyświetlaczu pojawią się napisy "SCL: B" | "SDA: B" (rysunek 2), a program zatrzyma się w pętli oczekującej na
krótkie naciśnięcie przycisku S1, po którym skaner wznowi monitorowanie stanu linii SCL/SDA.
Natomiast, jeśli w tym czasie ok. 50ms niski stan nie zostanie wykryty na żadnej linii, to skaner zakłada że magistrala
nie jest używana i przeprowadza jej skanowanie. Do prawidłowego działania skanera konieczne jest, aby podczas
wykonywania procesu skanowania magistrali, żadne podłączone do niej urządzenie nie prowadziło transmisji danych.
W przeciwnym razie wystąpi konflikt/kolizja transmisji, a wynik skanowania będzie nieprzewidywalny i niewiarygodny
(trzeba je powtórzyć), co nie zostanie w żaden sposób zasygnalizowane użytkownikowi (ewentualnie tylko przez
wykrycie nieoczekiwanych urządzeń).



Rysunek 1


Rysunek 2


Rysunek 3


Rysunek 4

Skanowana magistrala I2C oraz magistrala wyświetlacza OLED jest obsługiwana całkowicie programowo (bit-bang)
z częstotliwością 100 kHz (standard mode). Przebiegi czasowe sygnałów (O)SCL/(O)SDA są zgodne ze specyfikacją
magistrali I2C oraz generowane z dokładnością do 1 cyklu zegarowego, niezależnie od częstotliwości pracy CLK
mikrokontrolera, która musi mieć parzystą wartość z zakresu 4-20 MHz (zapewnia to idealną symetrię sygnałów
(O)SCL/(O)SDA).
Wykrywanie każdego podłączonego urządzenia polega na: rozpoczęciu transmisji warunkiem START, wysłaniu 8-bito-
wego adresu urządzenia ($00-$7F + bit RW=0), sprawdzeniu odpowiedzi urządzenia (odczyt wartości bitu potwierdze-
nia ACK z linii SDA, następuje 2.5us po wygenerowaniu 9 rosnącego zbocza zegara na linii SCL) oraz zakończeniu
transmisji warunkiem STOP. Taka sekwencja zostaje wykonana 128 razy dla każdego adresu.
Według specyfikacji 16 adresów (2 grupy po 8) jest zarezerwowanych i przeznaczonych do pełnienia specjalnych fun-
kcji: %0000xxx ($00-$07) oraz %1111xxx ($78-$7F). Jeśli te funkcje nigdy nie będą używane na magistrali I2C, to za-
rezerwowane adresy można przydzielić urządzeniom. Dlatego te zakresy (w tym adres rozgłoszeniowy 0) również są
skanowane.
Jeśli urządzenie odpowie bitem potwierdzenia (ACK=0), to znaczy że jest podłączone do magistrali I2C i działa.
Zostanie ono oznaczone na wyświetlaczu pełnym kwadratem 6x6 pikseli, umieszczonym w odpowiednim wierszu 0-7
i kolumnie 0-F szesnastkowych cyfr, które określają jego 7-bitowy adres. Brak odpowiedzi od urządzenia (ACK=1)
oznacza, że nie jest podłączone do magistrali lub nie jest gotowe na komunikację (może być zajęte wykonywaniem
innych operacji). Takie nieobecne urządzenie zostanie oznaczone na wyświetlaczu pojedynczym pikselem (zamiast
pełnego kwadratu).
Jeśli żadne urządzenie nie zostanie wykryte na magistrali I2C, to wyświetlacz będzie wyglądał jak na rysunku 3.
Natomiast, jeśli zostaną wykryte dwa urządzenia o 7-bitowych adresach: $3C (wyświetlacz OLED 128x32) oraz
$27 (ekspander PCF8574T), to wyświetlacz będzie wyglądał jak na rysunku 4.
Na wyświetlaczu można odczytać szesnastkową wartość 7-bitowego adresu urządzenia, które zostało wykryte na
magistrali. Z kolumny cyfr 0-7 należy wybrać cyfrę, w której wierszu znajduje się znacznik wykrytego urządzenia - jest
to szesnastkowa wartość 3 najstarszych bitów jego adresu. Z wiersza cyfr 0-F należy wybrać cyfrę, w której kolumnie
znajduje się znacznik wykrytego urządzenia - jest to szesnastkowa wartość 4 najmłodszych bitów jego adresu. Adresy
7-bitowe są używane, np. przez programowy skaner I2C oraz bibliotekę Wire w środowisku Arduino, ale często stosuje
się też adresy 8-bitowe. Aby z odczytanego 7-bitowego adresu uzyskać adres 8-bitowy (zawierający najmłodszy bit
kierunku danych RW=0), należy pomnożyć jego wartość przez 2 (przesunąć o jeden bit w lewo).
Po wyświetleniu ekranu z wynikiem skanowania, krótkie naciśnięcie przycisku S1 spowoduje powrót do początkowego
trybu monitorowania i pokazywania aktualnych stanów logicznych na liniach SCL/SDA magistrali I2C (jak po włączeniu
skanera).
Jeśli podczas włączania zasilania zworka J1 (FLIP) będzie zwarta (ON), to wyświetlany obraz zostanie obrócony
o 180 stopni. Jeśli po włączeniu zasilania wyświetlacz nie zostanie wykryty, to skaner nie rozpocznie swojego dzia-
łania, a program zatrzyma się w pętli. Jeśli zamiast wyświetlacza 128x64 podłączy się 128x32, to pokazany na nim
obraz będzie nieczytelny (za mała rozdzielczość).


3. Szczegóły

Zaprogramowanie wyświetlania wszystkich dostępnych adresów I2C na jednym ekranie 128x64 pikseli, nie było łatwe
ze względu na ograniczenia sterownika SSD1306. Nie umożliwia on wyboru dowolnej pozycji Y (numer piksela w pio-
nie), od której będzie wyświetlany obraz, ani rysowania pojedynczych linii czy pikseli. Pionowa rozdzielczość (64 pikse-
le) jest podzielona na 8 wierszy (0-7), każdy po 8 pikseli wysokości. To powoduje, że najmniejszym fragmentem obrazu
jaki można narysować jest pionowa kolumna 8 pikseli (bajt danych), o współrzędnych startowych Y: 0, 8, 16, 24, 32, 40,
48 lub 56. Przy wyświetlaniu znaków (np. czcionki) o stałym rozmiarze 8x8 pikseli, nie stanowi to żadnego problemu.
Natomiast, aby zmieścić wszystkie dane na jednym ekranie, użyte cyfry (0-F) i symbole wykrytego/nieobecnego na
magistrali I2C urządzenia, mają rozmiar 7x7 pikseli. To powoduje, że rysowane jeden nad drugim, nachodzą na siebie
w kolejnych 8-pikselowych wierszach obrazu, więc nie ma możliwości ich niezależnego wyświetlania.
W bibliotekach Arduino do obsługi wyświetlaczy ze sterownikiem SSD1306, problem ten rozwiązano wprowadzając
bufor obrazu o rozmiarze 1kB (128x64 = 8192 bity/piksele = 1024 bajty), umieszczony w pamięci SRAM mikrokontro-
lera. Wszystkie funkcje rysujące operują tylko na danych w tym buforze, który następnie w całości jest kopiowany do
pamięci graficznej GDDRAM wyświetlacza. Dzięki temu możliwe jest rysowanie pojedynczych pikseli o dowolnych
współrzędnych X/Y. Jednak bufor obrazu wymaga użycia 1kB pamięci SRAM, której mikrokontrolery ATtiny24/44/84
mają znacznie mniej (128/256/512 bajtów), a same funkcje rysujące są trudne w implementacji, powolne (odświeżają
zawartość całego ekranu) i zajmują dużo pamięci FLASH mikrokontrolera.
Dlatego opracowałem własne i proste rozwiązanie. Kolumna z cyframi 0-7 jest zapisana w programie jako bitmapa
5x56 pikseli (35 bajtów + znacznik $FF), wyświetlana na ekranie w zakresie kolumn 5-9 oraz wierszy 1-7. Sterownik
SSD1306 automatycznie zmienia wartość wskaźnika kolumny/wiersza tak, aby kolejne bajty bitmapy były wyświetlane
w obszarze obrazu, który został ustalony zakresem skanowania kolumn/wierszy. Wiersz z cyframi 0-F jest zapisany
w programie jako bitmapa 112x8 pikseli (112 bajtów + znacznik $FFFF), wyświetlana na ekranie w zakresie kolumn
12-123 oraz wiersza 0.
Następnie adresy na magistrali I2C są skanowane w kolejności 0-127, a wynik detekcji urządzeń jest zapisywany
w pierwszych 16 bajtach pamięci SRAM mikrokontrolera. Każdy bit o wartości 1/0 odpowiada wykrytemu/nieobecne-
mu na magistrali urządzeniu. Algorytm sprawdza liczbę i pozycję wszystkich wykrytych/nieobecnych urządzeń, których
adresy znajdują się na ekranie jeden nad drugim, w 2 sąsiednich liniach adresów (górnej $x0-$xF i dolnej $y0-$yF).
W zależności od tego oraz od numeru aktualnie rysowanego wiersza (1-7) obrazu jest wyświetlana odpowiednia gra-
fika 7x7 pikseli, która zawiera symbole tych dwóch urządzeń jednocześnie (nachodzą na siebie). Symbole wszystkich
wykrytych/nieobecnych urządzeń tworzą siatkę, wyświetlaną na ekranie w zakresie kolumn 12-123 oraz wierszy 1-7.


4. Uruchomienie

Rezonator kwarcowy X1 taktujący pracę mikrokontrolera ma dość dokładną/stabilną częstotliwość, dzięki czemu
przebiegi czasowe sygnałów (O)SCL/(O)SDA są precyzyjne/symetryczne względem siebie. Istnieje też możliwość
taktowania mikrokontrolera jego wewnętrznym oscylatorem RC, o nominalnej częstotliwości 8 MHz. Zaletą tego roz-
wiązania jest to, że nie trzeba wtedy montować rezonatora X1 i kondensatorów C3/C4, ale dużą wadą jest bardzo
niedokładna/niestabilna częstotliwość taktująca, która powoduje pogorszenie jakości przebiegów czasowych sygna-
łów (O)SCL/(O)SDA. W praktyce, w normalnych warunkach nie ma to jednak większego wpływu na pracę skanera.
Kondensatory C1 i C2 filtrują napięcie zasilania. Rezystory R2/R3 podciągają do plusa zasilania linie SCL/SDA
badanej magistrali I2C. Trzeba pamiętać, że jeśli skaner jest zasilany z badanej magistrali (lub napięciem o zbliżo-
nej wartości), to rezystory te łączą się równolegle z jej rezystorami podciągającymi, a przez to maleją wypadkowe
rezystancje podciągające linie SCL/SDA.
Opcjonalne szeregowe rezystory R4/R5 na liniach SCL/SDA wraz z wewnętrznymi diodami zabezpieczającymi mi-
krokontrolera, zapewniają słabą ochronę jego pinów przed ewentualnym pojawieniem się niższego/wyższego niż
GND-0.5V/Vcc+0.5V napięcia, pochodzącego z badanej magistrali I2C. Oczywiście, jeśli takie wyższe napięcie Vin
(np. 5.5V) przechodzi przez rezystor podciągający Rp=3-10k badanej magistrali, to nie stanowi zagrożenia dla pinów
mikrokontrolera (przy Vcc=1.8-5.5V). Wynika to z maksymalnego dopuszczalnego prądu, który może płynąć przez
diody zabezpieczające i wynosi ok. 1mA - można go obliczyć ze wzoru Vin-(Vcc+0.5V)/Rp. Dopiero większy prąd
może spowodować uszkodzenie diody zabezpieczającej, a następnie pinu/portu mikrokontrolera.
Dawniej takie szeregowe rezystory o wartości ok. 300 omów były stosowane w telewizorach, aby zabezpieczać pra-
cujące w nich urządzenia I2C przed szpilkami wysokiego napięcia, które powstają w kineskopach i przedostają się
do linii SCL/SDA. Ponadto rezystory te znacznie redukują odbicia/zakłócenia, występujące zwłaszcza w długich liniach
SCL/SDA. Mają niewielką rezystancję, ponieważ zwiększa ona wartość napięcia niskiego stanu logicznego wyjścio-
wych sygnałów SCL/SDA oraz wydłuża czas opadania ich zboczy. Jeśli nie potrzebujemy takiej ochrony linii SCL/SDA
lub skaner nie działa z daną magistralą I2C, to zamiast rezystorów R4/R5 trzeba wlutować zworki.
Po wlutowaniu wszystkich elementów w typowej kolejności, upewniamy się o braku zwarć. Następnie programujemy
mikrokontroler właściwym dla jego częstotliwości pracy wsadem przez złącza CON1 (VCC) i CON4 (ISP), przy użyciu
dowolnego programatora ISP (In-System Programming). Konieczne jest również ustawienie odpowiednich wartości
fuse/lock bitów.
W przypadku, gdy mikrokontroler będzie taktowany rezonatorem kwarcowym X1=4-6/8-20 MHz: FL (Fuse Low):
$FD/$FF, FH (Fuse High): $DF, FE (Fuse Extended): $FF, LB (Lock Bits): $FF. Powodują one, że mikrokontroler
korzysta z zewnętrznego rezonatora kwarcowego (bity CKSEL3-0=1101/1111); wyłączony jest dzielnik częstotliwości
przez 8, co powoduje taktowanie mikrokontrolera pełną częstotliwością rezonatora (CKDIV8=1); wydłużony jest czas
jego startu do ok. 65ms po włączeniu napięcia zasilania (SUT1-0=11); wyłączone jest generowanie częstotliwości
taktującej mikrokontroler na pinie PB0 (CKOUT=1); włączona jest możliwość jego resetowania przez pin PC6
(RSTDISBL=1) oraz programowania przez interfejs szeregowy (SPIEN=0).
W przypadku, gdy mikrokontroler będzie taktowany wewnętrznym oscylatorem RC=8 MHz: FL (Fuse Low): $E2,
FH (Fuse High): $DF, FE (Fuse Extended): $FF, LB (Lock Bits): $FF. Powodują one, że mikrokontroler korzysta
z wewnętrznego oscylatora RC, o nominalnej częstotliwości 8 MHz (bity CKSEL3-0=0010); wyłączony jest dzielnik
częstotliwości przez 8, co powoduje taktowanie mikrokontrolera pełną częstotliwością oscylatora (CKDIV8=1);
wydłużony jest czas jego startu do ok. 65ms po włączeniu napięcia zasilania (SUT1-0=10); wyłączone jest genero-
wanie częstotliwości taktującej mikrokontroler na pinie PB0 (CKOUT=1); włączona jest możliwość jego resetowa-
nia przez pin PC6 (RSTDISBL=1) oraz programowania przez interfejs szeregowy (SPIEN=0).
Należy bardzo uważać, aby nie dokonać zmian w fuse/lock bitach, które uniemożliwią dalsze programowanie mikro-
kontrolera. Po zaprogramowaniu mikrokontrolera odłączamy programator, podłączamy wyświetlacz OLED do złącza
CON3 i włączamy zasilanie skanera, który jest już gotowy do działania. Ponieważ złącze CON4 (ISP) znajduje się
pod wyświetlaczem, musi on być odłączany przy każdym programowaniu.
Moduł wyświetlacza posiada wlutowaną listwę kołkową goldpin, która jest wpinana do żeńskiego złącza goldpin na
płytce skanera (pozwala to na jego łatwe odłączenie/wymianę). Można go też przylutować do płytki na krótkich drutach.
Wyświetlacze OLED mają różne wymiary, rozmieszczenie otworów montażowych oraz sygnałów na wyprowadzeniach
modułu. Płytka jest przystosowana do użycia wyświetlacza 128x64 o wymiarach 28x28mm, który ma sygnały rozmie-
szczone w kolejności: GND, VCC, SCL, SDA. Rezystory podciągające linie OSCL/OSDA dla OLED nie zostały umie-
szczone na płytce skanera, bo zawiera je płytka modułu wyświetlacza. Minimalne napięcie zasilania potrzebne do
działania wyświetlacza OLED, wynosi ok. Vcc=1.8V (niska jasność).
Skaner można zasilać napięciem stałym Vcc=2.7-5.5V z badanej magistrali I2C, zasilacza lub z baterii/akumulatorów
(np. z jednego ogniwa typu 18650). Nie jest on w żaden sposób zabezpieczony przed odwrotnym podłączeniem napię-
cia zasilania Vcc. Pomylenie polaryzacji tego napięcia spowoduje uszkodzenie mikrokontrolera. Pobór prądu z rezo-
natorem X1=4 MHz i wyświetlaczem OLED 128x64 pikseli przy napięciu Vcc=2.7/5V, wynosi maksymalnie 9.6/14mA
w stanie spoczynku (ekran wynikowy, wykryte 128 urządzeń - wtedy świeci najwięcej pikseli).
Wartość napięcia Vcc powinna być, jak najbardziej zbliżona (tolerancja +/- 10%) do wartości napięcia pracy badanej
magistrali I2C, aby mikrokontroler prawidłowo wykrywał pojawiające się na niej stany logiczne (VILmax = 0.3*Vcc,
VIHmin = 0.7*Vcc). Dzięki temu nie zostaną też przekroczone graniczne wartości napięcia wejściowego (VILmin =
GND-0.5V, VIHmax = Vcc+0.5V), co może spowodować uszkodzenie jego pinów do obsługi linii SCL/SDA (słabo
chronią przed tym opcjonalne rezystory R4/R5).
Skaner zmontowałem na płytce jednostronnej o wymiarach 45x45mm, wykonanej metodą transferu chemicznego.
W jej rogach znajdują się cztery otwory montażowe o średnicy 3mm, dzięki którym płytkę można przykręcić do
obudowy lub zamontować w nich jakieś nóżki, na których będzie ona stała.


SPIS ELEMENTÓW:

Rezystory:
R1-R3 - 10k
R4, R5 - 100

Kondensatory:
C1 - 10u/10V
C2 - 100n
C3, C4 - 22p
Układy scalone:
U1 - ATtiny24/44/84

Rezonatory:
X1 - kwarcowy 4-20 MHz (niski)

Przełączniki:
S1 - mikroprzełącznik
Złącza:
CON1, CON2, J1 - goldpin 2x1 (męskie)
CON3 - goldpin 4x1 (żeńskie), wysokość 8-9mm nad PCB
CON4 - goldpin 4x1 (męskie), wysokość 9mm nad PCB

Inne:
CON3 - wyświetlacz OLED z przylutowaną listwą kołkową
              goldpin 4x1, o wysokości 9mm nad PCB.
J1 - zworka 2x1