Przejdź do głównej zawartości

Programowanie AVR cz. 3: ATtiny2313, EEPROM AT24C04C i magistrala I2C. Oraz krótko o pewnej zapomnianej obietnicy.

000 wstęp

Głównym bohaterem tego posta jest magistrala I2C, zwana również interfejsem dwuprzewodowym (ang. Two-wire lub 2-wire interface). To proste łącze wykorzystywane jest w wielu ciekawych układach mogących współpracować z mikrokontrolerami i nie tylko. Można tu wspomnieć - żeby nie było, że użyłem słowa "wielu" bez pokrycia - choćby o układach pamięci, zegarach czasu rzeczywistego, przetwornikach AC/CA...
Co prawda "małe" mikrokontrolery nie mają dedykowanych linii dla I2C, ale dzięki środowiskom i bibliotekom dla programistów, zapewniającym pełną implementację m. in. protokołu I2C, mamy możliwość bezproblemowego wykorzystania dobrodziejstw tej magistrali posługując się uniwersalnymi liniami wejścia - wyjścia. Można też podjąć się samodzielnej implementacji obsługi tej magistrali - jeśli ktoś lubi takie wyzwania.

Na początek jednak warto przyjrzeć się samej idei i koncepcji magistrali I2C:
Dobrze by było też przeanalizować kartę katalogową układu AT24C04C (zakładam, że Tiny2313 już dość dobrze znamy):

Układ AT24C04C - jak sugeruje tytuł posta - to pamięć EEPROM. Nie jest to jednak kostka pamięci w klasycznym tego słowa rozumieniu, z wieloma liniami adresowymi i danych oraz liniami sterującymi - mówimy o tym układzie "pamięć szeregowa", ponieważ dostęp do jej zawartości uzyskujemy właśnie poprzez szeregową magistralę I2C. Taka konstrukcja pamięci pozwoliła przede wszystkim na zmniejszenie fizycznych rozmiarów układu do np. typowej kostki w obudowie DIP-8 (dwa rzędy po cztery wyprowadzenia), co sprzyja wykorzystaniu tego układu w małogabarytowych projektach.
Przy okazji przeglądania (analizy!) karty katalogowej AT24C04C, możemy się wiele dowiedzieć na temat samej magistrali, tym razem już konkretnie - głównie chodzi tu o protokół, sposób adresacji urządzeń itp. Ze względu zaś na prostotę operacji - bo w przypadku pamięci mamy wyłącznie zapis i odczyt bez dodatkowych czynności - AT24C04C jest rewelacyjnym środkiem dydaktycznym i znakomitym przykładem na początek przygody z naszą magistralą.

A dlaczego właśnie 24C04, a nie np. 24C08? Proste: taką kostkę akurat miałem...

No to zaczynamy!

001 przygotowanie układu

Trzeba pamiętać, że wiele układów cyfrowych przeznaczonych do współpracy z innymi układami za pomocą magistral, posiada wyjścia typu otwarty kolektor (otwarty dren). Żeby się nie rozpisywać - chodzi tutaj o "końcówkę mocy" wyjścia układu; jest ona niepełna, co daje możliwość dostosowania obciążenia układu w dużo większym zakresie, niż ma to miejsce w przypadku klasycznych wyjść cyfrowych. Dostosowanie obciążenia (to w pewnym sensie skrót myślowy - zainteresowanych odsyłam do literatury technicznej dotyczącej podstaw elektroniki) wykonuje się przy pomocy rezystorów podciągających, które stanowią uzupełnienie owego niekompletnego wyjścia układu. W przypadku I2C konieczne jest zastosowanie właśnie takich rezystorów dla obu linii (SCL i SDA); wartość tych rezystorów należy odpowiednio dobrać - w przypadku naszego układu będzie to 4,7kΩ. Oczywiście rezystor podciągający włączamy między zasilanie a linię magistrali. Dodatkowo linie I2C należy podłączyć do mikrokontrolera poprzez rezystory o wartości 300-330Ω.
Następnym krokiem w procesie przygotowania układu testowego jest ustalenie adresu sprzętowego dla kostki pamięci. Adresy urządzeń na magistrali I2C to liczby 7-bitowe. Ósmy bit (a w zasadzie pierwszy, bo na najmniej znaczącej pozycji) to znacznik kierunku transmisji - wartość "1" oznacza odczyt z urządzenia, "0" to zapis do urządzenia. Wynika z tego, że każde urządzenie ma dwa adresy 8-bitowe... Przeglądając dokumentację AT24C04 natkniemy się w którymś momencie właśnie na opis adresowania tego układu. Cztery najstarsze bity adresu 24C04 zawierają "zaszytą" sekwencję "1010", dalej brane są pod uwagę stany zadane na wyprowadzenia A2 i A1 układu (A0 jest ignorowane w przypadku 24C04), następnie mamy znacznik "banku" pamięci P0 i bit kierunku R/W. Co do znacznika banku pamięci - należy zwrócić uwagę, że układ 24C04 ma pojemność 4kb czyli 512B. Ponieważ przez magistralę I2C można przesyłać dane tylko w postaci paczek 8-bitowych, nie ma możliwości "płaskiego" adresowania całej zawartości pamięci - za pomocą liczby 8-bitowej jesteśmy w stanie zaadresować jedynie połowę zawartości tej pamięci, czyli 256B (24C04 ma organizację bajtową). Tutaj właśnie z pomocą przychodzi nam znacznik P0, który stanowi przełącznik dla owych połówek pamięci - np. dla P0=1 komórka pamięci o adresie 00h to tak naprawdę komórka o adresie 100h.
W naszym układzie testowym ustalamy wartość bitów A2 i A1 jako "0" (podłączamy do masy).
Jak się ostatecznie okazuje, nasz układ pamięci ma aż cztery adresy na magistrali I2C! Adresy te, już w postaci liczbowej dziesiętnej, znajdziecie w prezentowanym w dalszej części artykułu listingu programu.
Na koniec zerujemy wejście układu pamięci oznaczone jako WP (Write Protect), żeby zapewnić sobie możliwość swobodnego zapisu i odczytu.

Na poniższym schemacie widzimy już kompletny układ do testowania pamięci 24C04 i magistrali I2C:



Dodatkowo, w celu wizualizacji procesu poprawnego (lub nie) zapisu i odczytu pamięci, dołączyłem do układu testowego wyświetlacz LCD (na schemacie jest to wyświetlacz 16*2 - w rzeczywistości użyłem 16*1a) - klasyczny, na bazie układu kompatybilnego z HD44780 oraz dwie diody LED. Program (przedstawiony dalej) uruchamiany jest przyciskiem, który na schemacie widnieje pod postacią jumpera TEST J1 - tutaj też użyłem symbolu zastępczego (muszę uzupełnić biblioteki Eagle'a).

002 program

Żeby hardware był użyteczny, potrzebny jest software... Na listingu poniżej widnieje program testowy, którego zadaniem jest zapełnienie obu banków pamięci pewnymi wartościami (dla każdego banku jest to inna wartość), a następnie sprawdzenie, czy dane zostały prawidłowo zapisane - czyli odczytanie zawartości obu banków i porównanie liczby odczytanej z zakładaną wartością poprawną.



Polecam przeanalizowanie programu, ze szczególnym zwróceniem uwagi na to, jak elegancko zostały zaprojektowane funkcje BASCOMa operujące na magistrali I2C - odzwierciedlają one dość dokładnie "protokół" logiczny tej magistrali.

Należy zdać sobie sprawę, że sporą część kodu stanowią ozdobniki związane z wizualizacją operacji - stąd program po kompilacji zajmuje ok. 1,5kB. Same operacje komunikacji z I2C są tutaj w miarę lekkie.

Ktoś pomyśli: no ok, działa...
...ale jak sprawdzić, czy faktycznie? Bo każde następne uruchomienie spowoduje - w przypadku nieudanego zapisu - odczyt wcześniej zapisanych do pamięci danych, które są oczywiście poprawne. Sprawa jest prosta - trzeba przekompilować program z innymi wartościami Val_p0Val_p1. A jeśli ktoś chce sprawdzić, jak to jest z tymi rezystorami podciągającymi - zachęcam do wyjęcia jednego z nich (lub obu) w trakcie pracy układu. Efekty specjalne gwarantowane (spokojnie, jeśli nie zrobicie gdzieś jakiegoś zwarcia, nic się nie spali).

003 todo

Jeśli nic nie pomyliliśmy, to nasz układ do testowania I2C powinien działać bez problemów. Nie wiem, jak Wy, ale ja zwykle lubię troszkę podrążyć temat (sukces jest najlepszą zachętą) - proponuję więc przyjrzenie się układowi PCF8583P. Jest to zegar czasu rzeczywistego z kalendarzem - oczywiście obsługiwany poprzez I2C i umieszczony, podobnie jak AT24C04, w malutkiej obudowie ośmiowyprowadzeniowej. Podłączamy do niego oscylator (ok. 34kHz), kondensatorek 33pF, zapewniamy ciągły dostęp zasilania (można z baterii) i... Ale o tym być może wkrótce :) Zachęcam również do samodzielnych eksperymentów.

Postscriptum

Dawno temu obiecałem (tak, czego ja już na tym blogu nie obiecywałem...) program do przekształcenia ATtiny 2313 w układ sterowania linijką świetlną. Oto i on:



Jeżeli chodzi o elektronikę, do portu B mikrokontrolera podłączamy osiem diod LED poprzez rezystor 220Ω (podobnie jak na schemacie pokazanym wcześniej), zaś do wskazanych na listingu wyprowadzeń portu D - przyciski zwierające do masy. Do tego oczywiście oscylator 4MHz z dwoma kondensatorkami 33pF (również jak na wcześniejszym schemacie).

Po wgraniu programu można pobawić się efektami świetlnymi (proszę zwrócić uwagę, że efekt "spoczynkowy" jest generowany przez pracujący w tle timer, natomiast definicje efektów umieszczone są w wewnętrznej pamięci EEPROM mikrokontrolera).
Udanych eksperymentów zatem!

ERRATA czy też konieczny, acz zapomniany dopisek

Zagłębiając się w adresowanie układów na magistrali I2C i podłączanie ich do niej, zapomniałem o czymś, co wprawdzie łatwo można znaleźć w kodzie programu (pierwszy listing), ale co nie rzuca się specjalnie w oczy. A powinno.
Otóż jako wyjścia magistrali I2C mikrokontrolera ATtiny 2313 mogą zostać użyte dowolne dwie linie portów wejścia-wyjścia. U mnie, m. in. ze względu na konieczność podłączenia wyświetlacza, jako wyprowadzenia I2C "robią" linie (wyjścia) PORTB.1 (SCL) i PORTB.0 (SDA). Konfiguracji tych wyjść można dokonać z poziomu środowiska BASCOMa (Options -> Compiler -> I2C):


Dodatkowo zalecałbym wstawienie do kodu, przed deklaracjami zmiennych, dwóch linijek, których znaczenie jest to samo, jak powyższych ustawień środowiska dla I2C:
Config Scl = Portb.1
Config Sda = Portb.0
Dublowanie konfiguracji nie jest szkodliwe, a w tym przypadku wręcz pożądane (uniezależnimy się od konfiguracji środowiska - czasem po prostu możemy o niej zapomnieć).

Komentarze

Popularne posty z tego bloga

Niesamowicie prosty czujnik zmierzchowy.

Tym razem zero programowania, będzie natomiast nostalgiczno-wspomnieniowy układzik, lekko zmodyfikowany. Otóż kilka dni temu rozmawialiśmy w gronie znajomych o różnego rodzaju czujnikach zmierzchowych i czujnikach ruchu. Ponieważ należę do tych wariatów, co to hołdują jeszcze owej przestarzałej i kompletnie odrealnionej dziś zasadzie: "po co kupować, gdy można zrobić", stwierdziłem, że poskładam takie coś (czujnik zmierzchowy; sensor ruchu faktycznie lepiej nabyć, choćby ze względu na rozmiary ;)) i być może podłączę do jakiegoś mikrokontrolera. Przypomniało mi się też przy okazji, że znalazłem ostatnio w elektronicznych śmieciach stary fotorezystor (dla niewtajemniczonych: element zmieniający rezystancję, czyli opór elektryczny, pod wpływem działania strumienia światła) RPP130, jeden z kilku pozostałych po montowanych wieki temu układach tranzystorowych do zdalnego sterowania pracą urządzeń za pomocą latarki... No OK, nie było to specjalnie rozbudowane zdalne sterowanie ;)

Płytka prototypowa na bazie ESP8266 (ESP-01)

To nie jest kolejny artykuł traktujący od początku do... nieco dalej (bo na pewno nie do końca) o płytkach ESP8266 . Żeby się dowiedzieć, co to takiego, odwiedźcie proszę np. tę stronę (oraz wiele innych – poproście o pomoc Waszą ulubioną wyszukiwarkę): http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family . No ale żeby nie było, ESP8266 to układ zawierający na pokładzie wydajny mikrokontroler z rdzeniem RISC-owym, taktowany zegarem 40MHz (wersja, o której jest ten wpis) lub 80MHz, 512KB pamięci flash i podsystem komunikacji przez sieć WiFi . Jest powszechnie wykorzystywany jako swego rodzaju karta sieciowa do połączeń bezprzewodowych naszych urządzeń IoT , które budujemy w zaciszu domowych laboratoriów (i nie tylko). Układ montowany jest na płytkach występujących w kilku wersjach, różniących się przede wszystkim liczbą wyprowadzeń uniwersalnych, czyli GPIO – im większa liczba, tym większe możliwości wykorzystania układu (więcej urządzeń peryferyjnych itp.). Są też pewne

Programowanie AVR cz.8: Przetwornik analogowo-cyfrowy oraz modulacja szerokości impulsu.

Dziś kolejny wgląd w wyposażenie mikrokontrolera ATmega48P - tym razem przyglądamy się wbudowanemu w układ przetwornikowi analogowo-cyfrowemu oraz - dostępnej również w modelach ATtiny - modulacji szerokości impulsu realizowanej przez timery. Artykuł ten jest w pewnym sensie wstępem do następnego, który pojawi się już wkrótce, a którego tematykę zdradziłem na końcu. Przetwornik A-C (skrót spotykany w anglojęzycznej literaturze to ADC od Analog to Digital Converter ) to układ pozwalający na zamianę wartości napięcia (elektrycznego sygnału analogowego ;-)) na liczbę. W przypadku mojej ATmegi przetwornik ma rozdzielczość 10-bitową, co oznacza, że wartość napięcia podawanego na wejście przetwornika może być po konwersji zapisana jako liczba z przedziału od 0 do 1023 (musimy użyć zmiennej word do zapamiętania tej liczby). Jeśli jesteśmy w posiadaniu mikrokontrolera w obudowie PDIP 28-wyprowadzeniowej, to mamy do dyspozycji sześć kanałów (niezależnych wejść) przetwornika A-C, przyporzą