Pierwszy raz z technologią wyświetlaczy LCD spotkaliśmy się w 13 odcinku kursu (EP 2023/11) – opracowaliśmy w nim moduł obsługujący 4-cyfrowy wyświetlacz 7-segmentowy. Opisywaliśmy wówczas dokładnie podstawy funkcjonowania takiego komponentu, a w szczególności sposób multipleksacji wyświetlacza, który ma cztery wyprowadzenia wspólne COM, a wszystkie jego elektrody steruje się czterema poziomami napięć. Gorąco zachęcam do odświeżenia informacji o podstawach multipleksacji LCD przed przeczytaniem niniejszego odcinka, ponieważ przebiega ona zupełnie inaczej niż w przypadku wyświetlaczy z diodami LED.
W naszym projekcie zastosujemy płytkę Segment14, opisaną w tym samym numerze „Elektroniki Praktycznej”. Współpracuje ona z płytką deweloperską MachXO2 Mega, używaną w poprzednich odcinkach kursu i zaprezentowaną w EP 2023/09. Można ją nabyć w sklepie AVT.
Na rysunku 1 zestawiono oznaczenia wszystkich segmentów w wyświetlaczu 14-segmentowym. Stanowią one standard przyjęty przez większość producentów, ale można spotkać różne nomenklatury w zakresie segmentu przecinka (punktu dziesiętnego) – czasem oznaczany jest literami DP od angielskiego decimal point, a innym razem po prostu P.
Zaprezentowane powyżej ułożenie segmentów umożliwia wyświetlanie znaków widocznych na rysunku 2. Choć wyświetlacz 14-segmentowy jest „wstecznie kompatybilny” z panelem 7-segmentowym, to można użyć dodatkowych segmentów, aby cyfry 1, 3 i 7 upodobnić do naturalnego kształtu tych znaków. Istnieje także możliwość wyświetlania niektórych małych liter, znaków interpunkcyjnych i wybranych symboli matematycznych.
Na płytce testowej zastosowano wyświetlacz VIM-828-DP13.2-RC-S-LV firmy Varitronix – o bardzo klasycznej topologii, przystosowany do pokazywania 8 znaków, bez żadnych dodatkowych ikonek i innych bajerów. Komponent ten nie ma wbudowanego sterownika, więc musimy opracować go sami. Działa on w trybie:
- 1/4 duty, co oznacza, że w danej chwili możliwe jest zaczernienie 1/4 segmentów, a więc sam wyświetlacz ma cztery elektrody wspólne COM,
- 1/3 bias, co znaczy, że napięcie doprowadzone do elektrod stopniuje się co 1/3 maksymalnej wartości napięcia zasilającego, a dokładniej są to napięcia równe 0 V, 1 V, 2 V oraz 3 V (części ułamkowe zaokrągliłem).
Model VIM-828 ma 36 elektrod, z czego 4 to elektrody wspólne COM, a 32 – elektrody sterujące segmentami. Multipleksacja wyświetlaczy LCD, w przeciwieństwie do wyświetlaczy LED, jest niestety dość mocno skomplikowana i wymaga zastanowienia się przez dłuższą chwilę, jak w ogóle opanować obsługę takiego ekranu.
Dla ułatwienia elektrody COM oraz odpowiadające im segmenty zaznaczono kolorami:
- Niebieski – COM0,
- Zielony – COM1,
- Żółty – COM2,
- Czerwony – COM3.
W każdej chwili aktywna jest tylko jedna z czterech elektrod COM, a to umożliwia zaczernienie tylko segmentów zaznaczonych kolorem odpowiadającym aktywnej elektrodzie wspólnej. Zaczernione zostaną jedynie te segmenty, których elektrody są aktywne, na przykład: aby włączyć segment A znaku nr 7, musimy jednocześnie aktywować elektrody COM0 oraz 7ABCP. Wszystkie pozostałe segmenty pozostaną niewidoczne.
Poprzez pojęcie „aktywny” rozumiemy stan, w którym do elektrody doprowadzamy odpowiednie napięcie. Różnica napięć między aktywną parą elektrody COM i elektrody segmentów wynosi ±3 V, a między nieaktywnymi elektrodami przyjmuje wartość ±1 V. Zjawisko to zostało dokładniej opisane w 13 odcinku kursu – wraz z ukazaniem dokładnych przebiegów napięć na elektrodach wyświetlacza.
Preprocesor
Poznamy nową funkcjonalność języka Verilog, z której jeszcze nie korzystaliśmy. Jest nią preprocesor (choć bardziej prawidłowo powinniśmy używać nazwy „dyrektywy kompilatora”). Programiści języka C i C++ polubią tę opcję, ponieważ preprocesor w Verilogu działa bardzo podobnie.
Poniżej wypisano najczęściej stosowane dyrektywy preprocesora:
- `define ZMIENNA – zdefiniowanie zmiennej bez wartości,
- `define ZMIENNA WARTOŚĆ – zdefiniowanie zmiennej i przypisanie do niej jakiejś wartości,
- `undef ZMIENNA – kasowanie definicji zmiennej,
- `include „plik.v” – dołączenie pliku.
Zwróć uwagę, że wszystkie dyrektywy poprzedzone zostały znakiem ukośnego apostrofu, w przeciwieństwie do C i C++, w których stosuje się znak #.
Istotną różnicą względem C i C++ jest to, że w celu odczytania wartości zdefiniowanej zmiennej musimy jej nazwę poprzedzić ukośnym apostrofem. Takie zmienne możemy wtedy stosować w kodzie tak samo, jak stałe określone parametrami.
Istnieje możliwość tworzenia instrukcji warunkowych. Przykłady takich operacji zaprezentowano na listingu 1. Na marginesie dodam, że tym, co w języku Verilog zawsze mnie dziwiło, jest brak najprostszej instrukcji warunkowej `if. Można sprawdzać tylko, czy jakaś zmienna została lub nie została zdefiniowania, natomiast nie można w żaden sposób sprawdzać jej wartości.
// Zdefiniowanie zmiennej A
`define A
// Sprawdzanie, czy zmienna jest zdefiniowana
`ifdef A
// Ten blok zostanie wykonany
`else
// Ten blok zostanie pominięty
`endif
// Sprawdzanie czy zmienna nie jest zdefiniowania
`ifndef A
// Ten blok zostanie pominięty
`else
// Ten blok zostanie wykonany
`endif
Listing 1. Przykłady instrukcji warunkowych
Jak już wiemy, wyświetlacz VIM-828 ma 36 pinów, a każdy ze znaków ma 14 segmentów plus kropkę. Oczywiście można by napisać sterownik tego wyświetlacza i posługiwać się w kodzie numerami wyprowadzeń oraz numerycznymi pozycjami segmentów w taki sposób, jak zrobiliśmy to, pisząc kod 4-cyfrowego wyświetlacza 7-segmentowego. Przy tak prostym wyświetlaczu było to jeszcze akceptowalnie wygodne, ale przy bardziej złożonym lepiej będzie przypisać wszystkim pinom jakieś etykiety tekstowe, aby uniknąć pomyłki. Użyjemy w tym celu definicji preprocesora.