16-znakowy wyświetlacz ASCII LED
Można powiedzieć, że całe „lata temu” opracowałem moduł wyświetlacza ASCII. Opisywałem też sposób połączenia dwóch takich wyświetlaczy oraz wyświetlania komunikatów. Wydaje się, że to żaden problem, ponieważ wewnątrz ich kontrolera jest szeregowy rejestr przesuwny z zatrzaskiem na wyjściach. Wystarczy w takt impulsów zegarowych szeregowo przesłać liczbę bitów odpowiadającą liczbie połączonych rejestrów i po sprawie. Tak można zrobić, jeśli wyświetlacze pracują w tej samej pozycji, jednak niekiedy może zajść potrzeba ich odwrócenia np. o 180 stopni. Jak sobie wtedy poradzić?
Płytka wyświetlacza jest wykonana w taki sposób, że matryce LED są montowane na „górze” płytki. Umowny dół, ze względu na zamontowane pod spodem układy scalone źródeł prądowych, jest nieco szerszy. Powoduje to duży odstęp pomiędzy znakami, jeśli dwie linie wyświetlaczy zostaną złożone w normalny sposób. W takiej sytuacji warto je złożyć odwrócone o 180 stopni, jak na fotografii tytułowej. Samo połączenie wyświetlaczy nie przedstawia kłopotu – wystarczy nieco dłuższy przewód, jak pokazano na fotografii. Trzeba też wykonać jakąś ramkę lub odpowiednio przymocować wyświetlacze do obudowy i to tyle. Nieco trudniej jest z wykonaniem programu sterującego tak połączonymi wyświetlaczami.
Jak pamiętamy, rejestry danych wyświetlaczy są połączone szeregowo. To oznacza, że dane do pierwszego wyświetlacza muszą być przesyłane na samym końcu. Wyświetlanie odbywa się metodą linia po linii. Do rejestrów przesuwnych są wysyłane kompletne linie – przyjęto, że jako pierwsza jest zaświecana linia na samej górze, najwyższa w znaku. Następnie jest ona gaszona, przesyłane są dane kolejnej linii, ta kolejna linia jest zaświecana i gaszona, i tak 7 razy, bo z tylu linii składa się każdy znak – 5 pikseli w poziomie i 7 w pionie. Zaświecenie i gaszenie pikseli odbywa się z częstotliwością około 300Hz i jest niezauważalne dla ludzkiego oka. Była o tym mowa w poprzednich artykułach – można je znaleźć na tej stronie internetowej.
Wyświetlacz opisywany w tym przykładzie jest złożony z 4 modułów, każdy po 4 znaki. Moduły są połączone parami – 2 razy po 2. Wyjście pierwszej pary modułów jest dołączone do wejścia drugiej pary, która jest obrócona o 180 stopni. Pierwsza para modułów tworzy dolną linię wyświetlacza, a druga górną. Wyświetlacz może wyświetlać 16 znaków alfanumerycznych, jak typowy moduł wyświetlacza tekstowego LCD o rozdzielczości 2 linie×8 znaków. Co prawda, w oprogramowaniu nie ma aż tak bogatego zestawu znaków, jaki zawiera w pamięci np. kontroler HD44780, ale nic nie stoi na przeszkodzie, aby takie dodatkowe znaki wykonać samodzielnie definiując np. polskie „ogonki”, cyrylicę czy inne znaki narodowe. Dla wygody użytkownika, w pamięci mikrokontrolera zadeklarowano bufor display mieszczący 16 znaków. Znak umieszczony w buforze na pozycji [0] jest wyświetlany w prawym, górnym rogu, znak z pozycji [8] w lewym, dolnym rogu, a znak z pozycji [15] w prawym, dolnym rogu. W ten sposób łatwo wyświetlić komunikat po prostu wpisując znaki w odpowiednie miejsca bufora display. Resztą zajmie się procedura obsługi przerwania od przepełnienia licznika Timera0, wysyłająca znaki do wyświetlacza.
O ile znaki w dolnej linii wyświetlacza mogą być wysyłane wprost z tablicy zawierającej ich wzorce (trafiają do niej bajty z bufora displayspod indeksów od 8 do 15), o tyle przy wysyłaniu znaków do „przekręconych{ modułów w górnej linii trzeba uprawiać pewną żonglerkę (przyjęto, że pozycje wyświetlacza również są numerowane od 0 do 15 z tym, że pozycji 0 odpowiada prawy, górny róg wyświetlacza):
- znaki spod indeksów od 0 do 3 bufora display trafiają, odpowiednio, na pozycje od 15 do 12 wyświetlacza,
- znaki spod indeksów od 4 do 7 bufora display trafiają, odpowiednio, na pozycje od 11 do 8 wyświetlacza.
„Żonglerka” bitami jest wykonywana w procedurze obsługi przerwania wysyłającego dane do wyświetlacza. Samą funkcję obsługi przerwania oraz sposób jej działania omówiono we wcześniejszych artykułach, więc tu skupmy się jedynie na funkcjonalności odwracania wyświetlanych znaków oraz łączenia modułów wyświetlaczy.
Wzorzec wyświetlanego znaku jest zapisany w tablicy ascii_table[]. Na kolejnych jej pozycjach zapisano bajty będące wzorcami znaków z tym, że logiczne 0 odpowiada pikselowi zaświeconemu, a logiczna 1 pikselowi zgaszonemu. Za załączanie linii znaków odpowiada trzeci rejestr w szeregu. Z kolei tutaj, logiczne 0 odpowiada linii zaświeconej, a logiczna 1 linii zgaszonej.
Dla potrzeb zaświecania lub gaszenia poszczególnych linii czy pikseli zdefiniowano makro CHECK_BIT(zmienna, pozycja) służące do testowania bitów:
//makro do testowania bitów w zmiennej
#define CHECK_BIT(var,pos)((var)&(1<<(pos)))
Działanie makra polega na wykonywaniu operacji bitowej AND zmiennej oraz stałej z ustawionym bitem na testowanej pozycji. Jak łatwo się domyślić, rezultat iloczynu zmiennej oraz stałej jest zwracany jako wynik testu. Na bazie tego makra wykonano również dwa inne, służące do ustawiania (SET_BIT) lub zerowania bitu w zmiennej (CLR_BIT):
//makra do ustawiania/zerowania bitów
#defineSET_BIT(var,pos)((var)|=(1<<(pos)))
#defineCLR_BIT(var,pos)((var)&=~(1<<(pos)))
Linia znaku do wyświetlenia jest pobierana z tablicy wzorców na podstawie kodu zapisanego w buforze display. Numer znaku do pobrania jest wyznaczany i zapamiętywany w zmiennej offset.
offset=(display[4-j]*8)+linia;
zalacz=ascii_table[offset];
Makra zdefiniowano w jednym celu – ich użycie ułatwia testowanie bitów zmiennej w dowolnej kolejności, co bardzo przyda się do odwracania znaków na wyświetlaczu. Jak pamiętamy, wzorce znaków są pobierane z tablicy ascii_table i wyświetlane linia po linii, więc aby odwrócić znak o 180 stopni należy zmienić kolejność załączania linii. Reasumując, jeśli chcemy wyświetlić znak normalnie należy poszczególne linie załączać w kolejności:
for(i=0;i<8;i++)
{
/* znaki wyświetlane normalnie */
if(CHECK_BIT(zalacz,8-i))SET_DIN;elseCLR_DIN;
...
Jeśli znaki mają być odwrócone o 180 stopni, to poszczególne linie należy załączać w kolejności:
for(i=0;i<8;i++)
{
/* znaki odbite wzdłuż osi OX */
if(CHECK_BIT(zalacz,i))SET_DIN;elseCLR_DIN;
...
Jednak w ten sposób – jak łatwo się przekonać – otrzymamy odbicie lustrzane znaku, ponieważ dokonaliśmy odbicia symetrycznego tylko wzdłuż jednej z osi. Dlatego też trzeba odwrócić kolejność pobierania lub testowania bitów, aby wykonać kolejną transformację i otrzymać na wyświetlaczu znak o normalnym wyglądzie:
zalacz=ascii_table[offset];
for(i=0;i<5;i++)
{
/* znaki odbite wzdłuż osi OY */
if(CHECK_BIT(zalacz,i+3))SET_DIN;elseCLR_DIN;
...
Testowanie bitów w znaku bez transformacji odbywa się w następującej kolejności:
zalacz=ascii_table[offset];
for(i=0;i<5;i++)
{
/* znaki wyświetlane normalnie */
if(CHECK_BIT(zalacz,7-i))SET_DIN;elseCLR_DIN;
...
Zależnie od tego, na którą pozycję wyświetlacza ma trafić znak, są one pobierane w odpowiedniej kolejności z tablicy display. W dużym skrócie, odpowiadające za to fragmenty programu można przedstawić następująco (wszystko odbywa się w procedurze ISR(TIMER0_OVF_vect)):
- czwarty moduł wyświetlacza w szeregu, znaki odwrócone o 180 stopni – „j”z zakresu 4 do 1,offset=(display[4-j]*8)+linia;
- trzeci moduł wyświetlacza, znaki odwrócone o 180 stopni – „j”z zakresu 4 do 1, offset=(display[8-j]*8)+linia;
- drugi moduł wyświetlacza, znaki normalne – „j”z zakresu od 0 do 3, offset=(display[15-j]*8)+linia;
- pierwszy moduł wyświetlacza, znaki normalne – „j”z zakresu od 0 do 3,offset=(display[11-j]*8)+linia;
Program demonstracyjny wykonano za pomocą AVR Studio 7 dla mikrokontrolera ATmega8A. Jest on taktowany z użyciem wbudowanego generatora RC o częstotliwości 8MHz. Dla tej częstotliwości taktowania dobrano czasy opóźnień, częstotliwość wywoływania przerwania zegarowego, prąd segmentów wyświetlaczy itd.
Na koniec niedobra informacja... Niestety, firma Prema Semiconductor już nie produkuje układów PR4010 i PR4001 zastosowanych w module. Aktualnie powstaje wersja wyświetlacza z driverem dla Arduino, na bazie układów scalonych oferowanych przez firmę AMS. Ale o tym wkrótce...
Jacek Bogusz
j.bogusz@easy-soft.net.pl
Załącznik | Wielkość |
---|---|
Przykładowy program | 2.81 KB |
Dodaj nowy komentarz