DISPLAY LCD



I display a cristalli liquidi o LCD (Liquid Crystal Display), vengono contraddistinti dal numero di righe (fino a 4) e il numero di caratteri (fino a 40) (es. 16x2 significa 2 righe e 16 caratteri). Sono utilizzati quando non bastano i tradizionali display a 7 segmenti. Sono definiti display intelligenti perchè hanno all'interno un controller che semplifica la gestione di questi mediante i microcontrollori. L'interfaccia citata è la HD44780 della Hitachi, divenuta uno standard, infatti anche le altre marche si sono adeguate allo stesso funzionamento, così da essere tutti compatibili. Altra caratteristica importante è il colore della retroilluminazione, i due più importanti sono :

  1. sfondo verde con caratteri di colore nero;

  2. sfondo azzurro con caratteri di colore bianco.



Osservazione 1 – il controller è formato da due memorie :

  1. CGROM (Character Generator Read Only Memory) che contiene le informazione dei caratteri gestiti (font). Questi caratteri di default possono essere cambiati.

  2. DDRAM (Display Data Random Access Memory) che matiene in memoria il contenuto e la posizione (che dipende dalla locazione in cui è memorizzato il contenuto) del dato da visualizzare. Ha una capacità fissa di 80 locazioni. Quindi per display 16x2 rimangono locazioni libere, mentre per display 40x4 necessita di un secondo banco da 80 locazioni e l'aggiunta di un secondo enable (E) quindi avranno un pin in più nel connettore. Le locazioni non usate possono essere usate come RAM, ma in questo caso il display va usato sia in scrittura che in lettura.



Osservazione 2 – il controller ha due registri :

  1. IR : è un registro di sola scrittura, memorizza i comandi, e viene usato quando il pin RS=”0”;

  2. DR : è un registro che memorizza il dato che le istruzioni che arrivano devono gestire;

Osservazione 3 – quando il display viene usato anche in lettura :

Istruzione

RS

D7

D6

D5

D4

D3

D2

D1

D0

Descrizione

Pulisci display (Clear Display)

0

0

0

0

0

0

0

0

1

Cancella il contenuto del display e pone l’Address Counter a 0 (il cursore torna quindi in posizione 1 alla prima riga)

Home

0

0

0

0

0

0

0

1

x

Pone l’Address Counter a 0 (riporta il cursore ad inizio riga)

Modalità immissione (Entry Mode Set)

0

0

0

0

0

0

1

I/D

S

Imposta l’incremento della posizione nella DDRAM (I/D = Increment/Decrement) e lo spostamento del display (S = Shift display)

Controllo display (Display on/off control)

0

0

0

0

0

1

D

C

B

Spegne/accende il display (D = Display), visualizza/nasconde il cursore (C = Cursor), fa lampeggiare/rimaner fisso il cursore (B = Blinking)

Spostamento cursore o Display (Cursor or Display shift)

0

0

0

0

1

S/C

R/L

x

x

Imposta il movimento del cursore o del display (S/C = Shift display/Cursor) e lo spostamento del display (R/L = Right/Left) senza cambiare il contenuto della DDRAM

Impostazione funzioni (Function Set)

0

0

0

1

DL

N

F

x

x

Imposta la lunghezza dati dell’interfaccia (8 o 4 bit) (DL = Data Length), numero di righe del display (N = Number), grandezza del font da utilizzare (F = Font)

Indirizzo CGROM (Set CGROM Address)

0

0

1

*

*

*

*

*

*

Imposta il punto (l’indirizzo) della CGROM in cui scrivere o da cui leggere. (al posto degli asterischi va impostato l’indirizzo: es: inviamo 0100 0000 => setta l’indirizzo della CGROM al primo carattere). Il dato sarà disponibile (o verrà scritto) dopo questa impostazione. Questa funzione è utile per impostare i caratteri custom.

Indirizzo DDRAM (Set DDRAM Address)

0

1

*

*

*

*

*

*

*

Imposta il punto (l’indirizzo) della DDRAM in cui scrivere o da cui leggere. (al posto degli asterischi va impostato l’indirizzo: es: inviamo 1000 0000 => setta l’indirizzo della DDRAM al primo carattere, 1100 0000 =>setta l’indirizzo della DDRAM al primo carattere della seconda riga). Il dato sarà disponibile (o verrà scritto) dopo questa impostazione

Le lettere in tabella hanno il seguente significato :

Simbolo del bit

0”

1”

I/D

Incrementa/decrementa la posizione in DDRAM

Posizione

S

Il testo rimane fermo

Il testo si sposta

D

Display spento

Display acceso

C

Cursore invisibile

Cursore visibile

B

Il cursore non lampeggia

Il cursore lampeggia

S/C

Si sposta il cursore

Si sposta il display

R/L

Spostamento a sinistra

Spostamento a destra

DL

Interfaccia a 4 bit

Interfaccia ad 8 bit

N

Il display ha una sola riga

Il display ha 2 o più righe

F

Font 5×8

Font 5×10

X

Qualsiasi valore non influenza




Noi useremo un display a sfondo verde e carattere nero di tipo 16x2. Si presenta nel seguente modo :




La piedinatura di solito è la seguente :



Pin

Denominazione

Descrizione

1

Vss o Gnd

Massa

2

Vcc

+5V

3

Vcontrasto

Regolazione contrasto ( 0 … 5 V )

4

RS

Register Select (selezione comando RS=”1”, dati RS=”0”)

5

R/W

Read/Write R/W=”0” per inviare dati, R/W=”1” per leggere dati

6

E

Enable (Abilitazione) linea di controllo, con E=”1” si abilita il display a ricevere dati e istruzioni

7

D0

Linea Dati, bit 0

8

D1

Linea Dati, bit 1

9

D2

Linea Dati, bit 2

10

D3

Linea Dati, bit 3

11

D4

Linea Dati, bit 4

12

D5

Linea Dati, bit 5

13

D6

Linea Dati, bit 6

14

D7

Linea Dati, bit 7

15

A

Anodo Retroilluminazione (+4.2V)

16

K

Catodo Retroilluminazione (Massa)



Intanto bisogna dire che il pin 15 e 16 spesso non sono utilizzati.

I dati possono essere trasferiti a byte (D0 … D7) e nibble (D4 … D7), la seconda soluzione fa risparmiare pin sul microcontrollore ed è quella che useremo, quindi i pin D0 … D3 vanno collegati a massa.

Anche il pin R/W non viene utilizzato e quindi viene collegato a massa (quindi si potrà solo inviare dati verso il display).

Per poter scrivere sul display quindi abbiamo :

Per poter usare dei nibble al posto dei byte si fa un operazione di multiplex : si invia prima il nibble basso e poi il nibble alto, il controller ricostruirà il byte.

Oltre ai pin di alimentazione (+5V, GND) c'è il Vcontrasto che va collegato a un potenziometro che ci permette di trovare un valore adatto. Lo schema è il seguente :




Lo schema della EASYPIC 3 si presenta così :






a questo punto decido di usare, cliccando la spunta nella library manager, le librerie che mikroC PRO mi mette a disposizione :



La funzione principale, quella di settaggio, è la



void Lcd_Init(); // prototipo



Lcd_Init (); //questa va chiamata una sola volta all'inizio del sorgente

Questa richiede di abbinare delle variabili globali usate nella libreria ai pin usati nella scheda prima di essere chiamata :



sbit LCD_RS at RB2_bit; // assegna alla variabile LCD_RS il pin 2 della PORTB

sbit LCD_EN at RB3_bit; // assegna alla variabile LCD_EN il pin 3 della PORTB

sbit LCD_D4 at RB4_bit; // assegna alla variabile LCD_D4 il pin 4 della PORTB

sbit LCD_D5 at RB5_bit; // assegna alla variabile LCD_D5 il pin 5 della PORTB

sbit LCD_D6 at RB6_bit; // assegna alla variabile LCD_D6 il pin 6 della PORTB

sbit LCD_D7 at RB7_bit; // assegna alla variabile LCD_D7 il pin 7 della PORTB



sbit LCD_RS_Direction at TRISB2_bit; // assegna la direzione di LCD_RS il pin 2 della PORTB

sbit LCD_EN_Direction at TRISB3_bit; // assegna la direzione di LCD_EN il pin 3 della PORTB

sbit LCD_D4_Direction at TRISB4_bit; // assegna la direzione di LCD_D4 il pin 4 della PORTB

sbit LCD_D5_Direction at TRISB5_bit; // assegna la direzione di LCD_D5 il pin 5 della PORTB

sbit LCD_D6_Direction at TRISB6_bit; // assegna la direzione di LCD_D6 il pin 6 della PORTB

sbit LCD_D7_Direction at TRISB7_bit; // assegna la direzione di LCD_D7 il pin 7 della PORTB



poi ci sono le funzioni che scrivono delle stringhe :



void Lcd_Out(char row, char column, char *text); //prototipo



Lcd_Out (char valore o variabile riga, char valore o variabile colonna, testo da visualizzare);



per specificare la posizione riga, colonna e il testo da scrivere. Posso scriverla anche



Lcd_Out (char valore o variabile riga, char valore o variabile colonna, *stringa);



dove scrivo il valore della stringa.

Esempio

Lcd_Out(1,2,”Noi siamo la”);

Lcd_Out(1,4,”5 B ITI”);



la libreria che fa copia a questa, ma che non specifica la posizione, ma assume quella corrente del cursore, è la seguente



void Lcd_Out_Cp(char *text); //prototipo



Lcd_Out_Cp(“testo da scrivere);



oppure



Lcd_Out_Cp(char *stringa);



Le funzioni che scrivono un carattere:



void Lcd_Chr(char row, char column, char out_char);



Lcd_chr (char valore o variabile riga, char valore o variabile colonna, 'carattere');



che visualizza il carattere racchiuso tra apici nella riga, colonna specificata. Oppure



Lcd_chr (char valore o variabile riga, char valore o variabile colonna, valore o char variabile o registro);



Visualizza il simbolo corrispondente al codice ASCII del valore inserito o del valore della variabile o del contenuto di un registro. La stessa istruzione, che però non specifica la posizione, ma assume quella corrente del cursore :



Lcd_Chr_Cp('carattere');



oppure



Lcd_Chr_Cp(variabile o registro corrispondente codice ASCII);

È importante tener presente, che la tabella dei caratteri che la memoria CGROM contiene di default, è per la maggior parte corrispondente al codice ASCII :








l'ultima funzione è quella che ci permette di fornire comandi al display :



void Lcd_Cmd(char out_char);



Lcd_Cmd(comando);



i comandi disponibili sono elencati sotto e sono evidenziati in blu :



_LCD_FIRST_ROW

Move cursor to the 1st row

_LCD_SECOND_ROW

Move cursor to the 2nd row

_LCD_THIRD_ROW

Move cursor to the 3rd row

_LCD_FOURTH_ROW

Move cursor to the 4th row

_LCD_CLEAR

Clear display

_LCD_RETURN_HOME

Return cursor to home position (1,1)

_LCD_CURSOR_OFF

Turn off cursor (spegne cursore)

_LCD_UNDERLINE_ON

Underline cursor on (attiva cursore linea bassa)

_LCD_UNDERLINE_OFF

Underline cursor off (disattiva cursore linea bassa)

_LCD_BLINK_CURSOR_ON

Blink cursor on (attiva cursore lampeggiante)

_LCD_BLINK_CURSOR_OFF

Blink cursor off (disattiva cursore lampeggiante)

_LCD_MOVE_CURSOR_LEFT

Move cursor left without changing display data RAM

_LCD_MOVE_CURSOR_RIGHT

Move cursor right without changing display data RAM

_LCD_TURN_ON

Turn Lcd display on (accende display)

_LCD_TURN_OFF

Turn Lcd display off (spegne display)

_LCD_SHIFT_LEFT

Shift display left without changing display data RAM

_LCD_SHIFT_RIGHT

Shift display right without changing display data RAM

Esempio

LCD_Cmd(LCD_CLEAR); // CANCELLA IL DISPLAY

Spesso si presentano le necessità di scrivere dei valori di locazioni o variabili sul display, e per fare questo ci vengono in aiuto funzioni di conversione da tipi di variabile a stringhe facilmente gestibili.

ByteToStr



void ByteToStr(unsigned short input, char *output); //prototipo





unsigned short t = 24;
char txt[4];
...
ByteToStr(t, txt);

Ricordo prima di proseguire che una stringa contiene sempre un carattere '\0' di chiusura, per questo nell'esempio sopra e in quelli che seguiranno l'array che contiene la stringa ha una posizione che non compare. Nell'esempio appena visto abbiamo un array da 4 posti, un valore di due cifre e vediamo che la stringa è formata da [spazio vuoto – 2 – 4 – null]

shortToStr



void ShortToStr(short input, char *output); //prototipo



short t = -24;
char txt[5];
...
ShortToStr(t, txt);// txt conterrà “ -24”



WordToStr



void WordToStr(unsigned input, char *output); //prototipo



unsigned t = 437;
char txt[6];
...
WordToStr(t, txt);  // txt is "  437" (2 caratteri vuoti)



IntToStr



void IntToStr(int input, char *output); //prototipo



int j = -4220;
char txt[7];
...
IntToStr(j, txt);  // txt is " -4220" (un carattere vuoto)



LongToStr



void LongToStr(long input, char *output); //prototipo



long jj = -3700000;
char txt[12];
...
LongToStr(jj, txt);
// txt is "   -3700000" (3 spazi vuoti)



LongWordToStr



void LongWordToStr(unsigned long input, char *output);



unsigned long jj = 3700000;
char txt[11];
...
LongWordToStr(jj, txt);
// txt is "   3700000" (3 caratteri vuoti)



FloatToStr



unsigned char FloatToStr(float fnum, unsigned char *str);



float ff1 = -374.2;
float ff2 = 123.456789;
float ff3 = 0.000001234;
char txt[15];
...
FloatToStr(ff1, txt);  // txt is "-374.2"
FloatToStr(ff2, txt);  // txt is "123.4567"
FloatToStr(ff3, txt);  // txt is "1.234e-6"



rtrim



char *rtrim(char *ptr);



Dec2Bcd



unsigned short Dec2Bcd(unsigned short decnum); //prototipo



unsigned short a, b;
...
a = 25;
b = Dec2Bcd(a);    // b equivale 37



Bcd2Dec16



unsigned Bcd2Dec16(unsigned bcdnum);



unsigned a, b;
...
a = 0x1234;          // a equivale al valore decimale : 4660
b = Bcd2Dec16(a);    // b equivale al BCD : 1234



Dec2Bcd16



unsigned Dec2Bcd16(unsigned decnum);



unsigned a, b;
...
a = 2345;
b = Dec2Bcd16(a);    // b equals 9029
L'ultimo argomento che tratteremo riguarda la personalizzazione di caratteri. MikroC PRO ha uno strumento che produce il codice automaticamente :
Tools – LCD Custom Character