|
Pilotare un Display compatibile HD44780
Introduzione a HD44780
Di certo un display LCD è assolutamente inutile senza un circuito elettronico in grado di gestirlo e, dato l'oneroso compito a cui è chiamato, sembra improbabile solo pensare a realizzarlo con componenti discreti. Per questo il mercato offre strutture integrate (moduli) dotate di tutto ciò che serve, montato su un circuito stampato; da un lato è saldato il display e sul lato opposto sono presenti numerosi componenti, tra cui circuiti integrati. Certamente il più importante tra questi è il controller, un componente programmabile con una duplice funzione:
- dispone della struttura necessaria per gestire fino a 50 (10 * 5) pixel per ciascuno dei possibili caratteri alfanumerici del display, organizzati su una o più righe;
- assicura l' interfaccia intelligente tra il visualizzatore e il processore o il microcontrollore chiamato a gestirlo.
Il controller di gran lunga più diffuso ed utilizzato sul mercato è senz'altro il controller HD44780 della Hitachi, quasi uno standard di fatto.
Lo schema a blocchi di un display basato su HD44780 è tipicament questo (io riporto lo schema per il modello TM204):

Piedinatura del modulo LCD
| N. Pin |
Nome |
I/O |
Descrizione |
| 1 |
Vss |
Power |
Massa |
| 2 |
Vcc |
Power |
+5V |
| 3 |
Vo |
Analog |
Regolazione contrasto |
| 4 |
RS |
Input |
Selezione dati/istruzioni |
| 5 |
R/W |
Input |
Read/Write |
| 6 |
E |
Input |
Abilitazione |
| 7 |
D0 |
I/O |
Dati LSB |
| 8 |
D1 |
I/O |
Dati |
| 9 |
D2 |
I/O |
Dati |
| 10 |
D3 |
I/O |
Dati |
| 11 |
D4 |
I/O |
Dati |
| 12 |
D5 |
I/O |
Dati |
| 13 |
D6 |
I/O |
Dati |
| 14 |
D7 |
I/O |
Dati MSB |
| 15 |
A |
Power |
Retroilluminazione (+) |
| 16 |
K |
Power |
Retroilluminazione (GND) |
|
| Tab.1 - Assegnazione Pin |
- I pin 1 (Vss) e 2 (Vcc) servono per fornire alimentazione (5 volt); di solito l'assorbimento è contenuto, dell'ordine di pochi mA.
- Il pin 3 (Vo) è un ingresso analogico al quale si deve fornire una tensione compresa tra 0 e 5V al fine di regolare il contrasto del display, cioè la capacità di rendere più o meno scuri i pixel attivi, per rendere migliore la visualizzazione, in funzione della luminosità dell’ambiente, del display; di solito la regolazione si ottiene con un potenziometro da 10k.
- Il pin 4 (RS), detto Register Selector, indica la natura dell’informazione presente sul bus dati: se viene forzato a 0 il byte in ingresso sarà interpretato come un comando da eseguire (istruzione), mentre con un 1 sarà ritenuto dato da interpretare.
- Il pin 5 (R/W) specifica la direzione dei bytes sul bus: se vale 0 si sta scrivendo nella memoria interna LCD, mentre con un 1 questa memoria è sottoposta a lettura.
- Il pin 6 (E) è il segnale che abilita il dispositivo: quando è a livello alto sincronizza la lettura del dato o del comando predisposto sul bus dati. L'Enable è il vero e proprio segnale di sincronismo, da forzare a 1 quando il dispositivo è pronto a gestire un dato o un comando predisposto sul bus dati (in funzione del valore del busy flag: finché il suo valore è 1 il controller è occupato a gestire i trasferimenti interni e non è in grado di accettare l'istruzione successiva).
- I pin dal numero 7 al numero 14 (D0-D7) rappresentano il Data Bus su cui avviene la trasmissione o ricezione dati dal display, in base all’operazione che si sta svolgendo
- I pin 15 e 16, mediante i quali è possibile alimentare l'eventuale luce di retroilluminazione.
Lo schema di connessione al microcontrollore è molto semplice:

Il transistor BC547 è utilizzato per accendere la retroilluminazione.
Set Caratteri disponibili in ROM
Questa struttura si basa sulla presenza di una capace memoria CGROM (Character Generator Read Only Memory), contenente i font dei 208 caratteri da 5x8 punti (8320 bit) e dei 32 caratteri da 5x10 punti (1600 bit). Il codice del carattere che si desidera visualizzare, fornito come dato al controller, consente di localizzare la matrice di punti corrispondente all'interno di questa memoria a sola lettura, in accordo con la seguente tabella:
 |
| Tab.2 - Codici carattere per matrice 5x8 |
Il set di istruzioni
Il componente HD44780 è nato per costituire un'interfaccia con qualunque microprocessore o controllore di processo in grado di fornire i 2 segnali R/W e RS che regolano il traffico d'informazioni del suo bus dati a 8bit. Anche una porta parallela può simulare con estrema facilità questa gestione.
Naturalmente diventa importante imparare le istruzioni che consentono il controllo alla CPU esterna; alcune istruzioni sono dedicate al controllo del visualizzatore, altre alla gestione dei dati sulle 2 RAM.
Le istruzioni (bytes di comando) necessarie per controllare il display sono raccolte nella tabella seguente:
| Istruzione |
Input |
Data Bus |
Descrizione |
Tempo MAX |
| RS |
R/W |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
| NOP |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Nessuna operazione |
0s |
| Cancella display |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
Cancella il visualizzatore e fa tornare il cursore alla posizione 0. |
1,64ms |
| Cursore a capo |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
- |
Riporta il cursore alla posizione 0. |
1,64ms |
| Modo d'accesso dei caratteri |
0 |
0 |
0 |
0 |
0 |
1 |
I |
S |
Imposta la direzione del movimento del cursore (I/D) e specifica se muovere il display (S). Queste operazioni sono fatte durante la lettura/scrittura dati. |
40µs |
| Controllo Display |
0 |
0 |
0 |
0 |
1 |
D |
C |
B |
Imposta il display On/Off (D), il cursore On/Off (C) e il lampeggio del cursore (B). |
40µs |
| Scorrimento cursore e display |
0 |
0 |
0 |
1 |
S/C |
R/L |
- |
- |
Imposta il movimento del cursore o lo spostamento del display (S/C) e la direzione del movimento. Il contenuto della DDRAM rimane invariato. |
40µs |
| Impostazioni Funzioni |
0 |
0 |
1 |
DL |
N |
F |
- |
- |
Imposta la lunghezza dei dati dell'interfaccia (DL), il numero di linee del display (N) e il font del carattere (F). |
40µs |
| Indirizzo CGRAM |
0 |
1 |
CGRAM Address |
Imposta l'indirizzo della CGRAM. Il dato CGRAM deve essere inviato o ricevuto dopo questa impostazione. |
40µs |
| Indirizzo DDRAM |
1 |
DDRAM Address |
Imposta l'indirizzo della DDRAM. Il dato CGRAM deve essere inviato o ricevuto dopo questa impostazione. |
40µs |
| Lettura Bit di Stato/Indirizzo |
1 |
BF |
Address Counter |
Legge Busy Flag e l'Address Counter |
0s |
| Scrittura dato |
1 |
0 |
Dato da scrivere |
Scrive un dato nella CGRAM o nella DDRAM |
40µs |
| Lettura dato |
1 |
Dato da leggere |
Legge un dato dalla CGRAM o dalla DDRAM |
40µs |
|
| Tab.3 - Set di istruzioni del controller HD44780 |
Driver SW per HD44780
Il driver SW è del tutto parametrico e facile da utilizzare con qualunque Microcontrollore anche se non Infineon XE164. Prima di procedere alla compilazione, bisogna procedere a configurare le porte utilizzate per la connessione, il file HD44780.h deve essere perciò modificato a seconda delle proprie esigenze:
// Port Connection Defines
#define RS_LINE P1_OUT_P4
#define RW_LINE P1_OUT_P5
#define E_LINE P1_OUT_P7
#define DATA_PORT P0
#define DATA_PORT_OUT P0_OUT
#define DATA_PORT_IN P0_IN
#define CONTROL_DATA_PORT_0 CONTROLIO_P0_0
#define CONTROL_DATA_PORT_1 CONTROLIO_P0_1
#define CONTROL_DATA_PORT_2 CONTROLIO_P0_2
#define CONTROL_DATA_PORT_3 CONTROLIO_P0_3
#define CONTROL_DATA_PORT_4 CONTROLIO_P0_4
#define CONTROL_DATA_PORT_5 CONTROLIO_P0_5
#define CONTROL_DATA_PORT_6 CONTROLIO_P0_6
#define CONTROL_DATA_PORT_7 CONTROLIO_P0_7
#define CONTROL_RS_LINE CONTROLIO_P1_4
#define CONTROL_RW_LINE CONTROLIO_P1_5
#define CONTROL_E_LINE CONTROLIO_P1_7
Come visibile io ho utilizzato le porte P1.4 per RS, P1.5 per RW, P1.7 per E. La porta dati è connessa alla porta P0 del Microcontrollore XE164 percui i pins P0.0 ... P0.7 devono essere configurati opportunamente dal SW mediante la chiamata della funzione ""LCDinitialize
//****************************************************************************
// @Function LCDinitialize
//
//----------------------------------------------------------------------------
// @Description Inizialize LCD display, this fuction is the first routine to call
// sets the control port and the data port
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters None
//
//----------------------------------------------------------------------------
// @Date 21/05/2009
//
//****************************************************************************
void LCDinitialize(void)
{
// Display control Port
IO_vSetPinOut ( _RS_LINE, IO_PUSH_PULL) ;
IO_vSetPinOut ( _RW_LINE, IO_PUSH_PULL) ;
IO_vSetPinOut ( _E_LINE, IO_PUSH_PULL) ;
// Display Data Port
IO_vSetPortOut ( DATA_PORT, 0xFF);
IO_vSetPinOut ( _DATA_PORT_0, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_1, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_2, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_3, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_4, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_5, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_6, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_7, IO_PUSH_PULL) ;
DATA_PORT_OUT = 0x00;
RS_LINE = 0;
RW_LINE = 0;
E_LINE = 1;
GPT2_waitXXms(20);
LCDwriteCtrl(0x38); //function set
GPT2_waitXXms(10);
LCDwriteCtrl(0x38); //function set
GPT2_waitXXms(1);
LCDwriteCtrl(0x08); //disp off
GPT2_waitXXms(1);
LCDwriteCtrl(0x06); //entry mode set
GPT2_waitXXms(1);
LCDwriteCtrl(0x01); //display clear
GPT2_waitXXms(10);
LCDwriteCtrl(0x0c); //disp on
GPT2_waitXXms(1);
}
La configurazione delle porte avviene in fase di inizializzazione mediante chiamata alle funzioni:
...
IO_vSetPinOut ( _DATA_PORT_0, IO_PUSH_PULL) ;
IO_vSetPinOut ( _DATA_PORT_1, IO_PUSH_PULL) ;
...
Esse eseguono la inizializzazione delle porte P0 come uscita con drive Push-Pull abilitati (le funzioni IO_vSetPinOut sono funzioni standard generate da DaVE).
Le funzioni seguenti non necessitano di molti commenti:
- void LCDhome(void); --> setta il cursore nella posizione Home
- void LCDclear(void); --> pulisce lo schermo
- void LCDdispON(void); --> accende il display
- void LCDdispOFF(void); --> spegne il display
- void LCDgoToPos(ubyte line, ubyte pchar); --> sposta il cursore in (line, pchar)
Il cuore del Driver SW è la funzione "LCDwriteString":
//****************************************************************************
// @Function LCDwriteString
//
//----------------------------------------------------------------------------
// @Description Write a string
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters String to be written
//
//----------------------------------------------------------------------------
// @Date 21/05/2009
//
//****************************************************************************
void LCDwriteString(sbyte *string)
{
uword inx=0;
while(string[inx] != '\0')
{
LCDwriteChar(string[inx]);
inx++;
}
}
Infine la funzione "LCDtest" permette di eseguire una sequenza di visualizzazione a modi test di accensione:
//****************************************************************************
// @Function LCDtest
//
//----------------------------------------------------------------------------
// @Description Test the correct functioning of displaly
//
//----------------------------------------------------------------------------
// @Returnvalue None
//
//----------------------------------------------------------------------------
// @Parameters None
//
//----------------------------------------------------------------------------
// @Date 21/05/2009
//
//****************************************************************************
void LCDtest(void)
{
ubyte check1[] = {0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff};
ubyte check2[] = {0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80, 0xff, 0x80};
LCDgoToPos(1,1);
LCDwriteString(check1);
LCDgoToPos(2,1);
LCDwriteString(check2);
LCDgoToPos(3,1);
LCDwriteString(check1);
LCDgoToPos(4,1);
LCDwriteString(check2);
LCDwait60cycles();
LCDgoToPos(1,1);
LCDwriteString(check2);
LCDgoToPos(2,1);
LCDwriteString(check1);
LCDgoToPos(3,1);
LCDwriteString(check2);
LCDgoToPos(4,1);
LCDwriteString(check1);
LCDwait60cycles();
LCDclear();
}
Nota:
Il Driver SW per HD44780 si basa su due funzioni di ritardo per poter eseguire le operazioni con le corrette tempistiche (così come definite nella Tab.3):
-
void LCDwait60cycles(void); --> una semplice funzione per eseguire un breve ritardo
-
extern void GPT2_waitXXms (unsigned int i); // Not defined in this project file since is application related. In case of not having any available timer, just replace with a \for{ _nop();} statement
Percui dovete predisporre la funzione "GPT2_waitXXms" che avrà lo scopo di ritardare l'esecuzione di xx msec (cioè esegue un ritardo pari a "i" in millisecondi, ad esempio "GPT2_waitXXms (5)" deve generare un ritardo pari a 5 msec).
Futuri Sviluppi
Anche se non ne ho parlato, dovete sapere che è anche possibile definire il proprio set di caratteri e realizzare semplici grafiche come ad esempio un visualizzatore a barra (proporzionale perciò ad una grandezza analogica):
Buon lavoro !!!!
|