Obsługa kolorowego wyświetlacza LCD-TFT 320×240 za pomocą mikrokontrolera STM32
Ważnym elementem graficznego interfejsu użytkownika jest wyświetlanie informacji tekstowych. Jak wiemy sterownik zastosowany w module LCD nie zapewnia żadnego wsparcia poza możliwością zapalenia/zgaszenia pojedynczego pikseli o zadanym kolorze. Dlatego wyświetlanie znaków alfanumerycznych trzeba wykonać całkowicie programowo. Zaczniemy od generatora znaków. Tablicę z wzorcami znaków można sobie samemu zdefiniować, ale jest to żmudne zajęcie. Ja wykorzystałem gotową tablicę wykonaną przez James’a P. Lyncha dla wyświetlacza telefonu Nokia 6100. Tablica zawiera wzorce znaków o 3 wielkościach: 6 x 8 pikseli (SMALL), 8x8pikseli (MEDIUM) i 8x16pikseli (LARGE). W praktyce najbardziej przydatne okazały się największe znaki, ale pozostałe tez są używalne. Nic nie stoi na przeszkodzie by sobie zdefiniować jeszcze większe znaki. Pierwsze 3 bajty w tablicy generatora dla każdej z wielkości znaków zawierają informację o ilości kolumn, wierszy i bajtów na znak. Na tej podstawie jedna uniwersalna procedura potrafi wyświetlić znaki o różnych wielkościach.
Procedura potrafiąca wyświetlić jeden znak jest pokazana na listingu 9.
List. 9. Procedura wyświetlania jednego znaku
void LCDPutChar(char c, int x, int y, int size, unsigned char fColor, unsigned char bColor) { extern const unsigned char FONT6x8[97][8]; extern const unsigned char FONT8x8[97][8]; extern const unsigned char FONT8x16[97][16]; int i,j; unsigned char nCols; unsigned char nRows; unsigned char nBytes; unsigned char PixelRow; unsigned char Mask; unsigned char *pFont; unsigned char *pChar; unsigned char *FontTable[] = {(unsigned char *)FONT6x8, (unsigned char *)FONT8x8, (unsigned char *)FONT8x16}; //wskaznik na poczatek tablicy generatora znakow pFont = (unsigned char *)FontTable[size]; nCols = *pFont; //liczba kolumn wzorca znaku nRows = *(pFont + 1); //liczba wierszy wzorca znaku nBytes = *(pFont + 2); //liczba bajtow wzorca znaku //wskaznik na ostatni bajt z wzorca naszego znaku pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1; //petla wykonywana dla kazdego wiersza for (i = nRows - 1; i >= 0; i--) { //pobierz bajt z wzorca znaków PixelRow = *pChar--; WrAddr(x,y+i); Mask=0x80; for (j = 0; j < nCols; j ++) { if ((PixelRow & Mask) == 0) WrData (bColor); //jezeli piksel = 0 kolor tla else WrData(fColor); //jezeli piksel = 1 kolor znaku Mask=Mask>>1; } } }
Argumentami procedury są : kod ASCII wyświetlanego znaku, położenie na ekranie (współrzędne x i y ),rozmiar, kolor znaku i kolor tła. W zmiennej pFont jest umieszczany wskaźnik na początek tablicy generatora znaków. Do zmiennych nCols, nRows i nBytes są zapisywane pierwsze 3 bajty z tablicy generatora znaków. Ponieważ wzorce znaków nie są umieszczane w tablicy zgodnie z kodami ASCII, to trzeba kod ASCII wyświetlanego znaku przekształcić na pozycję w tablicy generatora. Po przekształceniu wskaźnik pChar wskazuje na ostatni bajt wzorca znaku w tablicy generatora. Program pobiera kolejne bajty z tablicy (od ostatniego do pierwszego). Każdy bit tego bajtu jest analizowany. Jeżeli jest ustawiony, to bit jest wyświetlany w kolorze znaku określonym argumentem fColor. Kiedy bit jest wyzerowany, to jest wyświetlany w kolorze określonym argumentem bColor. W ten sposób można wyświetlać znaki w dowolnym kolorze na tle w dowolnym kolorze o głębi 8-bitowej. Tryb tekstowy uzupełnimy procedurą wyświetlania tekstu w jednym z trzech rozmiarów(argument size). Pozycja początku ciągu znaków jest ustalana argumentami x, y, a kolor znaków i tła argumentami fColor i bColor.
Wynik działania tej procedury został pokazany na fotografii 5.
Fot. 5. Przykładowy efekt działania procedury z listingu 10
List. 10. Procedura wyświetlania tekstu
void LCDPutStr(const char *pString, int x, int y, int Size, char fColor, char bColor) { //w petli do znalezienia końca ciagu while (*pString != 0x00) { //wyswietl znak alfanumeryczny LCDPutChar(*pString++, x, y, Size, fColor, bColor); //korekcja pozycji y w zaleznosci od wielkosci znaku if (Size == SMALL) x = x + 6; else if (Size == MEDIUM) x = x + 8; else x = x + 8; if (x > 320) break; } }