Bc. Karel Románek, UREL, FEEC, VUT Brno
xroman00stud.feec.vutbr.cz
Cílem tohoto projektu je vytvoření knihovny vykreslovacích funkcí pro grafický LCD displej EA DOGM132. Vytvořená knihovna bude zahrnuta do momentálně vznikající diplomové práce "Nezávislý datalogger s USB připojením". Displej bude podávat informace o zaznamenávaných datech, stavu zařízení a případně vykreslovat zjednodušené grafické průběhy. Vytvářené funkce jsou tedy koncipovány tak, aby vyhovovaly právě této aplikaci. Ovládání displeje je provedeno pomocí vývojového kitu MCBSTM32E s 32-bitovým ARM cortex M3 mikrokontrolérem STM32F103. Pro vytvoření knihovny je použito vývojové prostředí uVision v4.03.
LCD displej DOGM132X-5 od společnosti ELECTRONIC ASSEMBY je monochromatický grafický displej s rozlišením 132x32 pixelů. Svými rozměry odpovídá klasickým 2x16 (4x22) alfanumerickým displejům. Displej samotný je řízen řadičem ST7565R. Výborně se hodí pro přenosná zařízení, jelikož pracuje s jednotným napájením 3,3V se spotřebou přibližně 140uA v režimu bez podsvícení. Celé okolní zapojení displeje se zkládá z devíti kondenzátorů a dvou omezovacích odporů k podsvícení. Vývojové zapojení je na obr. 1,2. Displej je řízen jednosměrnou komunikací s MCU pomocí SPI sběrnice. Jednotlivé řídící signály jsou vidět na obr. 1. Jsou to: sériová data - LCD_SPI, sériový hodinový signál LCD_SCK, adresní linka LCD_A0, chip select LCD_CS, a reset LCD_RST.
void LCD_SendByte(u8 Tx_byte) { u8 i; u8 temp; u32 j; BitAction Tx_bit = Bit_RESET; // prenaseny bit for(i = 0; i < 8; i++) // opakovani pro 8 bitù { temp = Tx_byte; if( temp & 0x80 ) // nastaveni bitu k odeslani {Tx_bit = Bit_SET;} else {Tx_bit = Bit_RESET;} GPIO_WriteBit(LCD_SI_port, LCD_SI, Tx_bit); // nastaveni linky LCD_SI GPIO_WriteBit(LCD_SCK_port, LCD_SCK, Bit_SET); // nastupna hrana LCD_SCK GPIO_WriteBit(LCD_SCK_port, LCD_SCK, Bit_RESET); // sestupna hrana LCD_SCK Tx_byte <<= 1; } }
Po připojení displeje k napájení a řídícímu MCU musí být provedena inicializace. Ta spočívá v nastavení potřebných parametrů řadiče displeje. K tomu slouží funkce LCD_init( ) definovaná v lcd_dogm132.c. Zdrojový kód je uveden dále:
extern void LCD_init(void){ GPIO_WriteBit(LCD_CS_port, LCD_CS, Bit_RESET); // CS - enable LCD_SendByte(0x40); // pocatecni radek 0 LCD_SendByte(0xA1); // reversni rezim displeje LCD_SendByte(0xC0); // nastavení COM vystupu 0 - 63 LCD_SendByte(0xA6); // neinverzni rezim displeje LCD_SendByte(0xA2); // bias napeti displeje 1/9 LCD_SendByte(0x2F); // booster, regulator a follower on LCD_SendByte(0xF8); // nastavení pocatecnihi hodnoty boosteru 4x... LCD_SendByte(0x00); // ... LCD_SendByte(0x23); // nastavení interniho napetoveho regulatoru LCD_SendByte(0x81); // nastaveni kontrastu... LCD_SendByte(0x1F); // ... LCD_SendByte(0xAC); // nastaveni statickeho indikatoru... LCD_SendByte(0x00); // ... LCD_SendByte(0xAF); // displej on GPIO_WriteBit(LCD_CS_port, LCD_CS, Bit_SET); // CS - disable }
Po provedení uvedené inicializační funkce je třeba ještě vymazat obsah displeje funkcí LCD_clear( ) (z lcd_dogm132.c) jelikož v zobrazovací paměti displeje jsou v tuto chvíli náhodné čísla.
Jednotlivé pixely jsou vykreslovány na displej odesláním a uložením obrazových dat do paměti řadiče displeje. Zobrazovací prostor je rozdělen podle obr. 4., jsou to tedy 4 stránky (pege), v každém 8 bitů obrazových dat a 132 sloupců (column). Toto také odpovídá adresování paměti řadiče displeje.
extern void LCD_redraw_buffer(void) { GPIO_WriteBit(LCD_CS_port, LCD_CS, Bit_RESET); // CS - enable for(page=0xB0 ; page<0xB4 ; page++) // zopakovani pro vsechny 4 page { GPIO_WriteBit(LCD_A0_port, LCD_A0, Bit_RESET); // A0 = 0 - rezim odesilani prikazu LCD_SendByte(page); // nastavit page LCD_SendByte(0x00); // nastavit column na zacatek - nizsi nibl LCD_SendByte(0x10); // nastavit column na zacatek - vyssi nibl GPIO_WriteBit(LCD_A0_port, LCD_A0, Bit_SET); // A0 = 1 - rezim odesilani dat for(col=0 ; col<132 ; col++) // zopakovani pro vsechny column { sbyte = (disp_buf[col] >> (((page-0xB0)*8))); // nastaveni bytu pro odeslani z bufferu despleje LCD_SendByte(sbyte); // smazat vybrany column ve vybrane page } } GPIO_WriteBit(LCD_CS_port, LCD_CS, Bit_SET); // CS - disable GPIO_WriteBit(LCD_A0_port, LCD_A0, Bit_RESET); // A0 = 0 - rezim odesilani prikazu }
Jak bylo zmíněno v úvodu, knihovna je koncipována pro konkrétní aplikaci, tedy informační displej pro logovací meteostanici. Od toho se také odvíjí vytvořené funkce definované v lcd_dogm132.c. Jsou to následující:
Funkce pro inicializaci displeje. Je popsána v kapitole Inicializace displeje.
Funkce pro mazání displeje. Funkce pouze nastaví všechny bity v zobrazovacím bufferu na log0
Funkce pro vykreslení všech pixelů displeje. Funkce pouze nastaví všechny bity v zobrazovacím bufferu na log1.
Funkce pro vykreslení pixelu.
Vstupy funkce:
x (0-131) - x souřadnice - bráno od levého dolního rohu
y (0-31) - y souřadnice - bráno od levého dolního rohu
Funkce pro vykreslení čáry.
Vstupy funkce:
x1 (0-131) - x souřadnice - levý spodní bod
y1 (0-31) - y souřadnice - levý spodní bod
x2 (0-131) - x souřadnice - pravý horní bod
y2 (0-31) - y souřadnice - pravý horní bod
pozn.: souřadnice brány od levého dolního rohu
Funkce pro vykreslení obdelníku. Tato funkce má kromě vstupních souřadnic další dva parametry "border" a "filled". Parametr "border" určuje šířku okraje v px, okraj je vykreslován od zadaných souřadnic dovnitř. Paramet "filled" určuje zda ma být obdelník vyplněn nebo má být vykreslen pouze okraj.
Vstupy funkce:
x1 (0-131) - x souřadnice - levý dolní roh
y1 (0-31) - y souřadnice - levý dolní roh
x2 (0-131) - x souřadnice - pravý horní roh
y2 (0-31) - y souřadnice - pravý horní roh
pozn.:souřadnice brány od levého dolního rohu
border (0-16) - šiřka okraje v px - směrem dovnitř od zadaných souřadnic
filled (TRUE/FALSE) - TRUE - vyplněny obdelník, FALSE - nevyplněný obdelník
Funkce pro vykreslení indikátoru průběhu. Funkce vykreslí obrysový čtverec zadaných souřadnic a do něj obdelník zobrazující "průběh". Kromě souřadnic má vstupní parametr "prog", který je rozsahu 0-100% a určuje poměr vykreslené k nevykreslené části obdelníku určující "průběh". Dalším parametrem je "dir", který určuje zda bude indikátor ve vertikálním nebo horizontálním směru.
Vstupy funkce:
x1 (0-131) - x souřadnice - levý dolní roh obdelníku
y1 (0-31) - y souřadnice - levý dolní roh obdelníku
x2 (0-131) - x souřadnice - pravý horní roh obdelníku
y2 (0-31) - y souřadnice - pravý horní roh obdelníku
pozn: souřadnice brány od levého dolního rohu obdelníku od rohových bodů
prog (0 - 100) - % zaplnění
dir (0 / 1) - směr - 0 - vertikální, 1 - horizontální
Funkce pro výpis textů na displej. Vstupem je ukazatel na pole typu char. Displej nemá implementovanou znakovou sadou. Je tedy definována v paměti MCU. Délka vypisovaného textu není omezena, jelikož šířky znaků v definované znakové sadě nejsou u včech znaků stejné. Znaková sada "font1" je definována v souboru lcd_dogm132_font.h.
Vstupy funkce:
x (0 - 131) - x souřadnice - bráno od levého dolního rohu (displej i text)
y (0 - 31) - y souřadnice - bráno od levého dolního rohu (displej i text)
txt[] (0-255) - řetězec písmen, které mají být zobrazeny
Funkce pro vykreslení zobrazovacího bufferu na displej. Je popsána v kapitole Vykreslování pixelů na displej.
Funkce pro vykreslení jednoduchého grafu. Vykreslí na displej jednoduchý graf s 10 dílky na x-ové ose a pěti dílky na y-ové ose, popisek grafu, rozsahy na ose y a velikost dílku na ose x. Dále vykreslí body ze zadaného pole proměnných y, vždy jeden bod na dílek osy x a tyto body propojí spojnicemi. Funkce využívá dalších dvou podfunkcí "LCD_graph_cross(...)" pro vykreslení křížků v bodech a LCD_print_num_small(...0) pro vypsání číslic do grafu. Znaková sada "font2" pro tuto funkci je definována v lcd_dogm132_font.h.
Vstupy funkce:
x (0-76) - x souřadnice - levý spodní roh grafu
yp (0 - 255) - pole y hodnot
xscale (0-255)- krok hodnot na ose x grafu
yscale1 (0-255)- dolní hranice y hodnot grafu
yscale2 (0-255)- horní hranice y hodnot grafu
variable (txt) - popisek grafu přibližne max 5 znaků
Příklad definice funkce na vykreslování obdelníků LCD_rect(...).
extern void LCD_rect(u8 x1, u8 y1, u8 x2, u8 y2, u8 border, bool filled) { u32 i = 0; u32 j = 0; if(filled) // pokud ma byt obdelnik vyplneny nastavi border na 16 { border = 16; if((x2-x1) < (y2-y1)) // upravi ramecek podle mensi delky strany obdelniku, { // tak aby nedoslo k prolnuti pres protejsi stranu if((border > x2 -x1) && ~filled) { border = (x2 - x1); } } else { if((border > y2 -y1) && ~filled) { border = (y2 - y1); } } } for(j=0 ; j < border ; j++ ) // vykresli tolik obdelniku smerem dovnitr, { // kolik je zadana sirka okraje for(i = x1 ; i < x2 ; i++) // vykresleni vodorovnych car do bufferu displeje { disp_buf[i] |= (1 << (32-y1)); disp_buf[i] |= (1 <<); } for(i = y1 ; i <= y2 ; i++) // vykresleni svislych car do bufferu displeje { disp_buf[x1] |= (1 << (32-i)); disp_buf[x2] |= (1 << (32-i)); } x1++; // zmenseni rohovych souradnic smerem dovnitr obdelniku x2--; y1++; y2--; } }
Displej pro zmíněnou meteostanici by mohl vypadat následovně:
Knihovna funkcí LCD displeje EA DOGM132-X5:
LCD_dog132.rar
Projekt s příklady použití knihovny pro Keil uVision 4:
LCD_dog132_proj.rar
Video s přikladem použití:
LCD_dog132_meteo.avi