Knihovna pro LCD SPI displej EA DOGM132

projekt z předmětu MMIA

Bc. Karel Románek, UREL, FEEC, VUT Brno
xroman00stud.feec.vutbr.cz

Obsah:

  1. Úvod
  2. Realizace
  3. Příklad použití
  4. Ke stažení
  5. Závěr
  6. Literatura

Úvod

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.

Realizace

LCD displej EA DOG132M

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.

schéma zapojení testovací desky

Obr. 1: Zapojení testovací desky s displejem DOGM132X-5
displej na nepajivem poli a vyvojový kit

Obr. 2: Zapojení displeje na nepájivém poli, připojené k vývojovému kitu

SPI komunikace s displejem

Kvůli jednodušší přenositelnosti knihovny mezi platformami je SPI komunikace řešena softwarovou implementací. Vždy se přenáší 1 byte příkazů nebo dat. Komunikace mezi MCU a displejem začíná uvedením chip select pinu LCD_CS disleje do Log0. Následuje 8 impulsů hodinového signálu LCD_SCK. Při každém impulsu se mění také ůroveň signálů LCD_SI podle odesílaného bytu od MSB k LSB. Při osmém LCD_SCK impulsu je displejem přečtena úroveň pinu LCD_A0, čímž je vybrán typ přenášených dat, Log0 pro příkazy a Log1 pro data. Průběh komunikace je zobrazen na obr. 3.
diagram přenosu dat

Obr. 3: Průběh komunikace s displejem [1]

Tuto komunikaci zajistuje funkce "LCD_SendByte(...)" pro odesílání 1 bytu definovaná v lcd_dogm132_com.c. Zdrojový kód je uveden dále:

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;  
  }
}
	

Inicializace displeje

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.

Vykreslování pixelů na displej

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.

schéma zapojení testovací desky

Obr. 4: Adresní prostor zobrazovací paměti řadiče.

Při adresování zobrazovací paměti se nejdříve odesláním série příkazů zadá adresa strany (0-3) a adresa sloupce (0-131). Od adresy sloupce v dané straně bude probíhat zapisování. Dále jsou již odesílána obrazová 8-bitová data. Při úspěšném přijetí každého bytu obrazových dat je inkrementována adresa sloupce paměti. Všechny dále popsané vykreslovací funkce (vykreslovaní pixelů, čar, znaků, atd.) vždy pouze připraví potřebná data do zobrazovacího bufferu displeje. Buffer displeje (disp_buf[132]) je pole o 132 prvcích typu unsigned integer. Při vykreslování jsou jednotlivé prvky bufferu bitovým maskováním a rotací rozděleny na 8-bitové data, které se odesílají do řadiče displeje. Toto zajišťuje funkce "LCD_redraw_buffer(...)" definovaná v lcd_dogm132_com.c.

  
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
}  

Vykreslovací funkce

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í:


extern void LCD_init(void)

Funkce pro inicializaci displeje. Je popsána v kapitole Inicializace displeje.

extern void LCD_clear(void)

Funkce pro mazání displeje. Funkce pouze nastaví všechny bity v zobrazovacím bufferu na log0


extern void LCD_set_all(void)

Funkce pro vykreslení všech pixelů displeje. Funkce pouze nastaví všechny bity v zobrazovacím bufferu na log1.


extern void LCD_draw_px(u8 x, u8 y)

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


extern void LCD_line(u8 x1, u8 y1, u8 x2, u8 y2)

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


extern void LCD_rect(u8 x1, u8 y1, u8 x2, u8 y2, u8 border, bool filled)

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


extern void LCD_progress_bar(u8 x1, u8 y1, u8 x2, u8 y2, u8 prog, u8 dir)

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í


extern void LCD_print_string(u8 x, u8 y, u8 *txt)

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


extern void LCD_redraw_buffer(void)

Funkce pro vykreslení zobrazovacího bufferu na displej. Je popsána v kapitole Vykreslování pixelů na displej.

extern void LCD_graph(u8 xs,u8 *yp, u8 yscale1, u8 yscale2)

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--;
  }
}
  

Příklad použití

Displej pro zmíněnou meteostanici by mohl vypadat následovně:


Pro představu je zachynec

Ke stažení

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

Závěr

V rámci tohoto projektu se podařilo vytvořit knihovnu zobrazovacích funkcí pro grafický LCD displej EA DOGM132-X5. Knihovna by měla být přenositelná i na jiné platformy než na STM32. Do knihovny by bylo možné ještě přidat další funkce pro vykreslování kružnice případně dalších ovládacích prvků, podle požadavků jiné aplikace. Možným vylepšením by byla úprava algoritmu funkce pro vykreslování čáry s hlídáním chyby výpočtu.

Literatura

[1] ELECTRONIC ASSEMBLY, GILCHING: DOGM GRAPHIC SERIES 132x32 DOTS, [online].last revision Jun-2009, [cit. 2010-5-28]. 8 s. Dostupný na:
<http://www.lcd-module.de/eng/pdf/grafik/dogm132-5e.pdf>
[2] SINTRONIX: ST7565R 65x132 Dot Matrix LCD Controller/Driver, [online].last revision Mar-2006, [cit. 2010-5-28]. 72 s. Dostupný na:
<http://www.sitronix.com.tw/sitronix/SASpecDoc.nsf/FileDownload/ST7565R1189450/$FILE/ST7565R%20V17c_980914.pdf>
[3] STMicroelectronics NV, STAEFA : STM32F103x8 STM32F103xB, [online]. last revision 22-Sep-2009, [cit. 2010-4-18]. 92 s. Dostupný na:
<http://www.st.com/stonline/products/literature/ds/14611.pdf>