Corso programmazione PICMicro in C – Lezione 7 (parte 1/3) – Interfaccia con LCD – Tutto quello che c’e´ da sapere sui display LCD alfanumerici “intelligenti”
Aggiornamento Ottobre 2017
La Microchip ha rilasciato nuovi tool per lo sviluppo: MPLAB X IDE e i compilatori XC. Per far fronte alle novità e per non riscrivere tutti gli articoli daccapo, ho scritto delle lezioni integrative per consentire il passaggio dai vecchi strumenti a quelli nuovi. Le nozioni teoriche riportate negli articoli “vecchi” sono ancora valide. Per quanto concerne la scrittura del codice, l’utilizzo dell’IDE, i codici di esempio ecc, fate riferimento alle nuove lezioni che si trovano nella categoria PICmicro nuovo corso.
Un display LCD è sicuramente un’interfaccia molto interessante e utile nei progetti utilizzanti i microcontrollori, questo perchè può visualizzare una grande varietà di informazioni e rendere quindi le cose più semplici agli utilizzatori per la creazione di menù, interfacce utente ecc.
La presenza sul mercato di display che presentano dei controller integrati, e rom già contenenti i caratteri (anche definiti “display intelligenti“), ha reso molto più semplice la progettazione di interfacce di controllo con i microcontrollori, specie quando l’interfaccia di comunicazione è di tipo parallelo: è dei display con interfaccia parallela che parleremo in questo articolo, in quanto si tratta dello standard più diffuso e anche più semplice da controllare.
Questa lezione sarà articolata in 3 parti: la prima parte (questa) è di introduzione sui display alfanumerici intelligenti , nella seconda parte il display verrà interfacciato con il picmicro e impareremo a scrivere (!) per cui sarà presentata una semplice applicazione dimostrativa di scrittura sull’LCD, con relativi codici sorgente. La terza parte, infine, sarà incentrata sulla personalizzazione dei caratteri, ovvero: come creare nuovi simboli da caricare nel display (come nell’immagine introduttiva, in cui sono stati definiti 3 simboli personalizzati, non presenti normalmente nell’ LCD).
I display più comuni sono quelli basati sull’arcinoto controller HD44780 prodotto dalla Hitachi, esistono comunque in giro numerosi display aventi controller prodotti da altre marche che sono compatibili con quello della Hitachi, ne riporto qui alcuni:
Produttore | Sigla controller |
---|---|
Hitachi | HD44780 |
Hitachi | HD66702 |
Samsung | KS0070 |
Samsung | KS0066 |
Samsung | S6A0069 |
Sanyo | LC7985 |
Epson | SED1278 |
OKI | MSM6222 |
Sunplus | SPLC780D |
L’equivalenza di tali controller è stata trovata su internet, specialmente sul noto sito di aste in cui vengono venduti display aventi tali controller e dichiarati compatibili con l’HD44780, tuttavia il sottoscritto ha avuto modo di provare unicamente l’HD44780 e il KS0066 e confermo l’equivalenza. In fondo all’articolo sono comunque riportati i datasheet di tutti i controller qui elencati e da un rapido sguardo posso affermare che in effetti non trovo differenze sostanziali, il lettore prenda però questa affermazione con le pinze e controlli il datasheet del controller in suo possesso.
I display utilizzanti tali controller sono costruiti con varie caratteristiche “esterne”, per cui in fase di acquisto possiamo scegliere il numero di righe e il numero di caratteri (o colonne) che il display è in grado di visualizzare (i più diffusi sono i display 16×2 : 2 righe, ognuna delle quali può visualizzare 16 caratteri), altra caratteristica da scegliere è la colorazione della retroilluminazione (la più comune è quella verde con caratteri neri, ma è molto diffusa anche la retroilluminazione blu con caratteri bianchi o più raramente rossa con caratteri neri).
Tali display a volte possono anche essere reperiti facilmente in circuiteria “da recupero”: si possono trovare in telefoni fissi, stampanti, fotocopiatrici, apparecchiature industriali, segreterie telefoniche ecc., Il loro prezzo comunque è abbastanza contenuto (un classico display 16×2 verde costa circa 8 euro).
Anche se nella seconda parte di questa lezione potrà essere scaricato il codice sorgente necessario per potersi interfacciare in maniera semplice a questi dispositivi, è sempre bene capire la teoria che sta alla base del funzionamento, sia per poter scrivere una propria libreria sia semplicemente capirne il funzionamento di base per poter poi passare a cose più complicate come i display grafici (GLCD), che non hanno una rom caratteri e vanno pilotati pixel per pixel.
Indice dei contenuti
Funzionamento dei display basati su controller HD44780 o compatibile
Vediamo innanzitutto come si presenta esternamente un classico display lcd 16×2:
Partiamo innanzitutto col dire che non tutti i display presentano la piedinatura disposta in questo modo (anche se questa è la più comune): alcuni hanno due file da 8 contatti disposte sulla sinistra del display, altri anzichè 16 pin ne hanno 17 (questo capita nei display da 40 caratteri per 4 linee, che si comportano come se fossero due singoli display da 40 caratteri per 2 linee messi uno sull’altro, continua a leggere per maggiori informazioni). La raccomandazione quindi è sempre la stessa: scaricate il datasheet del display che avete sottomano per evitare di compiere errori fatali che possono portare al guasto del display (il datasheet del controller lo potete scaricare in fondo all’articolo, ma il datasheet del display, per sapere qual’è la piedinatura esatta e altro, dovete trovarlo voi sul sito del produttore del vostro display).
Come dicevo prima, la piedinatura sopra esposta è la più comune: 16 pin disposti in fila (la numerazione da 1 a 16 è generalmente riportata anche sulla scheda del display).
Di questi 16 pin, 14 sono per il funzionamento del display e i rimanenti 2 servono per la retroilluminazione (che avviene mediante una matrice di led). Generalmente i due pin destinati alla retroilluminazione sono gli ultimi 2: il 15 è collegato all’anodo, e richiede 4,2V, e il 16 è il catodo, e quindi va a massa: potete controllare con un tester se il vostro display segue questa regola: basterà controllare la continuità tra il pin 15 e il terminale A: sul lato del display sono difatti presenti due piattine saldate alla scheda, su cui è fissata internamente la matrice di led.
Spesso questo non è necessario in quanto i display hanno l’indicazione stampata sulla scheda che fa capire quali sono i terminali per la retroilluminazione
Quindi: fate attenzione alla piedinatura: su alcuni display i pin di retroilluminazione si trovano in posizione 1 e 2 (per cui il pin 1 della piedinatura qui esposta, si trova ad essere il pin 3 su questi display e così via). Un esempio è questo LCD:
Se osservate attentamente lo strip di contatti, il pin contrassegnato con 1 è in realtà il terzo, i primi due sono invece contrassegnati rispettivamente con LED+ e L-.
Su altri ancora i pin della retroilluminazione potrebbero non esserci affatto: o perchè la retroilluminazione non è presente o perchè dobbiamo fornirla sui due terminali A e K presenti affianco al display.
Riporto qui la piedinatura “classica”, riferita al disegno sopra esposto:
Pin | Denominazione | Descrizione |
---|---|---|
1 | Vss o Gnd | Massa |
2 | Vcc | +5V |
3 | Vo | Regolazione contrasto |
4 | RS | Register Select (selezione dati/istruzioni) |
5 | R/W | Read/Write |
6 | E | Enable (Abilitazione) |
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) |
Passiamo alla descrizione dei pin, tralasciando il 15 e il 16 di cui abbiamo già parlato:
1 – Gnd : tale pin va posto a massa.
2 – Vcc : tale pin va posto a +5V stabilizzati. Bisogna stare attenti a non invertire la polarità: il display si danneggerebbe in maniera irreparabile.
3 – V0 : regolazione contrasto, su tale pin deve giungere un segnale compreso tra 0 e 5 Volt per regolare il contrasto: ovvero per rendere più o meno scuri i pixel, in genere la regolazione del contrasto la si esegue mediante un piccolo trimmer da 10 / 20KΩ collegato nel modo seguente:
In molti trascurano la regolazione del contrasto e si lamentano che sul display non viene visualizzato nulla: collegate sempre il trimmer nel modo qui esposto, e, se non viene visualizzato nulla sul display, girate il cursore: vedete che in una posizione estrema il display appare completamente vuoto, nella posizione estrema opposta tutti i “quadratini” appaiono neri, dovete scegliere una posizione intermedia. Molti a volte collegano una resistenza fissa al posto del trimmer una volta appurato qual’è il valore di tensione giusto da fornire per ottenere una buona lettura.
4 – RS : Register Select. Questo pin serve per indicare al display che tipo di informazione stiamo inviando sulla linea dati: se RS viene posto a 1 (livello logico alto) vuol dire che, tramite la linea dati, stiamo inviando un carattere da visualizzare sul display, se invece poniamo RS a livello logico basso, vuol dire che il dato che stiamo inviando è un comando da eseguire (es.: cancellazione display, seleziona una riga in cui scrivere ecc.)
5 – R/W : Read/Write. Se posto a 0, vogliamo scrivere un dato, se posto a 1 vogliamo leggere un dato (il display può difatti funzionare in modalità lettura/scrittura: normalmente viene sempre utilizzato in modalità scrittura, ma se vogliamo realizzare effetti particolari o sfruttare la memoria dell’LCD, allora è necessario utilizzarlo anche in lettura).
6 – E : Enable. E’ in pratica il pin sul quale viene inviato il segnale di sincronismo: quando viene posto a 1, il controller esegue la lettura del dato sulla linea dati, lo interpreta e quindi scrive sul display (o esegue il comando): quando dovremo inviare un carattere da visualizzare, dovremo prima predisporre opportunamente la linea dati, quindi porteremo il pin E a livello logico alto, in maniera tale che il controller esegua la lettura del dato, dopodichè riporteremo E a livello logico basso.
Ricordate quello che ho detto sopra? Che alcuni display hanno un pin in più perchè si comportano come due display affiancati? In questi display sono infatti presenti due pin Enable: uno per il primo display e uno per il secondo, per cui quando inviamo un carattere, per fare in modo da utilizzare l’intero display dovremo abilitare l’uno o l’altro pin E per fare in modo che i caratteri appaiano nella posizione corretta.
7 ÷ 14 – D0 ÷ D7 : Linea dati. Sulla linea dati (8 bit) vengono inviati i comandi da eseguire o il codice del carattere da visualizzare (oppure servono a ricevere i dati quando il display viene utilizzato anche in lettura). Questi display, fortunatamente, possono essere utilizzati anche in modalità 4 bit: ovvero utilizzeremo soltanto le linee dati D4,D5,D6 e D7 e gli 8 bit che identificano il carattere (continua a leggere) li invieremo in 2 gruppi da 4 (nibble): prima i 4 bit di ordine superiore (7-4) e quindi i 4 bit di ordine inferiore (3-0).
La modalità a 4 bit è vantaggiosa perchè ci permette di risparmiare preziosi pin sul microcontrollore che gestirà il display, ma per contro dovranno essere scritte delle routine più complicate per poterlo gestire, soprattutto in lettura.
Funzionamento del display e struttura interna
Cercherò di spiegare in maniera molto semplificata il funzionamento del controller, che è alla base per capire perfettamente come interfacciarsi. Per forza di cose, alcuni argomenti risulteranno complicati a chi è alle prime armi, ho cercato pertanto di semplificare il più possibile sperando di non aver tralasciato nulla e di non aver commesso errori.
Il controller di questi display possiede due banchi di memoria: una CGROM (Character Generator Read Only Memory) che contiene in pratica i “font” utilizzati per i caratteri e una DDRAM (Display Data Random Access Memory) che ha il compito di memorizzare “cosa” va scritto sul display. Quando invieremo dei dati (codici dei caratteri) sulla linea dati, questi saranno memorizzati nella DDRAM, un contatore si occuperà di scrivere nella DDRAM i caratteri uno dopo l’altro. La DDRAM ha una capacità massima di 80 caratteri (ecco perchè i display molto grandi: 40×4 hanno due pin di abilitazione E: vi sono due banchi di DDRAM, ai quali bisogna accedere separatamente).
I più attenti faranno un’acuta osservazione: su un display 16×2 abbiamo in realtà bisogno unicamente di uno spazio di massimo 32 caratteri, rimarrà nella DDRAM quindi uno spazio vuoto di 48 caratteri. E’ così… Difatti la capacità massima dei display “normali” è di 20 caratteri x 4 righe (quelli da 40×4 come detto prima hanno due banchi e sono quindi pure più complicati da gestire). Nei display che quindi non sfruttano tutta la DDRAM a disposizione, le locazioni rimaste vuote possono anche essere utilizzate per altri scopi: possiamo scriverci all’interno e utilizzarle quindi come se fossero una normale memoria ram (lo è a tutti gli effetti). Ovviamente per poter prelevare poi il dato è necessario utilizzare il display anche in lettura. Quando si sfruttano le locazioni di ram inutilizzate del display, si scrive sempre in posizioni che non sono visibili sullo schermo.
Ogni posizione (carattere) sul display è quindi mappato da una locazione nella DDRAM. Nei display 16×2, ad esempio, la prima riga è mappata dalle posizioni di memoria 0x00 ÷ 0x0F (0÷15 in decimale), mentre la seconda riga è mappata dalle posizioni ox40 ÷ 0x4F (64 ÷ 79 in decimale), per cui potete capire come scrivere, ad esempio, nella locazione 16 (decimale) non produce nulla sullo schermo. Le librerie utilizzate per interfacciarsi con i display, difatti, dovranno tenere conto di questa cosa: che le righe del display successive non sono in realtà mappate in maniera contigua nella DDRAM.
La CGROM, abbiamo detto, contiene i font dei caratteri, questi font sono diversi a seconda della sigla presente sul controller (fate riferimento al datasheet del controller del display in vostro possesso), ad esempio per il controller Hitachi HD44780, la presenza di “A00” nella sigla del controller, indica che siamo in presenza di una rom che include anche gli ideogrammi giapponesi kanji (questo è il tipo di controller maggiormente diffuso, in quanto è in Giappone che tale controller è stato inventato): questo tipo di rom presenta alcune locazioni di memoria vuote e programmabili (le prime 8): ciò significa che (tramite opportuna programmazione esposta più in basso e realizzata in pratica nella terza parte di questa lezione n°6) possiamo creare noi nuovi caratteri da poter visualizzare.
La presenza di “A02” nella sigla del controller, invece, indica che ci troviamo in presenza di una rom “europea” (che però non possiamo “customizzare”), la quale contiene anche i caratteri dell’alfabeto cirillico più altri simboli.
I Controller di tipo HD44780 presentano generalmente anche una lettera dopo la sigla che indica la tensione minima di funzionamento (su alcuni controller la lettera è invece stampata in altra posizione anzichè dietro la sigla). Gli HD44780S possono funzionare unicamente a 5V e sono controller di tipo più vecchio, gli HD44780U sono i più diffusi e hanno un range di tensione che va da 2.7 a 5V, quelli con la sigla U, inoltre, hanno un set di caratteri più esteso rispetto a quelli con la sigla S. La sigla tipica del controller sarà quindi, ad esempio, HD44780UA00 (oppure HD44780A00 possono inoltre seguire altre 2 lettere che indicano il formato del chip). La Hitachi produce, per le grosse aziende, anche delle ROM “custom”, contenenti font definiti dal cliente, questi controller hanno una sigla del tipo HD44780UBxx.
Guardiamo sul datasheet del controller la tabella dei font presenti sulla CGROM del HD44780UA00 (riporto solo questa qui perchè è la più diffusa):
Il funzionamento è molto semplice: quando vorremo, ad esempio, visualizzare la lettera A, invieremo sulla linea dati il valore binario 0100 0001 (si incrocia la colonna con la riga).
Come vedete, i caratteri che hanno il codice dal n°32 (carattere spazio: 0010 0000 in binario) al n° 125 (parentesi graffa aperta a sinistra, 0111 1101) rispecchiano i codici ascii ( – a parte il simbolo dello Yen, il cui valore numerico ascii corrisponde al nostro backslash \ – vedi sezione risorse, “Tabella codici ASCII estesa): per cui potete capire come è semplice potersi interfacciare con tale controller. Per poter difatti visualizzare la lettera A, nel programma che andremo a scrivere, potremo inviare la lettera A direttamente come carattere (“A”), o come codice ascii nel formato numerico che preferiamo (decimale : 65, esadecimale :0x41 o binario: 0b01000001). Questo appunto ci facilita nella scrittura di stringhe: possiamo scrivere la stringa intera utilizzando le lettere sulla tastiera, dal momento che i codici ascii combaciano con i codici dei font della CGROM del display. Dovremo avere la tabella sottomano soltanto per visualizzare i caratteri speciali (es.: simbolo del grado, lettere greche ecc): per scrivere ad esempio una temperatura, non potremo inviare la stringa “23.4°” perchè verrebbe visualizzato sul display “23.4-” in quanto il nostro simbolo di grado ha codice ascii 176 (10110000) che però sulla tabella dei font del display corrisponde al trattino: in questo caso possiamo scrivere “23.4” normalmente, seguito dal codice 1101 1111 (che corrisponde al simbolo del grado nella tabella dei font del display). Vedremo poi col picmicro come fare nella seconda parte di questa lezione.
Dalla tabella si evince, inoltre, che vi sono alcuni caratteri (la maggior parte) che hanno una dimensione minore (font 5×8, ovvero costituiti da 8 righe di 5 pixel ciascuna) e altri (gli ultimi 32) che sono di dimensioni maggiori (5×10): questi ultimi 32 font, in realtà, vengono sempre rappresentati “tagliati” (ovvero mancanti delle ultime due righe di pixel) sul display.
In effetti ciò potrebbe non verificarsi con altri display, aventi più pixel e impostando la modalità font 5×10 (continua a leggere), purtroppo sui display che ho provato personalmente, ciò non si verifica mai, per cui non terrò conto della modalità font 5×10 per mancanza di sperimentazione personale.
Anche se il “quadratino” per disegnare il font è costituito da una griglia di 5×8 pixel, in realtà i font contenuti nella rom occupano uno spazio di 5×7 in quanto la riga in basso viene sempre lasciata vuota per far posto all’eventuale cursore (ma nulla ci vieta di utilizzare comunque questa riga nel caso vogliamo definire i caratteri personalizzati).
Come vedete alcune posizioni sono vuote: non vi sono caratteri in quelle locazioni. Le prime 8 locazioni di memoria, come dicevo prima, possono anche essere scritte: abbiamo a disposizione 8 locazioni in cui “disegnare” caratteri in formato 5×8, la metodica per disegnare nuovi caratteri e memorizzarli nella CGROM sarà esposta nella terza parte di questa lezione.
Il Controller dispone di 2 registri ad 8 bit: l’IR (Instruction Registrer) e il DR (Data Register). L’IR è a sola scrittura e memorizza esclusivamente i comandi (es.: pulizia display) e le informazioni riguardanti l’indirizzamento della DDRAM e della CGROM. Il DR, invece, è un registro di transito e memorizza le istruzioni che devono essere scritte nella DDRAM o nella CGROM oppure il dato che deve essere letto dalla DDRAM o dalla CGROM. Quando difatti poniamo il pin RS (Register Select) a livello logico alto, il registro coinvolto nella comunicazione con la linea dati sarà DR (carattere da visualizzare), per contro quando RS=0 il registro coinvolto sarà IR (comando da eseguire).
Quando il display viene utilizzato anche in modalità di lettura, sulla linea dati abbiamo che i 6 bit meno significativi (D0 – D6) ci forniranno il valore del contatore (la posizione attuale del cursore: AC – Address Counter), mentre il bit più significativo (D7) rappresenta il Busy Flag: quando il controller è occupato nelle sue operazioni e quindi non è disponibile, tale bit si trova a livello logico alto, quando il controller è libero ed è quindi nuovamente disponibile per ricevere dati, tale pin si porta a livello logico basso: è utile disporre di queste funzioni quando si vuole utilizzare il display in modalità avanzata.
Invio di Comandi all’LCD
Vediamo l’elenco dei comandi che si possono impartire al display (fate comunque riferimento al datasheet). Viene indicato, per ogni comando, come va impostata la linea dati (è implicito che per inviare un comando, il pin RS deve essere posto a zero, ma nella tabella lo riporto ugualmente, così come anche fa il datasheet):
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 | … | 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 | … | … | 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 | … | … | 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 |
Dove è riportato “…” vuol dire che lo stato di quel bit è indifferente: possiamo lasciarlo a zero ad uno senza problemi, il significato dei bit rappresentati con le lettere è il seguente:
Simbolo del bit | se lo imposto a 0 | se lo imposto a 1 |
---|---|---|
I/D | La posizione all’interno della DDRAM decrementa | La posizione incrementa |
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 |
L’elenco completo dei comandi è contenuto nel datasheet del controller, scaricabile in fondo all’articolo. Anche se abbiamo detto che lavoreremo in modalità 4 bit, non spaventatevi se nella tabella sono elencati pure i bit da 7 a 4: come detto in precedenza l’intero byte verrà impostato con due invii successivi da un nibble (4 bit) ciascuno.
L’impostazione Set DDRAM Address è molto importante in quanto ci permette di poter posizionare il cursore (e quindi iniziare la scrittura) nel punto in cui vogliamo. Per quanto detto prima, le righe successive di un display generalmente non sono mappate da posizioni di memoria contigue, riassumo per tanto, nella tabella seguente, i comandi da inviare per posizionarsi nella prima posizione della riga voluta per i vari tipi di display:
Tipo display (righe X n° caratteri) |
Riga 1 | Riga 2 | Riga 3 | Riga 4 |
---|---|---|---|---|
1×8 | 0x80 | — | — | — |
2×8 | 0x80 | 0xC0 | — | — |
1×16 | 0x80 | — | — | — |
2×16 | 0x80 | 0xC0 | — | — |
2×20 | 0x80 | 0xC0 | — | — |
4×16 | 0x80 | 0xC0 | 0x90 | 0xD0 |
4×20 | 0x80 | 0xC0 | 0x94 | 0xD4 |
L’impostazione dell’Entry Mode Set (Modalità immisione: ovvero spostamento del cursore o del testo) in realtà è abbastanza complicata a spiegarsi, per capire bene cosa avviene impostando i bit per questa modalità, potete vedere le 4 gif animate seguenti e per le quali mando ancora un sincero grazie di cuore a Dincer Aydin per la sua disponibilità e per avermi concesso di utilizzare le sue immagini.
Sul sito personale di Dincer Aydin : www.dinceraydin.com potrete inoltre trovare tante altre informazioni utili sul funzionamento dei display LCD sia alfanumerici che grafici. In particolare nella pagina www.dinceraydin.com/lcd ci sono altre informazioni sui display alfanumerici intelligenti di cui stiamo trattando in questo articolo.
In queste immagini di esempio si presuppone di aver settato il cursore (reso inoltre visibile mediante il bit C come esposto nella tabella dei comandi) nella posizione 8 della prima riga
Entry Mode = 0x04 (ovvero I/D=0 e S=0) Stringa inviata all’LCD: DereliIl cursore si sposta verso sinistra (la scritta si sviluppa alla rovescia) e il testo è fermo(I/D=0 la posizione decrementa, S=0 il testo rimane fermo) |
|
Entry Mode = 0x05 (I/D=0 e S=1) Stringa inviata all’LCD: HakanIl cursore rimane fermo e si sposta invece la scitta (la quale si sviluppa sempre alla rovescia)(I/D=0 la posizione decrementa, S=1 il testo si sposta) |
|
Entry Mode = 0x06 (I/D=1 e S=0) Stringa inviata all’LCD: DereliIl cursore si sposta verso destra (la scritta si sviluppa “dritta”) e il testo rimane fermo. (I/D=1 la posizione incrementa, S=0 il testo è fermo)Questa è l’impostazione utilizzata nella maggior parte dei casi) |
|
Entry Mode = 0x07 (I/D=1 e S=1) Stringa inviata all’LCD: HakanIl cursore rimane fermo e si sposta invece la scritta (la quale si sviluppa “dritta”)(I/D=1 la posizione incrementa, S=1 il testo si sposta) |
Ovviamente, programmando, può non verificarsi l’effetto “macchina da scrivere” dal momento che l’invio dei dati è solitamente molto veloce, per cui visualizzeremo unicamente la scritta completa. Per ottenere questo effetto si può inserire una pausa tra l’invio di un carattere e l’altro. Generalmente questo non viene mai fatto in quanto tali effetti non hanno un utilizzo pratico e complicano di molto le cose: spesso è complicato stabilire la posizione di partenza del cursore per far eseguire la scritta al contrario (che poi a cosa servirà mai scrivere al contrario…)
Inizializzazione del display
Il display deve essere inizializzato prima di poter essere utilizzato, in realtà l’inizializzazione di base viene effettuata dalla circuiteria interna del display, ma ciò non sempre soddisfa i nostri requisiti, per cui l’avvio del display viene sempre effettuato via software impartendo al display la giusta sequenza di istruzioni come indicato dal datasheet:
Dopo aver dato tensione al display, bisogna aspettare per almeno 15 millisecondi (40 se si utilizza l’alimentazione a 2.7V).
Si pone quindi la linea RS a livello logico basso per dire al controller del display che intendiamo inviare dei comandi.
Si pongono a livello logico alto D4 e D5, e a livello logico basso D6 e D7, si da quindi il consenso portando il pin E a livello logico alto e quindi riportandolo subito a livello logico basso (questa operazione: portare il pin E prima a 1 e poi subito a 0, va fatta ogni volta che inviamo un dato sulla linea dati per avviare la sincronizzazione, per cui da ora in poi non lo ricorderò più).
Si aspettano almeno 4.1ms, si riesegue l’operazione precedente (D5 e D4 a 1 e D7 e D6 a 0) – in realtà se eseguiamo questa operazione col picmicro (o con altro o con la parallela) non c’è bisogno di reimpostare questi pin: già si trovano nello stato logico corretto dall’operazione precedente, quindi basta soltanto inviare il segnale di enable.
Si aspettano almeno 100 microsecondi, si esegue di nuovo l’operazione precedente.
Si imposta quindi D5 a 1 e D4 a zero per indicare che vogliamo utilizzare l’interfaccia a 4 bit.
Da questo momento in poi dovremo inviare sempre 8 bit ma suddivisi in due blocchi da 4 (come vedete lo schema illustrato dal datasheet, da questo punto in poi si sdoppia su due righe per ogni blocco di comandi da inviare).
Impostiamo quindi la modalità di funzionamento, rimanendo D5 e D4 come erano in precedenza e impostando i bit N (numero di righe del display) e F (grandezza font). Quindi volendo, ad esempio (impostazione classica) utilizzare interfaccia a 4 bit, 2 righe, e font 5×8, invieremo sulla linea dati il valore binario 0010 1000 (gli ultimi 2 bit li possiamo mettere a qualsiasi valore), ovviamente lavorando in modalità 4 bit, dovremo prima inviare 0010, dare l’enable, inviare quindi 1000 e ridare l’enable.
Da questo momento in poi, il numero di linee e il font non potranno più essere cambiati fino a nuova inizializzazione.
Spegniamo quindi il display (0000 1000)
Effettuiamo la “pulizia” del display (0000 0000)
Definiamo la modalità di immissione (Entry Mode) , ponendo a 1 D2 e quindi scegliendo il valore di D1 e D0: ad esempio inviamo il dato 0000 0110 (movimento normale del cursore – da sinistra verso destra).
A questo punto l’inizializzazione è finita, per cui possiamo riaccendere il display, ed eventualmente visualizzare anche il cursore.
Scrittura di caratteri sul display
Dopo aver inizializzato il display, è quindi possibile inviare i caratteri per la scrittura: basta impostare la linea dati sul codice carattere che ci interessa, inviare il segnale di enable, e quindi andare avanti un carattere alla volta: sarà il controller a posizionare i caratteri uno dopo l’altro.
Per scrivere su l’una o sull’altra riga, dobbiamo inviare un comando che scrive nella DDRAM l’indirizzo di partenza da cui cominciare a scrivere, come indicato nella tabella dei comandi. Per scrivere, ad esempio all’inizio della prima riga, dovremo impostare ad 1 D7 (ponendo RS a zero), così indichiamo di voler scrivere nella DDRAM, i rimanenti 7 bit della linea dati andranno impostati tutti a zero, invieremo quindi (con RS=0) il dato: 1000 0000 (oppure 0x80 in esadecimale), così in pratica impostiamo la posizione di scrittura alla prima posizione nella prima riga, per scrivere sulla seconda riga, dovremo impostare ad 1 anche D6, e scrivere quindi la posizione nei rimanenti bit (1100 0000 => oppure 0xC0 – scrive all’inizio della seconda riga). Il comando corretto da inviare per incominciare la scrittura nella posizione che desideriamo, per ogni tipo di display, è comunque illustrato nella tabella che abbiamo visto più in alto.
Nella seconda parte della lezione potrà essere scaricato il codice sorgente che effettua per noi tutte queste operazioni.
Datasheet Controllers
- Datasheet Display Controller Sunplus SPLC780D (1342 download)
- Datasheet Display Controller Hitachi HD66702 (1287 download)
- Datasheet Display Controller Oki MSM6222 (1103 download)
- Datasheet Display Controller Epson SED1278 (1362 download)
- Datasheet Display Controller Sanyo LC7985 (1214 download)
- Datasheet Display Controller Samsung KS0070 (1176 download)
- Datasheet Display Controller Samsung KS0066 (1335 download)
- Datasheet Display Controller Hitachi HD44780 (2587 download)
Datasheet Display
- Datasheet Display Seiko M4024 - Istruzioni operative (267 download)
- Datasheet Display Seiko M4024 (259 download)
- Datasheet Display Xiamen Ocular GDM1602 (16x2) (1401 download)
Application Notes e altri appunti
- Pilotare un display LCD dalla porta parallela (AN - Hantronix) (413 download)
- Come pilotare i display LCD intelligenti (Articolo in inglese su una rivista di elettronica del 1997) (469 download)
- Interfacciare un PICMicro con un display LCD (AN587 - Microchip) (661 download)