multilanguage

środa, 22 maja 2013

Uniwersalny licznik/generator

W ramach studiów musiałem stworzyć projekt na jeden z przedmiotów.
Pomyślałem, że to dobry czas na dokładne opracowanie uniwersalnego urządzenia, które posłuży do szybkiego tworzenia nowych projektów.



Tematem pracy było stworzenie cyfrowego licznika.
Z racji tego, że zalegało mi kilka pic16f1825, wybór padł na ten mikrokontroler
Nie jestem pewien czy nie będzie on za mały do bardziej skomplikowanych projektów, ale jak to mówią czas pokaże. Najwyżej będę stosował dwa mikrokontrolery ;)
Mikrokontroler zawiera następujące funkcje:
-wewnętrzny zegar o częstotliwości taktowania do 32MHz (8MIPS)
-szybki rdzeń (wszystkie funkcje prócz skoków wykonywane są w jednym cyklu zegarowym)
-1024 bajtów pamięci danych i 8k bajtów pamięci programu
-10 bitowy 12 kanałowy przetwornik analogowo-cyfrowy
-komparator pracujący w całym zakresie zasilania
-5 bitowy przetwornik cyfrowo analogowy
-programowalne źródło napięcia odniesienia
-4 liczniki 8bitowe z preskalerami
-jeden licznik 16 bitowy 
-dwa sprzętowe generatory PWM (korzystające z liczników)
-analogowy moduł do pomiaru pojemności przycisków (CaptiveTouch)
Niemalże wszystkie z tych funkcji są wykorzystywane. Ostatnim, niestety nie wykorzystywanym w projekcie układem jest wbudowany przerzutnik RS z możliwością sterowania z poziomu programu. Dzięki temu możliwa jest realizacja wielu funkcji na poziomie analogowym.

Mikrokontroler zawiera również w swojej strukturze sprzętowe wsparcie dla popularnych interfejsów komunikacyjnych takich jak: UART, SPI i I2C
Zawiera również modulator sygnałów cyfrowych (Data Signal Modulator(DSM)) pozwalający z wykorzystaniem innych peryferiów tworzyć własne interfejsy szeregowe lub komunikować się z już istniejącymi takimi jak IrDA lub tworzyć modulowany sygnał cyfrowy: ASK, FSK oraz PSK (odpowiednio modulacja amplitudy, częstotliwości i fazy sygnału). Mam już pomysł jak to wykorzystać.

Ponieważ zachciało mi się wyświetlacza LCD, a pic ilością wyprowadzeń  nie grzeszy, postanowiłem wykorzystać rejestr przesuwny (dokładnie 74HC595). Tu pojawił się mały problem z programem. Szukając gotowców w internecie nie trafiłem na nic w 100% się nadającego i ostatecznie napisałem całość sam.

Dodatkowo kolejnym problemem był czas odświeżania wyświetlacza. Chcąc oszczędzić na liczbie wyjść podłączyłem wejście enable wyświetlacza LCD również do rejestru przesuwnego, żeby uzyskać zmianę musiałem wpisywać wartość poszczególnych bitów dwukrotnie. W związku z tym że wyświetlacz ma 2x16 znaków, a musiałem dodatkowo wysłać dwie komendy pozycjonujące kursor wyszło:
(2*16+2)*8 (cały rejestr przesuwny)*2(zmiana linii enable)*2(sterowanie pół bajtami)=576 bajtów do wysłania.
Sporym problemem było tu również niezbyt optymalne przesuwanie bitowe. Nie dość że długie to jeszcze uzależniało położenie wyprowadzeń od wartości w rejestrach. Udało i się to rozwiązać tworząc unię dwóch struktur jednej z wartością poszczególnych danych, a drugą z poszczególnymi bitami. Dzięki temu zamiast korzystać z przesuwania bitowego można bezpośrednio odwoływać się do komórek w pamięci. Deklaracje takiej struktury przedstawiłem poniżej:

//deklaracja w pamięci
struct shift {
    unsigned char RS : 1;
    unsigned char Data : 4;
    unsigned char E : 1;
    unsigned char blank : 2;
};

struct shift_byte {
    unsigned char B0 : 1;
    unsigned char B1 : 1;
    unsigned char B2 : 1;
    unsigned char B3 : 1;
    unsigned char B4 : 1;
    unsigned char B5 : 1;
    unsigned char B6 : 1;
    unsigned char B7 : 1;
};

union unia {
    struct shift danel;
    struct shift_byte daneb;
};

//zapis i odczyt ze  struktur:
dane.danel.Data = dane_do_zapisu;
LCD_data = (dane.daneb.B7);
auto generated by http://tohtml.com/

W operacjach ustawiania bitów rejestru przesuwnego pominąłem tu jakiekolwiek pętle i kosztem pamięci wykonuje kolejno wszystkie instrukcje sterujące.
Obecnie cała procedura (wypełnienie całego wyświetlacza znakami) przy 8MIPS zajmuje dość długo bo około 30ms.
Chciałbym ją jeszcze zoptymalizować. Myślę, że dużym przyspieszeniem było by nie rozbijanie bajtów przy sterowaniu LCD na pół (skorzystanie z drugiego rejestru i sterowanie wszystkimi wyprowadzeniami), uprości to kod i dzięki temu otrzyma się również kilka dodatkowych wyjść ;)
Mam nadzieje, że niedługo uda mi się opracować uniwersalna wersję tego urządzenie w ładnej obudowie i z kawałkiem pola do prototypowania tak żeby konwertować się na funkcjonalności, a nie tworzeniu płytek. Poniżej przedstawiam kilka fotografii urządzenia.







Brak komentarzy:

Prześlij komentarz