Jste zde

Ovládání grafických LCD modulů s řadičem KS0108 (S6B0108)

083_ctvrty.jpg

Tento řadič se používá např. u LCD s rozlišením 128x64 pixelů s označením ATM12864, PG12864, .... Modul displeje obsahuje i teplotně kompenzovaný generátor záporného napětí, které je pro funkci LCD nezbytné. Nevýhodou je poměrně velký počet ovládacích vodičů a absence znakové sady - jedná se o čistě grafický LCD a znakovou sadu je nutné vytvořit externě.

Sběrnice je paralelní 8bitová, dále jsou nutné vývody E, RS, CS1 a CS2 a pro případné čtení obsahu LCD nebo busy příznaku ještě vývod RW. Posledním vývodem je RST, který není nutný. Zapojení vývodů modulu je uvedeno v tabulce.

Číslování a význam vývodů

Číslo 1 bývá označeno na desce LCD modulu.

Vývod Název Funkce
1 Vss napájení GND
2 Vcc napájení +5V
3 Vee (Vo) nastavení kontrastu
4 RS volba mezi: RS=0 - instrukcí, RS=1 - daty
5 RW volba mezi: RW=0 - zápisem, RW=1 - čtením
6 E hodinový signál
7 DB0 data bit DB0
8 DB1 data bit DB1
9 DB2 data bit DB2
10 DB3 data bit DB3
11 DB4 data bit DB4
12 DB5 data bit DB5
13 DB6 data bit DB6
14 DB7 data bit DB7
15 CS1 výběr řadiče pro levou část LCD (CS1=1 - vybráno)
16 CS2 výběr řadiče pro pravou část LCD (CS2=1 - vybráno)
17 RST reset modulu (RST=0 - reset, RST=1 - normalní funkce)
18 Vout výstup záporného napětí pro LCD (asi -12V)
19 LED+ anoda podsvětlovacích LED
20 LED- katoda podsvětlovacích LED

Komunikace s displejem

Celý displej je rozdělěn na 2 poloviny s rozlišením 64x64 pixelů. Každá z nich má svůj vlastní řadič. Všechny vývody mimo CS1 a CS2 jsou spojeny paralelně. Pomocí vývodů CS1 a CS2 se volí práce buď s levým, pravým nebo oběma řadiči (aktivní v log.1). Displej komunikuje po 8bitové paralelní sběrnici. Volba mezi zápisem a čtením se provádí pomocí vývodu RW a volba mezi instrikcí a daty pomocí vývodu RS (stejně jako u řadiče HD44780). Záporným pulzem na vývodu RST se LCD vypne a vynulují se interní registry. Obsah obrazové paměti se nezmění, takže po zapnutí LCD instrukcí se objeví původní obraz. Tento vývod není nutný a stačí ho připojit na +5V.

Při zápisu instrukce nebo dat je byte ze sběrnice načten při sestupné hraně kladného impulzu na vývodu E, Který by měl trvat alespoň 450ns. Upozorňuji, že data musí být na sběrnici přivedeny ještě před příchodem vzestupné hrany na E a ne těsně před sestupnou hranou, jak naznačuje graf v datasheetu, jinak při některých konkrétních kombinacích na datové sběrnici dojde k zápisu náhodného bytu do té části LCD, která není vybraná (CSx=0). Trvalo mi hodně dlouho než jsem přišel na to, kde je chyba a na konec se ukázalo, že stačilo data přivést před čelem pulzu na E.

Stavové slovo obsahující "busy" příznak, stav resetu a zapnuto/vypnuto se čte následovně: Vývod RW na log.1, vývod RS na log.0 a následně E na log.1. V tomto stavu se objeví stavové slovo na sběrnici. Význam jeho jednotlivých bitů je uveden v tabulce instrukcí. Po přečtení slova vývod E zpět na log.0. Při čtení dat se postupuje steně, pouze vývod RS musí být nastaven na log.1 a před vlastním čtením je třeba vygenerovat na E jeden kladný pulz (tzv. "dummy read").

Po zapnutí napájení není možné ihned vysílat instrukce. Je třeba buď generovat časovou prodlevu nebo dokola číst příznaky "busy" a "reset" a čekat, dokud nebudou oba v log.0. Příznaky "busy" a "reset" je třeba kontrolovat i po resetu vývodem RST.

Instrukce displeje

Po instrukcích zápisu a čtení dat, se automaticky zvyšuje hodnota čítače adresy v X. Po posledním (63) sloupci se začíná opět zleva. Stránky se automaticky neinkrementují. Registr pro psuv prvního řádku lze využít pro vertikální posouvání obsahu LCD.

Význam instrukce
RS
R/W
DB7
DB6
DB5
DB4
DB3
DB2
DB1
DB0
zap./vyp. displej, D=1 - zapnuto
0
0
0
0
 
 
 
 
 
D
nastaví stránku paměti
(svislou osmici pixelů, ráno shora), rozmezí 0-7
0
0
 
0
 
 
 

stránka

nastaví pozici v X (bráno zleva), rozmezí 0-63
0
0
0
 

X adresa

nastaví vertikální pozici horního řádku, rozmezí 0-63
0
0
 
 

Y posuv

zápis dat (LSB nahoře, MSB dole)  
0

data byte

čtení dat (LSB nahoře, MSB dole)  
 

data byte

čtení stavového slova
B=1 - řadič zaneprázdněn, B=0 - připraven
D=1 - LCD zapnut, D=0 - LCD vypnut
R=1 - probáhá reset, R=0 - reset ukončen
0
 
B
0
D
R
0
0
0
0

Ukázkový program

Na schématu je možný způsob připojení LCD k jednočipu 89C2051. Trimr R4 nastavuje kontrast displeje, jinak asi není co dodat. Problém je, že LCD zabírá skoro všechny vývody jednočipu, takže buď se musí použít typ s více porty nebo různé posuvné registry pro "rozmnožení" výstupů. Poslední, a docela vhodná, možnost je použít jeden samostatný jednočip pro řízení LCD a posílat do něj instrukce nebo data asynchronním kanálem, což používám u své zatím jediné konstrukce s tímto LCD.

Ukázkový program nejprve vypíše 2 texty, pak pomocí registru pro vertikální posuv prvního řádku posouvá obraz a nakonec se spustí program, který pohybuje pixelem po displeji a nechává za sebou stopu.

Znaková sada v externí EEPROM

Jak jsem se již zmínil, řadič KS0108 nemá vlastní znakovou sadu, takže jsem vytvořil vlastní. Velikost znaku je 5x7 pixelů. Znaková sada je poměrně velká, takže jsem ji uložil do sériové EEPROM 24C16. Bez změny programu nelze použít menší ani větší paměť, protože se liší způsobem adresování. Znakovou sadu do EEPROM naprogramuje toto zapojení. Zbytek paměti, což je nejméně 768 Bytu (od bytu 1280 výše), lze využít pro jiné účely. Nevýhodou použité paměti je, že již nelze na stejnou sběrnici připojit další paměť, ale pouze jiné obvody, které mají jinou adresu. Tento typ EEPROM totiž využívá bity A0, A1 a A2, které normálně slouží k odlišení adresy až osmi EEPROM, pro adresování paměti.

Knihovna pro pro práci s LCD obsahuje mimo vlastních funkcí i knihovnu pro práci s I2C sbernicí. Lze ji využít i pro jiné zařízení na téže sběrnici, ale je třeba dát pozor na bit "f0". Pro sekvenční čtení dat z EEPROM je totiž potřeba po čtení každého bytu během ACK "stáhnout" SDA na log.0, čímž paměť "zádám" o další byte. K tomuto účelu jsem použil bit "f0" - mimo sekvenční čtení musí být nastaven na log.1!!!

Knihovna obsahuje inicializaci LCD, nastavování řádku (0-7), nastavování kurzoru (0-20), mazání aktuálního řádku, mazání celého LCD, zápis jednoho znaku a zápis řetězce z tabulky. Po zápisu každého znaku se automaticky posouvá kurzor. Po dosažení konce řádku skočí na nový a po naplnění LCD skočí zpět na první řádek. Kurzor je jen pomyslný - není zobrazován. Celá knihovna i s I2C knihovnou má 372 bytů. Podrobnější popis je přímo ve zdrojovém kódu.

Rutiny kreslení úseček

Nedávno proběhla na MCU serveru diskuze "Jak kreslit spojnice bodů", což mě inspirovalo k "vyextrahování" patřičných rutin ze svých starších pokusů a vytvoření tohoto ukázkového prográmku.

Zřejmě nejjednodušším řešením kreslení úseček je následující metoda: Dejme tomu, že úsečka je definována body A a B. Porovnáme je podle X souřadnice a případně prohodíme, aby A byl na X ose vždy vlevo od B. Tím pádem teď může úsečka od bodu A směřovat jen do I. nebo IV. kvadrantu. Tyto dvě možnosti se liší pouze tím, že v I. kvadrantu Y poroste, zatímco ve IV. bude klesat, jinak je vše stejné. Porovnáním Ay a By určíme kvadrant. Nyní porovnáme délku úsečky v ose X a Y a vypočteme směrnici vztaženou k delší ose - tedy kratší/delší. Výpočet je vhodné provádět v pevné řádové čárce (float je zde k ničemu a celou rutinu mnhonásobně zpomaluje). Nyní nastavíme počáteční pozici úsečky - bod A a vykreslíme ho. Následně inkrementujeme/dekrementujeme (+1/-1) delší osu a ke kratší přičítáme/odečítáme směrnici (+ pro I., - pro IV. kvadrant). Po každé inkrementaci vykreslíme bod podle aktuálních X,Y souřadnic. Počet kroků je logicky dán počtem bodů v delší ose. Na každou úsečku je tedy třeba jen jedno celočíselné, neznamínkové dělení a pak jen přičítání/odečítání a sem tam nějaká rotace.

Tento prográmek měl původně pomocí rutiny pro kreslení spojnic vykreslovat rotující krychli ve dvou osách, ale nějak se mi nepovedlo patřične poskládat sin/cos fce, takže je z toho rotující nesmysl :-). Nicméně jako ukázka to snad stačí.

Odkazy

Hodnocení článku: 

Komentáře

Jsem trochu zmaten poznamkou o nemoznosti pripojeni vice nez jedne EEPROM.
Kdyz jsem si stahnul jeji datasheet, tak se v nem pise, ze pri adresovani na I2C je B7=1, B6/B5/B4 odpovidaji prave A2/A1/A0, B3/B2/B1 jsou pro strankovou adresaci uvnitr pameti a nakonec B0 rozlisuje cteni a zapis.
Ostatne i Vy mate ve schematu uvedene A2-A0, ale nezapojene. K cemu by je tam vyrobce daval, kdyby se nedaly pouzit?

I v tomto pripade datasheet uvadi na strane 3 nahore doslova: The AT24C16A does not use the device address pins, which limits the number of devices on a single bus to one. The A0, A1 and A2 pins are no connects.
Detailni popis adresovani je na strane 8 plus obrazek 7 na strane 9.
Zaver:
24C16: zadny adresovaci pin
24C08: jeden adresovaci pin (A2)
24C04: dva adresovaci piny (A2, A1)
mensi pameti vyuzivaji vsechny piny.

Skratka je k podivu, preco - i vzhladom k dnesnym cenam - nie je v konstrukcii pouzita 24C32/64/../1024, kde uz adresne nozicky plnia funkciu, ktora sa od nich ocakava. Ta 24C16 je na hranici, ci pouzit v I2C komunikacii dalsi byte na adresaciu vnutornej pamate alebo na adresaciu inej suciastky. V tomto je pouzitie 24C16 velmi osemetne a ak, tak doporucujem pouzit cip s vacsou kapacitou. Pren su uz adresne vodice naozaj adresnymi vodicami a nie akymsi "apendixom" na puzdre cipu.