sobota, 27 października 2012

Kalkulator CASIO fx-82ES PLUS i drażniący problem konwersji między systemami liczbowymi.

Jeśli już ktoś, kto zajmuje się informatyką i elektroniką cyfrową, decyduje się na zakup kalkulatora - często takie urządzenie bywa przydatne, a jak ktoś jest inżynierem, to posiadanie kalkulatora staje się nieodzowne (kalkulator to atrybut inżyniera) - chciałby, żeby jedną z jego podstawowych funkcjonalności była konwersja DEC->BIN->HEX->OCT->... A ponieważ tę funkcjonalność posiadają praktycznie wszystkie kalkulatory oznaczone napisem "scientific", nawet te bazarowe, zakupiłem kilka miesięcy temu wspomniany w tytule model, przejrzawszy wcześniej z grubsza jego funkcje. Właśnie - z grubsza. Okazało się, że kalkulatorek, który prowadzi obliczenia w zapisie naturalnym i jest naszpikowany wieloma funkcjami - w tym statystycznymi, potrafi obliczać wartości zadanej funkcji f(x) dla określonego przedziału x... nie ma wspomnianej konwersji!!! Miód po prostu... W pracy trzymam kalkulator za 12zł, który tę funkcjonalność posiada...
No ale trzeba sobie radzić. Oczywiście można dzielić sobie liczbę dziesiętną przez podstawę systemu docelowego, spisywać reszty z dzielenia itd. - znany algorytm. Ale do tego to w sumie kalkulatora nie trzeba - wystarczy kartka i ołówek. Odpada. Coś innego trzeba wymyślić...
I tak dziś, wykonując jakieś drobne obliczenia na tym wypas-kalkulatorze, przypomniał mi się problem konwersji i wymyśliłem sposób. Otóż jest w tym urządzonku wspomniana wcześniej funkcja obliczająca wartości f(x) dla pewnego przedziału x (x zmienia swoją wartość z zadanym krokiem). Wystarczy napisać funkcję, której wartości będą resztą z dzielenia x przez podstawę systemu liczbowego (testowałem na systemie binarnym, czyli 2), potem z uzyskanej tabelki spisać te wartości, które nas interesują (patrz: wspomniany wcześniej, popularny algorytm) i - voila! Mamy liczbę przekowertowaną!
A oto szczegóły:
  1. przełączamy kalkulator w tryb TABLE
  2. ustalamy liczbę miejsc dziesiętnych (FIX) na 0 - żeby funkcja Rnd zaokrąglała do wartości całkowitych
  3. funkcji, z której będziemy uzyskiwać wyniki, nadajemy postać f(x)=-(x-2Rnd(x/2)) - minus przed nawiasem, bo Rnd zaokrągla w górę, czyli np. 0,5 -> 1
  4. przedział dla x ustalamy od 0 do 12 (liczba, którą konwertujemy), z krokiem 1
  5. uruchamiamy proces i odczytujemy tabelkę :)
Podsumujmy więc:
  • zalety rozwiązania - bo jest to jakieś rozwiązanie problemu.
  • wady - sztuka dla sztuki, konieczność wspomagania się kartką, konwersja niewielkich liczb ze względu na ograniczoną pojemność pamięci kalkulatora...
No ale zawsze można się pobawić. Ot na przykład sprawdzić, jak kalkulator poradzi sobie z konwersją DEC->HEX :)

Inna rzecz, że gdyby się głębiej zastanowić, w konwersji DEC->BIN wystarczy tylko kartka i pisadło, nawet liczyć nie trzeba (nie wspomnę o konwersji niewielkich liczb w pamięci)...

czwartek, 25 października 2012

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ć).