V tomto článku se budu věnovat popisu ovládání TFT displeje, který byl koupen na Ebay.com. TFT display je řízen řadičem SSD1963.
Napájení displeje je 3,3V a se zapnutým podsvícením bude potřeba skoro 300mA – podle toho je potřeba navrhnout zdroj pro první pokusy na nepájivém poli. V první části článku popíšu připojení řadiče k procesoru řady ATmega a inicializaci řadiče. V dalších kapitolách textu budou popsány funkce nutné k vykreslení bodu, čáry, obdélníku a kruhu na TFT display. Řadič displeje neobsahuje žádný alfanumerický font, jako je obvyklé u LCD displejů s řadiči HD44780, nebo T6963. Tam stačilo poslat na displej kód znaku a řadič displeje se postaral o vytvoření znaku ze své paměti. Při práci s řadičem SSD1963 se o tvorbu znaků musí postarat program v procesoru, jednotlivé znaky je potřeba poslat na displej jako pole barevných bodů. Takže v poslední části článku se pokusíme z Windows do paměti procesoru ATmega dostat nějaký font.
Popisovaný TFT display má rozlišení 480 x 272 bodů.
Komunikace probíhá prostřednictvím 16-ti bitové, nebo 8-mi bitové sběrnice a řídících vodičů. Řadič umožňuje uspořádat časování řídících vodičů tak, jak je zvykem u procesorů řady 6800, nebo u procesorů řady 8080. V displeji který mám k dispozici, je řadič zapojen v režimu 8080, takže se podíváme, jak zařídit komunikaci v tomto režimu:
Při zápisu dat do displeje, musí být data připravena na sběrnici, signál /WR musí být aktivní (úroveň L) a data do displeje budou přenesena sestupnou hranou signálu /CS. Nakonec se ukázalo, že pořadí signálu /WR a /CS může být i opačné. Takže pokud na datové sběrnici procesoru není připojen jiný obvod než displej, stačí pro komunikaci signál /WR. Signál /CS, výběr obvodu, může být připojen na úroveň L pořád. Při čtení dat z displeje je nutné, aby datová sběrnice procesoru byla ve stavu vysoké impedance. Data na ní budou k dispozici, když bude signál /RD v úrovni L. Z displeje v tomto článku nebudemečíst nic, takže /RD zůstane pořád neaktivní v úrovni H.
Signál D/C slouží k rozlišení, zda jsou přenášena data, nebo příkazy (command). Pro přenos příkazů stačí 8-mi bitová sběrnice. Pro přenos barev je zapotřebí šest bitů na každou barvu, červenou, zelenou a modrou. To je dohromady 18 bitů. Řadič nabízí několik možností, jak barvy přenášet. Můžeme použít 8-mi bitovou sběrnici a barvu přenést ve třech krocích. Nebo je možné použít devět bitů a potom stačí dva kroky. Pro 16-ti bitový přenos řadič umožňuje ušetřit dva bity z 18-ti. Tento režim je nazván 5-6-5, červená a modrá barva má o jeden bit míň. Protože je nutné data přenášet co nejrychleji – na vykreslení 480 x 272 bodů je potřeba 130560 čísel, použijeme tento režim.
Ještě je potřeba najít příkaz, který ovládá režimy – je to 0xF0.
TFT display jsem připojil k procesoru a napsal makra pro jednotlivé piny portů, které budu potřebovat:
Funkce pro přenos příkazu:
Funkce pro přenos dat:
Ještě se bude hodit funkce, která najednou pošle příkaz a jeho parametr:
Na začátku práce, po připojení displeje na napájení je zapotřebí nastavit spoustu registrů v řadiči, aby bylo možné řadičem ovládat TFT panel. Následující funkce provede softwarový reset displeje, nastaví PLL generátor, nastaví počet bodů našířku a na výšku displeje. Poslední část funkce nastaví PWM generátor, kterým je možné řídit jas podsvícení displeje. Kvůli tomu je zapotřebí přemístit jeden odpor – propojku na plošném spoji displeje z pozice R4 na pozici R8. Parametry jednotlivých příkazů jsou převzaty z dokumentace, kterou lze stáhnout ze stránek na ebay.com.
TFT_SendCommand( 0x00E6 ); //SET PCLK freq=9.5MHz ; pixel clock frequency
TFT_SendData( 0x0000 ); // 0x03
TFT_SendData( 0x00FF );
TFT_SendData( 0x00BE );
TFT_SendCommand( 0x00B0 ); // set LCD specification
TFT_SendData( 0x0020 );
TFT_SendData( 0x0000 ); //LCD panel mode
TFT_SendData( 0x0001 ); //SET horizontal size=480-1 HightByte
TFT_SendData( 0x00DF ); //SET horizontal size=480-1 LowByte
TFT_SendData( 0x0001 ); //SET vertical size=272-1 HightByte
TFT_SendData( 0x000F ); //SET vertical size=272-1 LowByte
TFT_SendData( 0x0000 ); //SET even/odd line RGB seq.=RGB
TFT_SendCommand( 0x00B4 ); //SET Horizontal Period (8 parameters)
TFT_SendData( 0x0002 ); //531 HT
TFT_SendData( 0x0013 );
TFT_SendData( 0x0000 ); //43 HPS
TFT_SendData( 0x002B );
TFT_SendData( 0x000A ); //10 HPW
TFT_SendData( 0x0000 );
TFT_SendData( 0x0008 ); //8 LPS
TFT_SendData( 0x0000 );
TFT_SendCommand( 0x00B6 ); //SET Vertical Period (7 parameters),
TFT_SendData( 0x0001 ); //288 VT
TFT_SendData( 0x0020 );
TFT_SendData( 0x0000 ); //12 VPS
TFT_SendData( 0x000C );
TFT_SendData( 0x000A ); //10 VPW
TFT_SendData( 0x0000 ); //4 FPS
TFT_SendData( 0x0004 );
TFT_WriteDataChar( 0x0036, 0x0000 ); //rotation!!!!!!!!! toci displejem, prostudovat
TFT_WriteDataChar( 0x00F0, 0x0003 ); // 565 format barvy
_delay_ms( 5 );
TFT_SendCommand( 0x0029 ); // Display ON
TFT_SendCommand( 0x00BE ); // set PWM for B/L
TFT_SendData( 0x0006 );
TFT_SendData( 0x00F0 ); // hodnota PWM
TFT_SendData( 0x0001 );
TFT_SendData( 0x00F0 );
TFT_SendData( 0x0000 );
TFT_SendData( 0x0000 );
TFT_WriteDataChar( 0x00D0, 0x000D );
TFT_SendCommand( 0x00B8 ); // reset GPIO0
TFT_SendData( 0x0000 );
TFT_SendData( 0x0001 );
TFT_WriteDataChar( 0x00BA, 0x0000 );
}
TFT display se podařilo připojit a rozsvítit. Paměť tímto způsobem inicializovaného displeje je naplněna náhodnými čísly. Proto budou i barvy na displeji rozmístěny chaoticky – zrnění všech možných barev. Budeme potřebovat funkci, která celý displej zaplní jednou barvou. No a protože jsou barvy vyjádřeny 16-ti bitovými čísly, bude dobré nadefinovat několik základních barev, abychom si nemuseli pamatovat jejich číselné vyjádření:
Na začátku každé operace na displeji vymezíme prostor – obdélník, ve kterém budeme kreslit. K tomu slouží příkaz 0x2A a 0x2B, které jsem využil v následující funkci:
A tady je funkce, která vyhrazenou plochu displeje zaplní zadanou barvou. Do prostoru v paměti displeje vyhrazeného funkcí TFT_WindowSet, nahraje požadovanou barvu. To, že bude zahájeno nahrávání barev do paměti, oznámí řadiči příkaz 0x2C:
Další funkce je podobná, ale vyhrazená plocha má velikost jednoho bodu. Takže nakreslíme bod:
No a na konec budeme kreslit přímku, obdélník a kružnici:
dy = y2 – y1;
dx = x2 – x1;
if (dy < 0)
{
dy = -dy;
stepy = -1;
}
else stepy = 1;
if (dx < 0)
{
dx = -dx;
stepx = -1;
}
else stepx = 1;
dx <<= 1;
dy <<= 1;
TFT_DrawPoint( x1, y1, color );
if (dx > dy)
{
fraction = dy – (dx >> 1);
while( x1 != x2 )
{
if (fraction >= 0)
{
y1 += stepy;
fraction -= dx;
}
x1 += stepx;
fraction += dy;
TFT_DrawPoint( x1, y1, color );
}
}
else
{
fraction = dx – (dy >> 1);
while( y1 != y2 )
{
if (fraction >= 0)
{
x1 += stepx;
fraction -= dy;
}
y1 += stepy;
fraction += dx;
TFT_DrawPoint( x1, y1, color );
}
}
}
Písmenka jsou v paměti procesoru uložena jako sady černých a bílých bodů, kterými je nutné zaplnit obdélník veliký jako písmenko. K vyhrazení obdélníku slouží funkce TFT_WindowSet. Nyní je potřeba přijít na to, kde vzít soubor písmenek, ideálně z fontů, které jsou součástí systému Windows. Našel jsem volně dostupný program MikroElektronika-GLCD. Do něj je možné importovat každý font, který je součástí Windows, v požadované velikosti. Při importu lze zvolit rozsah importovaných znaků (smysl mají znaky 32 – 127), možnosti posouvání znaků k okraji bitmapy dle potřeby. Jednotlivé znaky lze dál upravovat podle vlastní fantazie:
Když jsme s fontem spokojeni, můžeme jej vyexportovat do pole dat, které bude možno použít v AVR studiu:
Tohle je jenom kousek… datové pole je celkem velké. První řádek plný nul, kód 32, je mezera. Na dalším řádku je zobrazen vykřičník, takže data 0x02 zobrazují šest bodů pod sebou. Potom je mezera a pak dva body pro tečku vykřičníku. Tímto způsobem jsou uložena všechna písmena fontu. Čtyři fonty, které jsou na úvodní fotografii zaberou v paměti procesoru asi 30kb.
Je potřeba si uvědomit, že překladač AVR studia automaticky vytvoří program, který na začátku uloží obsah datového pole do paměti RAM procesoru. No a to je problém, protože paměti RAM v ATmega není moc, musíme šetřit. A tvar znaků během chodu programu není potřeba měnit, takže není žádný důvod, aby pole bylo v RAM. K tomu, aby pole dat zůstalo v paměti programu a odtud bylo používáno, slouží knihovna pgmspace.h. Tu připojíme na začátku programu a potom můžeme využít její funkce. Do názvu pole dat doplníme slovo PROGMEM – data zůstanou v paměti programu a paměť RAM zůstane volná.
Nyní musíme pochopit, jak jsou data uspořádána, abychom je uměli použít. Na začátku datového pole je vyznačen kód prvního a posledního znaku. Začátek je 0x20 hexadecimálně, to je 32 decimálně, podle ASCII tabulky mezera. Konec datového pole je hexadecimálně 0x7F = 127 decimálně, to je kousek za malým Z, ještě je tam ~ a ještě něco. Dál je v datovém poli číslo 0x0D, to bude výška písmenka – počet řádků, pixelů displeje, které jsou zapotřebí pro zobrazení. Pak tu máme vždy čtveřici čísel pro každý znak uložený v datovém poli. První číslo udává počet sloupců, pixelů displeje – znaky mají různou šířku. Další tři čísla označují místo v poli dat, na kterém začíná písmenko. Písmenko je v poli dat zobrazeno po řádcích. Bity jdou zleva do prava, od bitu s nejnižší vahou k nejvyšší. Takže při zobrazování budeme číslem rotovat doprava a číst bit 0. Pro větší znaky bude čísel na jeden řádek potřeba víc, jde jedno za druhým. A když bude jeden řádek zaplněn, nový řádek začíná novým číslem.
V první části funkce pro zobrazení znaku z pole dat přečteme údaje o znaku, který má být zobrazen. Znaky jsou seřazeny tak, jak jdou za sebou v tabulce ASCII, takže od vstupní proměnné ChAscii stačí odečíst 32 a můžeme číst údaje z pole dat:
pgm_read_byte je z knihovny pgmspace.h. V další části funkce je smyčka, která bude z pole dat postupně číst bajty a rotovat jimi. Podle hodnoty nejnižšího bitu bude na displej odeslána barva pozadí, nebo barva znaku – když bit = 1.
Knihovna pro komunikaci s obvodem SSD1963, včetně funkce pro inicializaci obvodu
Knihovna obsahuje grafické funkce
Knihovna obsahuje alfanumerické funkce pro psaní textu a číslic
Fonty, které mohou být použity v knihovně alfanumerických funkcí
Autor článku: František OK2JNJ
Prepáčte, ale pred zanechaním komentára sa musíte prihlásiť.
Pekný článok, len tak ďalej 🙂
display s radičom by mal mať jednoduchšie ovládanie….
Pěkná práce.