ADuCino360: graficzny wskaźnik przyspieszenia 2D na mikrokontrolerze ADuCM360 (Cortex-M3 z Analog Devices)
Wyświetlacz graficzny – moduł KAmodTFT2
Do zobrazowywania wyników pomiarów przyspieszenia zastosowano moduł KAmodTFT2 z bardzo popularnym wyświetlaczem graficznym LCD od telefonu Nokia6100. Zastosowany moduł zawiera sterownik PCF8833, ale spotykane są również wersje wyświetlaczy ze sterownikiem Epsona. Przed przystąpieniem do prób warto upewnić się czy na pewno posiadany wyświetlacz ma sterownik PCF8833, gdyż obie wersje nie są ze sobą kompatybilne. O wyborze wyświetlacza w dużym stopniu decydowała jego stosunkowo niska cena oraz dobrej jakości matryca 132×132 punkty. Mimo niewielkich rozmiarów ekranu (25×25 mm) możliwe jest wyświetlanie grafiki z dużą liczbą szczegółów. Wyświetlacz jest skonfigurowany do pracy z 12-bitowym kolorem. Procesor przesyła dane do modułu przez interfejs SPI. Ten sam interfejs jest wykorzystywany do komunikacji procesora z czujnikiem przyspieszenia ADXL362. Linia Reset (zerowanie wyświetlacza) jest na stałe dołączona do napięcia +3,3 V, co oznacza, że sygnał ten nie jest wykorzystywany. Schemat połączenia modułu KAmodTFT2 do płytki ADuCino przedstawiono na rys 3.
Rys. 3. Schemat połączenia modułu wyświetlacza KAmodTFT2 do płytki ADuCino
Współdzielenie portu SPI
Mikrokontroler ADuCM360 ma w pełni dupleksowy podwójny interfejs SPI obsługiwany sprzętowo z przerwaniami. SPI1 może być obsługiwany przez kanał DMA. Obsługa sprzętowa oznacza, że wszystkie sygnały są sterowane automatycznie przez procesor bez udziału programu. Pozwala to na pełne wykorzystanie szybkości transmisji. Wśród wielu trybów pracy interfejsu nie ma niestety takiego, w którym są przesyłane dane 9-bitowe, a tego wymaga interfejs SPI zastosowany w wyświetlaczu. Dodatkowy bit jest wykorzystywany do rozróżniania typu przesyłanej informacji. Bit o wartości „0” oznacza, że do wyświetlacza będzie przesyłana komenda, zaś „1” oznacza transmisję danych opisujących tworzoną grafikę.
Jest jeszcze jedna trudność wynikająca z połączeń zastosowanych na płytce ADuCino, mianowicie sygnał CS interfejsu SPI0 jest na niej połączony „na sztywno” z wejściem CS akcelerometru ADXL362. Konieczne jest więc programowe generowanie sygnału CS dla modułu KAmodTFT2. Ręcznie jest też generowany 9. bit (właściwie pierwszy, z punktu widzenia kolejności wysyłania), pozostałe już sprzętowo. Całkowicie programowa obsługa komunikacji z wyświetlaczem spowodowałaby znaczne spowolnienie jego działania, co byłoby trudne do zaakceptowana. Aby obsługa interfejsu SPI0 przebiegała prawidłowo, konieczne jest odpowiednie wstępne skonfigurowanie portów mikrokontrolera. W trakcie dalszej pracy urządzenia konfiguracja ta ulega zmianom w kilku miejscach programu.
W aplikacji przyjęto obsługę komunikacji z wyświetlaczem i akcelerometrem bez przerwań, zrezygnowano również z zastosowania watchdoga. Na list. 1. przedstawiono fragment programu odpowiadający za inicjalizację mikrokontrolera, portów komunikacyjnych i urządzeń peryferyjnych. Jak widać, interfejs SPI0 jest taktowany przebiegiem o częstotliwości 4 MHz. Wynika to z maksymalnej częstotliwości pracy interfejsu wyświetlacza, która nie powinna być większa niż 6 MHz. Następna częstotliwość dostępna w mikrokontrolerze (8 MHz) byłaby więc zbyt wysoka. Parametry dotyczące interfejsów I2C, UART, PWM są w tej aplikacji bez znaczenia.
List. 1. Inicjalizacja systemu
//inicjalizacja systemu WdtGo(T3CON_ENABLE_DIS); //watchdog wylaczony //konfiguracja zegarow ClkCfg(CLK_CD0,CLK_HF,CLKSYSDIV_DIV2EN_DIS,CLK_UCLKCG); //system 16MHz ClkSel(CLK_CD1,CLK_CD0,CLK_CD7,CLK_CD7); //SPI: 4MHz, I2C: 16MHz, UART: - (125kHz), PWM: - (125kHz) ClkDis(CLKDIS_DISSPI1CLK|CLKDIS_DISUARTCLK|CLKDIS_DISPWMCLK|CLKDIS_DIST0CLK|CLKDIS_DIST1CLK|CLKDIS_DISDACCLK|CLKDIS_DISDMACLK|CLKDIS_DISADCCLK); //blokuj niewykorzystywane //Konfiguracja SPI0 (w tej wersji programu tryb ten nie jest jednak wykorzystywany SpiBaud(pADI_SPI0,0,SPIDIV_BCRST_DIS); //8MHz bez detekcji bledu linii CS SpiCfg(pADI_SPI0,SPICON_MOD_TX1RX1,SPICON_MASEN_EN,SPICON_CON_EN| SPICON_RXOF_EN|SPICON_ZEN_EN|SPICON_TIM_TXWR|SPICON_CPOL_HIGH|SPICON_CPHA_SAMPLETRAILING|SPICON_ENABLE_EN); //przerwanie po 1 wpisie do TX, tryb master, tryb ciagly //zezwolenie na nadpisanie RX, transmituj 00 jesli brak nowych danych w TX //inicjalizacja transmisji po wpisie do TX, probkowanie na opadajacym zboczu SCLK //SPI0 wlaczone CSAKC_H; DioCfg(pADI_GP1,0x2a00); //P1.7..4 jako SPI0 (MOSI, SCLK, MISO) w realizacji sprzetowej DioOen(pADI_GP1,0xe0); //P1.7 - CS_AKCEL, realizacja programowa CS SPI //P1.6 - MOSI, //P1.5 - SCLK CSLCD_H; DioOen(pADI_GP0,0x02); //P0.1 - CS LCD //NVIC_EnableIRQ(I2CM_IRQn); //przerwania I2C nie beda wykorzystywane //NVIC_EnableIRQ(SPI0_IRQn); //uaktywnij przerwania SPI0 - w tej wersji programu nie ma przerwan InitLcd(); //inicjalizacja wyswietlacza LCD InitAkcel(); //inicjalizacja akcelerometru ZapiszKomendeSpiLcd(SETCON); ZapiszDanaSpiLcd(48); //ustaw optymalny kontrast=45 LcdClearScreen(WHITE); //czysc ekran
Należy zwrócić uwagę na instrukcję: DioCfg(pADI_GP1,0x2a00); konfigurującą multiplekser portu P1 do pracy w trybie 10, w którym obsługuje on interfejs SPI0, ale bez sygnału CS. Sygnał ten będzie generowany programowo przez linię P1.7 dla akcelerometru i przez P0.1 dla wyświetlacza. Programowe generowanie 9. bitu dla wyświetlacza wymaga dostępu do linii MOSI i SCLK interfejsu SPI0. Jest to możliwe po tymczasowym przeprogramowaniu multipleksera do trybu 00 instrukcją DioCfg(pADI_GP1,0x0000), tak jak to pokazano np. na list. 2. W funkcjach obsługujących wyświetlacz zastosowano makra generujące odpowiednie stany na liniach sterujących interfejsu SPI0. Na przykład makro SCLKSPI_H ustawia linię SCLK w stan wysoki a SCLKSPI_L ją zeruje.
List. 2. Wysyłanie 9-bitowej danej przez interfejs SPI
void ZapiszDanaSpiLcd(unsigned char dana) { CSLCD_L; //uaktywnij CS SPI DioCfg(pADI_GP1,0x0000); //reczne sterowanie SPI MOSI_H; //generowanie 1. bitu (dziewiatego) = 0, bedzie 8-bitowa komenda SCLKSPI_L; //impuls zegarowy SCLKSPI_H; DioCfg(pADI_GP1,0x2a00); //powrot do sterowania automatycznego SpiTx(pADI_SPI0,dana); //wyslij komende delay(5); //opoznij wylaczenie CS LCD CSLCD_H; }
Po wygenerowaniu bitu definiującego typ przesyłanej informacji multiplekser portu P1 jest ponownie przeprogramowywany do trybu 10, po czym uruchamiana jest funkcja biblioteczna SpiTx(pADI_SPI0,dana). W wyniku jej działania dana jest wpisywana do rejestru nadawczego interfejsu SPI0, co powoduje automatyczne wysłanie ośmiu bitów z parametrami transmisji takimi, jakie zostały ustawione podczas inicjalizacji systemu. Przebiegi występujące na liniach interfejsu SPI podczas komunikacji z wyświetlaczem przedstawiono na rys. 4.
Rys. 4. Przebiegi na liniach interfejsu SPI0 podczas komunikacji z wyświetlaczem
Obsługa akcelerometru ADXL362
Czujniki przyspieszenia ADXL362 są obsługiwane przez rejestry sterujące i rejestr statusowy. Dostęp do określonego rejestru odbywa się po wcześniejszym przesłaniu typu informacji (instrukcja sterująca lub dana), zaadresowaniu odpowiedniego rejestru i przesłaniu danej (pojedynczej lub kilku). Przykład wysłania instrukcji sterującej do akcelerometru przedstawiono na rys. 5. W przeciwieństwie do metody zastosowanej przy obsłudze wyświetlacza, w akcelerometrze typ informacji jest przesyłany w postaci całego bajtu, nie pojedynczego bitu. Po nim następuje bajt adresujący rejestr, a następnie przesyłane są bajty danych. Zmierzone przyspieszenie jest przesyłane w dwóch bajtach. Każdy odczyt rejestrów danych jest poprzedzany sprawdzeniem czy w rejestrze statusowym jest ustawiony bit „Data Ready” sygnalizujący zakończenie pomiaru i skompletowanie danych w rejestrach czujnika. Odczytane przyspieszenia są normowane odpowiednio do zakresu wyświetlania i w obliczonych współrzędnych jest wyświetlane kółko symbolizujące koniec wektora przyspieszenia wypadkowego. Fragment programu realizujący to zadanie przedstawiono na list. 3.
Rys. 5. Przebiegi na liniach interfejsu SPI0 podczas komunikacji z akcelerometrem