[3] JAVA i STM32 – ekspresowy kurs programowania z MicroEJ – obsługa ADC i DAC

 

List. 1. Generacja GUI w metodzie main

W pierwszej instrukcji (MWT.RenderingContext.add(new PlainTheme());) ustawiany jest wygląd aplikacji. Obiekt PlainTheme zawiera instrukcje dotyczące m.in. koloru rysowanych komponentów i wykorzystywanych czcionek. Jest on zdefiniowany w bibliotece, jednak nic nie stoi na przeszkodzie aby utworzyć własny motyw graficzny.

Kolejne instrukcje tworzą krok po kroku interfejs graficzny. Jako pierwszy tworzony jest obiekt Desktop. Jest on przypisany do konkretnego wyświetlacza, przy czym każdy wyświetlacz może mieć przypisany tylko jeden obiekt tego typu. W systemie z jednym wyświetlaczem, obiekt Desktop jest przypisywany do niego domyślnie w konstruktorze. W przypadku większej ilości wyświetlaczy można wskazać do którego ma zostać przypisany nowo tworzony obiekt.

Kolejnym tworzonym obiektem jest Panel. Jest to kontener dla jednego, dowolnego widgetu. Panele są przypisywane do obiektów Desktop, dzięki czemu można je pokazywać, chować lub wymieniać dynamicznie w odpowiedzi na zdarzenia zewnętrzne.

Do obiektu Panel dołączany jest pierwszy z widgetów: GridComposite. Jest to jeden z widgetów, których zadaniem jest przechowywanie i pozycjonowanie innych obiektów. Dzięki temu na jednym panelu może znaleźć się wiele elementów poukładanych w różnych konfiguracjach. GridComposite układa elementy pionowo lub poziomo w siatce o określonym rozmiarze, w zależności od argumentów jego konstruktora. Jego elementami mogą być zarówno zwykłe widgety widoczne dla użytkownika, jak dodawany w następnej kolejności obiekt TitleLabel wyświetlający napis, jak i kolejne widgety pozycjonujące. Dzięki temu można swobodnie zaprojektować kompletny interfejs graficzny. W ten sposób zostały przygotowane kolejne dwie grupy widgetów grupujące elementy sterujące przetwornikami wewnątrz obiektów FlowComposite wyświetlających ich zawartość obok siebie w kolejności dodawania i przechodząc do nowej linii w przypadku braku miejsca. Po utworzeniu i dodaniu wszystkich potrzebnych elementów, cały interfejs jest wyświetlany na ekranie. Efekt można zobaczyć na rysunku 5.

Rys. 5. Interfejs graficzny do kontroli przetworników

Komentarza wymaga jeszcze konstruktor obiektu scaleDac:

       Scale scaleDac = new Scale(0, 300);

Przyjmuje od dwie wartości odpowiadające zakresie suwaka, a w tym przypadku także ustawieniom  wartości na wyjściu przetwornika cyfrowo-analogowego. Suwak został wyskalowany tak aby pojedynczy skok odpowiadał 10 mV, przez co wartość maksymalna powinna wygenerować 3000 mV na wyjściu. Dzięki temu aplikacja generuje mniej zdarzeń przy zmianie położenia suwaka kosztem rozdzielczości przetwornika.

Obsługa zdarzeń

Po wykonaniu interfejsu użytkownika należy jeszcze przygotować obsługę pochodzących od niego zdarzeń. W przedstawionej aplikacji są dwa komponenty mogące generować zdarzenia: buttonAdc typu Button oraz scaleDac typu Scale. Zasada obsługi ich zdarzeń jest identyczna jak w przypadku klasy EventGenerator z poprzedniego przykładu. Trzeba zatem utworzyć nowe klasy: DACScaleListener i ADCButtonListener implementujące ten sam co poprzednio interfejs Listener z metodami performAction. Tym razem jednak należy zaimplementować metodę przyjmującą dwa argumenty (performAction(int value, Object object)) – pierwszym z nich jest wartość, a drugim obiekt, który wygenerował zdarzenie. Oba obiekty słuchaczy mogą także ustawiać wartości pól tekstowych, odpowiednio dacValueField oraz adcValueField w odpowiedzi na zdarzenie. Obiekty te są przekazywane w konstruktorach słuchaczy.

Obsługa przetworników (Java)

Ostatnią częścią aplikacji Javy jest kontrola przetworników. W przykładzie będzie się ona ograniczać do konfiguracji i odczytu wartości ADC lub ustawienia wartości DAC. Do tego zadania powstaną dwie dodatkowe klasy udostępniające wymienione metody pozostałym obiektom aplikacji.

Kod odpowiedzialny za obsługę peryferii zostanie dodany do warstwy BSP, jednak aplikacja Javy musi być w stanie wywołać odpowiednie funkcje C. Do tego celu w MicroEJ został udostępniony mechanizm o nazwie SNI (Simple Native Interface), który umożliwia m.in. wywoływanie funkcji C z poziomu aplikacji Javy. Aplikacja nie wie nic na temat zawartości tych funkcji – zna jedynie ich nazwy, listy argumentów oraz typy wartości zwracanych. Wystarczy je zadeklarować wewnątrz klasy z użyciem słów kluczowych ’static native’, tak jak zostało to pokazane na listingach 2 i 3, zawierających kod klas ADC i DAC.

List. 2. Kod klasy ADC

List. 3. Kod klasy DAC

Dzięki obiektom klas ADC i DAC, obiekty słuchaczy interfejsu użytkownika mogą uzyskać dostęp do przetworników i odczytywać oraz zmieniać ich wartość. Kod słuchaczy pokazany został na listingach 4 i 5.

List. 4. Kod klasy ADCButtonListener

List. 5. Kod klasy DACScaleListener

Na koniec pozostało już tylko utworzyć i dodać słuchaczy do komponentów graficznych oraz utworzyć obiekty klas ADC i DAC oraz zainicjalizować przetworniki. Wszystkie te czynności można wykonać w metodzie main, której pełen kod został przedstawiony na listingu 6.

Do pobrania

O autorze