[5] STM32CUBE w przykładach (obsługa monochromatycznego wyświetlacza graficznego LCD)

W tej części cyklu, poświęconemu programowaniu układów z rodziny STM32F4, na warsztat weźmiemy popularny monochromatyczny, graficzny wyświetlacz LCD, będący klonem wyświetlacza wykorzystywanego w telefonach Nokia 5110 oraz Nokia 3310.

Fot. 1. Wygląd modułu wyświetlacza

Jest to wyświetlacz graficzny, co oznacza, że w przeciwieństwie do wyświetlaczy znakowych, posiada on matryce tworzącą piksele – równomiernie rozmieszczone kwadraty o jednakowych wymiarach, a nie znaki, czy symbole. Na takim wyświetlaczu możemy wyświetlić dowolną grafikę, składającą się z pikseli, podobnie jak na monitorze komputera. Ma on rozdzielczość 84 x 48 px oraz jednobitową „skalę szarości” – dany punkt może być zapalony bądź wygaszony.

Wyświetlacze te, dostępne są w postaci płytek – modułów dla hobbystów, gotowych do podłączenia do zestawów rozwojowych, takich jak Arduino czy Nucleo. Możemy zasilać go oraz sterować nim, przy pomocy napięć 3.3V oraz 5V. Moduły występują w dwóch wariantach – z podświetleniem jasnoszarym oraz niebieskim. Wykorzystywana w nich matryca, działa podobnie jak matryca pasywno–odbiciowa w kalkulatorach, a więc „zapalone” piksele są czarne, a te „wygaszone” – przepuszczają światło. Moduły takie możemy kupić w wielu sklepach internetowych. Szukać należy pod hasłem „wyświetlacz Nokia 5110” lub „Nokia 5110 display”.

Zasada działania wyświetlacza LCD

Światło generowane przez diodę podświetlającą wyświetlacz od spodu jest polaryzowane pionowo podczas przejścia przez wstępny filtr polaryzacyjny, następnie przechodzi ono przez matrycę komórek ciekłego kryształu, przed i za którymi, znajdują się elektrody podłączone odpowiednio do wyprowadzeń wierszy i kolumn wyświetlacza, w taki sposób aby możliwe było sterowanie każdą z nich z osobna. Przepuszczenie przez ciekły kryształ prądu elektrycznego, o odpowiednich parametrach, powoduje obrót cząsteczek kryształu i skręcenie polaryzacji światła o 90 stopni. Dalej, światło trafia na kolejny filtr – analizator, odrzucający wszystkie skręcone wiązki i przepuszczający jedynie te spolaryzowane pionowo. W ten sposób, światło w wiązkach skręconych przez aktywne piksele nie dociera do naszych oczu i piksele te są widoczne jako czarne punkty.

Sterownik wyświetlacza

Sam wyświetlacz to jednak nie tylko matryca i dioda podświetlająca. Z matrycy ciekłokrystalicznej wyprowadzone są połączenia elektrod poziomych i pionowych, w liczbie odpowiadającej liczbie pikseli w wierszach i kolumnach – dla naszego wyświetlacza, będzie to 84 + 48 wyprowadzeń. Przepuszczając sygnał o odpowiednim napięciu i częstotliwości przez pary wyprowadzeń elektrod pionowych i poziomych, możemy sterować zachowaniem ciekłych kryształów w poszczególnych komórkach matrycy. Nie było by to jednak wygodne rozwiązanie, zarówno ze względu na konieczność zajęcia aż 132 wyprowadzeń mikrokontrolera, a także ze względu na konieczność generowania odpowiednich sygnałów w stałych odstępach czasowych na wszystkich pinach. Z pomocą przychodzą nam układy sterowników wyświetlaczy. W omawianym module znajduje się sterownik Philips PCD8544, ten sam, co zastosowany w telefonie komórkowym Nokia 3310.

Komunikacja ze sterownikami wyświetlaczy odbywa się za pomocą typowych interfejsów ze „świata mikrokontrolerów”, tj. SPI, I2C, czy UART. Do sterowników, w zależności od ich typów i zaawansowania, przesyłamy polecenia sterujące, mapy bitowe wyświetlanych ramek, tekst, w postaci ciągu znaków ASCII, rodzaju czcionki i informacji gdzie ma on zostać wyświetlony, czy mapy bitowe elementów i informacje gdzie należy je umieścić. Część kontrolerów posiada także wsparcie dla akceleracji graficznej, umożliwiając przykładowo przewijanie elementów znajdujących się na ekranie. Jeden sterownik może służyć do sterowania różnymi matrycami, zazwyczaj jednak jest on dość specyficzny i obsługuje wyświetlacze o z góry określonej, stałej, rozdzielczości i typie matrycy.

Sterownik Philips PCD8544

Sterownikiem Philips PCD8544, sterujemy przy pomocy interfejsu SPI, znanego z poprzedniej części niniejszego kursu. Przesyłamy nim polecenia sterujące i konfigurujące sterownik, do pracy z matrycą LCD oraz dane które chcemy wyświetlić na wyświetlaczu. Sterownik posiada pamięć RAM o pojemności odpowiadającej liczbie pikseli matrycy LCD – 84 * 48 bitów. Przechowywany jest w niej stan każdego punktu – zapalony, bądź wygaszony. Sterownik nie posiada wbudowanych czcionek, jest więc jedynie prostym buforem ramki – przesyłamy do niego mapę bitową pikseli matrycy. Jest ona zapisywana w pamięci RAM, a następnie ustawiana na matrycy poprzez wygenerowanie odpowiednich sygnałów sterujących przez sterownik.

Wyprowadzenia

Sterownik posiada wyprowadzenia o następujących oznaczeniach: RST, DC, CE, DIN oraz CLK, do których dochodzi jeszcze wyprowadzenie modułu – pin BL oraz piny zasilania i masy.

  • Wyprowadzenie RST odpowiada za reset układu – podanie, na ten pin, napięcia niskiego, a następnie wysokiego powoduje reset zawartości wszystkich rejestrów sterownika i przywrócenie domyślnej konfiguracji. Nie powoduje to jednak wyczyszczenia zawartości pamięci RAM – ta po uruchomieniu, może być wypełniona niezerowymi wartościami. Jest to obowiązkowa operacja po uruchomieniu układu, przed przystąpieniem do jego wykorzystania.
  • Pin DC umożliwia wybór, czy transmitowany, w danej chwili sygnał jest instrukcją sterującą, czy danymi do umieszczenia w pamięci RAM oraz wyrysowania na ekranie. Do transmisji poleceń, ustawiamy na nim stan logiczny niski, do transmisji danych – wysoki.
  • Pin CE – Clock Enable, blokuje i odblokowuje możliwość transmisji danych interfejsem SPI. Aby transmisja mogła się odbyć, na czas jej trwania, potrzebujemy ustawić na pinie CE stan logiczny wysoki.
  • DIN oraz CLK to piny interfejsu SPI. Pinem DIN odbywa się transmisja danych i poleceń sterujących. CLK to wejście zegarowe.
  • Przy pomocy piny BL sterujemy podświetleniem wyświetlacza – ustawienie stanu wysokiego, powoduje włączenie podświetlenia.

Oprócz, wymienionych powyżej, układ sterownika posiada jeszcze inne wyprowadzenia – testowe oraz sterujące. Nie są one wyprowadzone z modułu wyświetlacza, więc nie będziemy ich omawiać.

Polecenia sterujące i konfiguracja sterownika

Po restarcie wyświetlacza, musimy go skonfigurować – wybrać napięcie sygnału sterującego matrycą (co pośrednio powoduje ustalenie kontrastu), współczynnik bias – liczba progów napięć sygnału sterującego, współczynnik kompensacji temperaturowej oraz tryb pracy wyświetlacza. Odbywa się to poprzez przesyłanie rozkazów, mieszczących się wraz z ustawianymi wartościami w poszczególnych bajtach danych przesyłanych interfejsem SPI. Dane te transmitujemy z maksymalną szybkością do 4.0 Mb/s.

W poniższej tabeli znajduje się spis obsługiwanych przez sterownik wyświetlacza rozkazów, wraz z ich strukturą binarną.

Tab. 1. Zestaw instrukcji obsługiwanych przez sterownik wyświetlacza

Polecenia podzielone są na dwie grupy – zestaw poleceń rozszerzonych (H=1) oraz podstawowych (H=0). Przy pomocy poleceń rozszerzonych, konfigurujemy sterownik do pracy z konkretną matrycą. Polecenia podstawowe dotyczą trybu wyświetlania, sposobu transmisji danych do wyświetlacza oraz położenia „kursora”. Są też częściej wykorzystywane w trakcie pracy z wyświetlaczem.

Aby wejść w tryb poleceń rozszerzonych i skonfigurować wyświetlacz, musimy nadać interfejsem SPI ciąg bitów „00100001” (hex 0x21), żeby później przejść do trybu poleceń podstawowych – „00100000” (0x20). Wyzerowane parametry PD oraz V występujące odpowiednio na bicie nr 3 i 2 (licząc od prawej), odpowiadają odpowiednio za: włączenie chipu oraz ustawienie kierunku adresacji (o tym później).

Będąc w trybie poleceń rozszerzonych, ustawiamy kolejno:

  • napięcie sygnału sterującego (kontrast)

Napięcie sygnału sterującego jest zależne od wykorzystywanej matrycy i powinno być odpowiednio do niej dobrane. Im wyższa wartość, tym wyższy będzie kontrast wyświetlanych elementów, nie możemy jednak zwiększyć jej za bardzo – mogłoby to spowodować uszkodzenie matrycy. Napięcie ustawiamy poleceniem „1XXXXXXX”, gdzie „XXXXXXX” to liczba binarna, którą podstawiamy do wzoru „3.06 + XXXXXXX * 0.06 V”, aby uzyskać wartość napięcia. Dysponujemy więc zakresem od 3.06 V, do 10.74 V. Optymalna wartość dla opisywanego modułu to 5.34 V, a ustawiające ją polecenie sterujące, to: „11001000” (hex 0xB8).

  • współczynnik kompensacji temperaturowej

W zależności od temperatury matrycy, zmienia się kontrast wyświetlanych na niej elementów. W niższej temperaturze, kontrast jest niższy – ciekłe kryształy nie poruszają się tak bardzo, jak przy wyższej temperaturze i nie odchylają wystarczająco dobrze polaryzacji wiązki światła. Aby to skompensować, sterownik wyświetlacza może zwiększyć napięcie sterujące i zarazem kontrast, przy niższych temperaturach oraz zmniejszyć napięcie sterujące, przy wyższych. Do ustawienia współczynnika kompensacji temperaturowej służy polecenie „000001XX”, gdzie pod „XX”, podstawiamy wartość współczynnika z zakresu od „00” do „11” binarnie. Dla omawianego modułu, efekt ten nie jest zauważalny, możemy więc spokojnie wybrać wartość „00”.

  • współczynnik bias

Aby pobudzić ciekły kryształ do skręcenia, potrzebujemy przepuścić przez niego prąd przemienny. Im więcej pikseli/obszarów obsługiwanych jest przez pojedynczą elektrodę sterującą ciekłym kryształem (w parze z innymi elektrodami po przeciwnej stronie matrycy), tym więcej poziomów napięć powinien mieć nasz sygnał sterujący. Współczynnik bias decyduje o liczbie tych poziomów. Zmieniamy go przy pomocy polecenia „00010XXX”. Jego optymalna wartość dla tej ilości pikseli przypadających na elektrodę to 4 (dokładniej 1/8, bo wartość ta podstawiana jest do wzoru „1/n+4”), czyli „100” binarnie. Gotowy rozkaz konfiguracyjny przyjmie więc postać: „00010100” (0x14).

Po powrocie do trybu poleceń podstawowych, poleceniem „00001D0E”, musimy jeszcze wybrać tryb wyświetlania elementów:

  • D=0, E=0, polecenie: „00001000” (hex 0x08) – w tym trybie wszystkie piksele wyświetlacza będą wygaszone, tj. będą przepuszczały światło;
  • D=1, E=0, polecenie: „00001100” (hex 0x0C) – tryb normalny – jedynka w mapie bitowej odpowiadać będzie czarnemu punktowi na wyświetlaczu, a zero spowoduje że punkt ten będzie przepuszczał światło;
  • D=1, E=1, polecenie: „00001101” (hex 0x0D) – tryb odwrócony – jedynka odpowiada punktowi przepuszczającemu światło, a zero – blokującemu je;
  • D=0, E=1, polecenie: „00001001” (hex 0x09) – w tym trybie wszystkie piksele wyświetlacza będą ustawione, tj. będą blokowały światło.

Adresowanie i transmisja danych

Rys. 2. Struktura pamięci RAM sterownika Philips PCD8544

Dane przesyłane do sterownika, trafiają do pamięci RAM, a następnie „na matrycę”. Pamięć ta podzielona jest na 6 segmentów, które wybieramy, ustawiając adres poziomy (liczbę z zakresu od 0 do 5) oraz na 84 kolumny w każdym segmencie, które wybieramy, ustawiając adres pionowy (liczbę z zakresu od 0 do 83). Transmitując bajt danych (8 bitów), przesyłamy mapę bitową paska o wysokości 8 pikseli, umieszczanego pod wskazanym adresem, oraz rysowanego, w odpowiadającym mu miejscu na wyświetlaczu. Każdy bit odpowiada jednemu pikselowi – jedynka powoduje że, piksel będzie czarny, zero – że, przeźroczysty. Najbardziej znaczący bit tego bajtu danych, opisuje skrajnie dolny punkt paska.

Aby po przesłaniu każdego bajtu, nie była konieczna zmiana adresu, zdefiniowane zostały dwa tryby adresacji – wertykalny (pionowy) i horyzontalny (poziomy). Po przetransmitowaniu każdego bajtu, inkrementowany jest adres poziomy lub pionowy – w trybie horyzontalnym, kolejne „paski” będą umieszczane po prawej, względem uprzednio przesłanego. Gdy skończy się linia, kolejny „pasek” umieszczony zostanie w pierwszej kolumnie następnego segmentu, lub jeśli był to koniec ostatniego segmentu, w pierwszej kolumnie, pierwszego segmentu. W trybie wertykalnym, kolejne pasku umieszczane są pod poprzednimi. Gdy skończy się kolumna, kolejny pasek trafi do pierwszego wiersza kolejnej kolumny lub pierwszego wiersza, pierwszej kolumny. Dokładniej zostało to zobrazowane na rysunkach 3 i 4.

Rys. 3. Kolejność wypełniania komórek pamięci RAM i pikseli na ekranie, przy adresacji wertykalnej

 

Rys. 4. Kolejność wypełniania komórek pamięci RAM i pikseli na ekranie, przy adresacji horyzontalnej

Adresację pionową (wertykalną), będąc w trybie poleceń podstawowych, wybieramy poleceniem „00100010” (hex 0x22), poziomą (horyzontalną) – „00100000” (hex 0x20). Poleceniami „1XXXXXXX” oraz „01000YYY”, podstawiając za „XXXXXXX” oraz „YYY” odpowiednio nr kolumny i numer segmentu, wybieramy konkretny adres.

Aby teraz wyświetlić na wyświetlaczu mapę bitową, przesyłamy do niego kolejne bajty, w identyczny sposób jak polecenia, jednak wcześniej, ustawiamy na pinie DC, stan wysoki.

Do pobrania