PIC e Linux: 4) La gestione del display LCD

Una delle cose che possono risultare utili sin da subito è la possibilità di visualizzare “qualcosa” con i PIC.

Ad esempio ci piacerebbe poter visualizzare il valroe di una temperatura, o lo stato di alcune porte, e tutto ciò con qualcosa di meglio che non dei semplici LED o dei display a 7 segmenti.

Per tutto questo si rivelano molto utili i display alfanumerici LCD, in quanto sono:

  • economici
  • semplici da usare
  • ricchi di possibili applicazioni

I display LCD alfanumericivengono venduti in diverse forme, ma tutti consentono di visualizzare un certo numero di caratteri (ad esempio 20 caratteri) su una o più righe (in genere si trovano display da 1 riga, 2righe o 4 righe).

Innanzitutto, non volendo ripetere quanto già di buono esiste in rete, vi segnalo alcuni ottimi articoli su cui approfondire la conoscenza generale dei display alfanumerici LCD:

  1. www.settorezero.com: lezione del corso di programmazione per i PIC micro
  2. www.picexperience.it: appunti sui display LCD
  3. www.laurtec.it: C18StepbyStep, Capitolo X: Utilizziamo un display alfanumerico LCD

Ciascuno di questi siti consente di imparare bene ad utilizzare un display alfanumerico LCD. In questa sede io mi occuperò di fornire un esempio pratico funzioante con il nostro solito Linux e l’ormai abituale SDCC.

1) La connessione del display al PIC

I display che utilizzeremo in questo esempio sono quelli della famiglia HD44780, e questi hanno tutti 16 pin di collegamento:

Pjn Nome in codice A cosa serve:
1 Vss Collegamento alla massa (GND)
2 Vdd Serve per fornire i 5V di alimentazione al Display. In genere viene collegato ad un piedino del PIC per poter accendere il diplay semplicemente mettendo a “1” il piedino
3 Vo Serve per regolare il contrasto del display, che in certi casi potrebbe essere poco visibile. In pratica dobbiamo fornire una tensione compresa fra 0 e 5V, regolabile con un trimmer o calcolare un partitore resistivo. Io, fortunatamente, fino ad oggi ho sempre trovato display LCD che non richiedevano nessun collegamento per questo piedino, anche se in alcuni casi le scritte apparivano piuttosto scure. Comunqeu per avere un risultato buono è meglio collegare questo piedino come indicato in questa imagine e poi regolarlo fino ad ottenere una visualizzaizone corretta
4 RS Registro “Select”, serve per indicare al Display se vogliamo inviargli dei DATI o dei COMANDI. Se vogliamo inviare dei dati (cioè vogliamo scrivere qualcosa) dobbiamo mettere un valore 1 (alto) su questo PIN, mentre se vogliamo inviare un comando (ad esempio, mandare a capo il cursore oppure cancellare tutto quello che è visualizzato sul display) dobbiamo dare un valore 0 (basso) a questo PIN
5 R/W Read o Write. In genere noi vogliamo utilizzare il display per scriverci qualcosa, quindi lo faremo funzionare sempre in modalità “Write” e pertanto metteremo a 0 (basso) questo PIN.
6 E Enable (Abilitazione): questo piedino viene messo alto per abilitare il funzionamento del display, è una specie di interruttore. Tuttavia ha anche un altro importante ruolo, serve, come vedremo più avanti, per inviare “impulsi di conferma”
7-14 DB0-DB7 Sui PIN dal 7 al 14 ci sono gli 8 bit del BUS dati, sul quale vengono fatti viaggiare sia i dati che i comandi. Si possono inviare i dati in due modi: o utilizzando tutti gli 8 bit, oppure mandando due “nibble” (metà byte) per volta. Anche se a prima vista potrebbe sembrare comodo mandare un byte intero utilizzando tutti e 8 i piedini, in realtà conviene utilizzare solo i piedini da 11 a 14, corrispondenti a DB4 – DB7. Ovviamente occorre impostare il display in modo che si prepari a ricevere due gruppi da 4 bit invece che un bye intero, e questo lo vedremo in seguito
15-16 Illuminazione Retroilluminazione, anodo e catodo, serve per poter accendere la luce di illuminazione del Display e renderlo visibile anche al buio. Perilluminare il display collegate il PIN 15 a + 5v e il PIN 16 a massa. ATTENZIONE: l’illuminazione assorbe più di 100mA, quindi collegatelo direttamente all’alimentazione e non ad un piedino del PIC altrimenti lo bruciate!

adesso vediamo come controllare il display,

2) Comandi disponibili: impostazioni generali

Per inviare un comando al display dobbiamo inviare un byte. Negli articoli che vi ho segnalato all’inizio sono indicati tutti i comandi che possiamo utilizzare, ad esempio in questa tabella, mentre io mi limiterò a spiegare i comandi principali, quelli di cui proprio non possiamo fare a meno:

0000 0001  ->  Pulizia Display

0010 AB00  ->  Imposto interfaccia a 4 bit, per rispoarmiare 4 linee del bus (0010) e imposto il numero di linee e la dimensione dei caratteri. Normalmente A=1 significa 2 o più righe, mentre F = 0 significa caratteri 5×8, e si tratta di impostazioni valide per la maggior parte dei casi, quindi  il comando da inviare sarà 0010 1000

0000 1111  -> Display acceso, cursore visibile e lampeggiante

0000 10xx  -> Display spento (non importa cosa mettete per ilcursore, tanto no si vedrebbe)

0000 1100  -> Display acceso e cursore invisibile

0000 0110   -> Spostamento del cursore da sinistra verso destra

3) Comandi disponibili: come scrivere nella posizione che vogliamo

I caratteri che noi scriviamo son conservati nella memoria del display. Ci sono tanti gruppi di locazioni quante sono le righe del display, ed ogni gruppo ha tante locazioni quanti sono i caratteri di ciascuna linea. Ad esempio, un display da due righe di 20 caratteri utilizzerà 40 locazioni di memoria, divise in due gruppi di 20.  Possiamo scrivere nella posizione che preferiamo, sapendo che, con l’impostazione 0000 0110, ogni volta che scriviamo un carattere, il display si posiziona già nella successiva locazione di memoria. Se però vogliamo cambiare riga, dobbiamo dire esplicitamente al display su quale indirizzo di memoria vogliamo posizionarci.

E’ molto utile conoscere le locazioni di memoria dove iniziano le righe. In genere per i display più comuni in commercio la prima riga inzia allalocazione 80h, mentre la seconda a C0h.

Quindi:

1000 0000 -> posiziona il cursore sul primo carattere della prima riga

1100 0000 -> posiziona il cursore sul primo carattere della seconda riga

4) Inizializzare il display

Una cosa particolarmente importante da sapere è che non basta acendere il disply e inviare i comandi. Prima occorre inviare una particolare sequenza di comandi che serve ad inizializzare il display. E’ molto importante che questa sequenza sia inviata con un certo intervallo di tempo ben definito, altrimenti non funziona.

5) Impulsi di sincronizzazione

Una ultima importante cosa da sapere è che dopo aver impostato sui piedini del pic i comandi da inviare occorre effettuare una particolare manovra per far sì che il display accetti il nuovo comando. Occorre dare quello che viene chiamato “un impulso di sincronizzazione”, e cioè :

  1. portare a 1 il PIN 6 (abilitazione)
  2. attendere circa 1 millisecondo
  3. portare a 0 il PIN 6

6) Un esempio

Vediamo adesso di mettere tutto insieme. Realizzeremo un semplice esempio costituito da una libreria di gestione del LCD e da un programma principale che ne fa uso.

6.1) La libreria lcd.h

Questa libreria è stata pensata per un utilizzo con la scheda Freedom-light di Mauro Laurenti (per accedere al sito occorre registrarsi, gratuitamente).

La libreria presenta le funzioni di base per l’uso di un display LCD:

void lcd_backlight_on() //accende la retroilluminazione del display
void lcd_backlight_off() //spegne la retroilluminaizone del display
int lcd_get_RW() //restituisce l'impostazione del piedino RW del display
int lcd_get_RS() //restituisce l'impostazione del piedino RS del display
void lcd_set_lettura() //imposta a 1 il piedino RW (modo lettura)
void lcd_set_scrittura() //imposta a 0 il piedino RW (modo scrittura)
void lcd_set_comandi() //imposta a 0 il piedino RS (modo comandi)
void lcd_set_ascii() //imposta a 1 il piedino RS (modo ASCII) 
void lcd_write_byte(unsigned char n) //scrive un byte sul display
void lcd_write( char * parola) //scrive una frase sul display
void lcd_clear() //pulisce il diplay e si posiziona sulla 1a riga
void lcd_riga1 () //si posiziona all'inizio della prima riga
void lcd_riga2 () //si posiziona all'inizio della seconda riga
void lcd_curs_on_blink_off () //accende il cursore, spegne il lampeggio
void lcd_curs_off_blink_off () //spegne cursore e lampeggio
void lcd_curs_on_blink_on () //accende cursore e lampeggio
void lcd_curs_off_blink_on () //spegne il cursore, accende il lampeggio
void lcd_curs_home () //porta il cursore a inizio display
void lcd_avvia() //inizializza il display

Le funzioni, presenti nella libreria lcd.h, contenuta insieme agli altri file in questo archivio compresso liberamente scaricabile (è un file .zip: scaricare e poi togliere l’estenzione .jpg), vengono utilizzate dopo essere state richiamate in modo molto semplice.

6.2) Il programma di test

Per testare la libreria abbiamo realizzato un programma di prova, anch’esso contenuto nel file allegato.

Il programma inizia con l’inclusione dell’header relativo al PIC 18F4550 e della libreria lcd.h. Viene anche inclusa la configurazione dei registri, che si trova nel file “registri.h”, ma che potrebbe benissimo essere semplicemente scritta nel programma, dopo gli “#include”.

A questo proposito va detta una cosa IMPORTANTISSIMA. Se state utilizzando il PicKit2 per programmare il microcontrollore, dovete disabilitare la programazione a basso voltaggio, inserendo la seguente direttiva di configurazione:

__code char __at __CONFIG4L CONFIG4L = _LVP_OFF_4L;

mentre se state utilizzando un programmatore che supporta la programazione a bassa tensione dovete isnerire la seguente direttiva di configurazione:

__code char __at __CONFIG4L CONFIG4L = _LVP_ON_4L;

Se non lo fate, anche se apparentemente riuscirete a programmare il microcontrollore, in realtà incontrerete tanti misteriosi e inspiegabili malfunzionamenti che vi faranno perdere ore….. specialmente per quanto riguarda l’uso della PORTB!!!!!

Dopo aver incluso i file, definiamo tre semplici funzioni, una per disporre di un ritardo, espresso in secondi, e altre due per generare delle pause che durano fino a quando l’utente preme il pulsate S2 oppure S3.

Le prime righe del nostro programa sono quindi le seguenti:

#include 
#include "registri.h"
#include "lcd.h"

//pausa il programma fino alla pressione del tasto S2
void pausaS2() {
  while (PORTBbits.RB4);
}

//pausa il programma fino alla pressione del tasto S3
void pausaS3() {
  while (PORTBbits.RB5);
}

//genera ritardo, all'incirca 'a' secondi con quarzo 20MHz
void ritardo(int a) {  
	long int i,j;
	for (i=0;i < a ;i++) for (j=0;j < 50000 ;j++);
}

Fatto ciò, non resta che scrivere il programma principale, che non fa altro che accendere il display e scrivere alcune cose, richiamando le funzioni di libreria:

void main() {
char parola[] = "Test lcd.h";
LATD=0;
TRISD = 0;
LATC=0;
TRISC = 0;
LATA=0;
TRISA = 0;
LATE=0;
TRISE = 0;
LATB = 0x00;
TRISB = 0xFF;

lcd_avvia();
lcd_clear();
lcd_display_on();
lcd_backlight_on();
lcd_write(parola);
lcd_riga2();
lcd_write("premi -> S2");
pausaS2();

lcd_clear();
lcd_riga1();
lcd_write("cursore off");
lcd_riga2();
lcd_write("blink off - (S3)");
lcd_curs_off_blink_off();
pausaS3();

lcd_clear();
lcd_riga1();
lcd_write("cursore ON");
lcd_riga2();
lcd_write("blink off - (S2)");
lcd_curs_on_blink_off();
pausaS2();

lcd_clear();
lcd_riga1();
lcd_write("cursore off");
lcd_riga2();
lcd_write("blink ON - (S3)");
lcd_curs_off_blink_on();
pausaS3();

lcd_clear();
lcd_riga1();
lcd_write("cursore ON");
lcd_riga2();
lcd_write("blink ON - (S2)");
lcd_curs_on_blink_on();
pausaS2();

lcd_clear();
lcd_riga1();
lcd_write("cursore a inizio");
lcd_riga2();
lcd_write("premi - S2");
lcd_curs_home();
pausaS2();

lcd_clear();
lcd_riga1();
lcd_write("Lampeggio lcd");
lcd_backlight_off();
ritardo(2);
lcd_backlight_on();
ritardo(2);
lcd_backlight_off();
ritardo(2);
lcd_backlight_on();
lcd_riga2();
lcd_write("premi -> S3");
pausaS3();

lcd_clear();
lcd_write(parola);
lcd_riga2();
lcd_write("W Linux (S2)");
pausaS2();
lcd_backlight_off();

}

Come vedete, l’utilizzo della libreria semplifica molto la gestione di un Display LCD. Lascio al lettore, come esercizio, la creazionedi altre funzioni di libreria che, volutamente, mancano. Ad esempio, la funzione

void lcd_gotoXY( int colonna, int riga )

che potrebbe essere utilizzata per posizionare il cursore su una colonna e una riga specificate

oppure le funzioni

void lcd_cur_sx()

e

void lcd_cur_dx

che spostano il cursore di una posizione a destra e una a sinistra

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...