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 :
sfondo
verde con caratteri di colore nero;
sfondo
azzurro con caratteri di colore bianco.
Osservazione
1 – il controller è formato da due memorie :
CGROM
(Character Generator Read Only Memory) che contiene le informazione
dei caratteri gestiti (font). Questi caratteri di default possono
essere cambiati.
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 :
IR
: è un registro di sola scrittura, memorizza i comandi, e viene
usato quando il pin RS=”0”;
DR
: è un registro che memorizza il dato che le istruzioni che
arrivano devono gestire;
Osservazione
3 – quando il display viene usato anche in lettura :
il
bus da D0 a D6 viene usato per identificare il valore del contatore
interno che definisce la posizione del cursore (address counter);
il
bit D7 è il busy flag che gestisce le informazioni nel seguente
modo :
D7=”0”
il bus è libero per ricevere comandi o dati;
D7=”1”
il bus è occupato.
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 :
bus
da 4 bit
RS
per definire se l'informazione presente sul bus è un comando
(RS=”0”) o un dato da visualizzare (RS=”1”)
E
(Enable) abilita la lettura del dato presente sul bus. E' importante
aver già messo il dato (comando o dato) sul bus e settato RS prima
di alzare l'enable.
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
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