Corso programmazione microcontrollori PIC® in C (aggiornamento MPLAB X) – Pilotare display alfanumerici compatibili Hitachi HD44780
Questa lezione è un aggiornamento per MPLAB X IDE e compilatore XC delle 3 vecchie lezioni sugli LCD. Per tutta la parte di teoria potete fare riferimento alle lezioni del vecchio corso di programmazione microcontrollori PIC® in C in cui parlo dei display alfanumerici con controller Hitachi HD44780 o compatibile.
Le 3 vecchie lezioni a cui faccio riferimento sono le seguenti:
- Lezione 7 (parte 1) – Tutto quello che c’è da sapere sui display alfanumerici intelligenti
- Lezione 7 (parte 2) – Hello World
- Lezione 7 (parte 3) – Caratteri personalizzati
La libreria inclusa in questo download prevede l’utilizzo di un I/O (RW) in più rispetto a quella vecchia dal momento che abbiamo inserito un’altra linea per il controllo di stato come dicemmo in un vecchio articolo. Ricordate, difatti, che in molti dovevano cambiare i ritardi nella libreria per poter utilizzare il proprio display: questo è dovuto ai tempi di latenza di alcuni controller che non sono perfettamente uguali allo standard de-facto stabilito dal controller della Hitachi. Eseguendo il controllo di stato tutti questi problemi di temporizzazione non si presentano.
Lo schema che andremo ad utilizzare è il seguente (se state utilizzando la scheda di sviluppo Freedom II, sappiate che è lo stesso schema):
Ricordo che stiamo utilizzando un PIC16F887 con un oscillatore esterno da 20MHz. Se usate il PIC16F18877 potete anche utilizzare l’oscillatore interno cambiando la word di configurazione (non appena mi arriva includo gli esempi anche per questo).
Dallo schema vedete che utilizzeremo 7 oppure 8 I/O per controllare l’LCD: 3 per le linee di controllo (Enable, RW e RS), 4 per le linee dati (pilotiamo il display in modalità 4 bit) e uno, facoltativo, per gestire la retroilluminazione. Le 4 linee dati non utilizzate vanno lasciate flottanti (non collegate a masse come sul vecchio schema). La scelta dell’I/O per la retroilluminazione fatta da Mauro Laurenti in realtà non è casuale ma viene fuori dal fatto che RC1 è anche l’uscita del modulo CCP2, per cui può inviare un segnale PWM permettendo di modulare l’intensità luminosa. Ad ogni modo potete anche mettere la retroilluminazione fissa con gli opportuni accorgimenti (dovrete mettere una resistenza da 220/330Ω) e risparmiare quindi un I/O. La libreria ha una funzione per controllare anche il pin per la retroilluminazione se non l’avete disattivata.
Nel file header della libreria (hd44780sz.h) dovrete fare gli opportuni aggiustamenti per il modello di display in vostro possesso, in particolare dovete impostare il numero di righe e colonne:
61 62 63 | // display size #define LCD_ROWS 2 #define LCD_COLS 16 |
Se avete la (s)fortuna di avere un raro display che ha il font della misura 5×10 anzichè 5×8, dovete decommentare la riga 67:
65 66 67 | // uncomment this if your lcd uses font 5x10 // (note: majority of lcds uses 5x8 font, so leave this commented) //#define FONT5x10 |
Infine, se non volete utilizzare il pin per le retroillumninazione (e quindi avete messo la retroilluminazione fissa oppure il vostro display non ce l’ha), commentate le righe 71,72 e 73:
69 70 71 72 73 | // uncomment if lcd backlight pin is I/O-driven // comment following 3 statements if lcd backlight is hardwired #define LCD_BACKLIGHT #define LCD_BL PORTCbits.RC1 #define LCD_TRIS_BL TRISCbits.TRISC1 |
Chiaramente se avete scelto di collegare il display ad altre porte, fate anche i cambiamenti per i registri PORT e TRIS con la raccomandazione che le 4 linee dati stiano sullo stesso banco e così anche le 3 linee di controllo (in realtà questo non è sempre necessario ma qualcuno su vecchi picmicro ha incontrato problemi).
La demo fa utilizzo di un display 16×2 per cui se usate un display diverso le scritte potrebbero trovarsi sfalsate. Il progetto è semplice: illustra unicamente come utilizzare le funzioni di libreria per stampare stringhe, caratteri, generare caratteri personalizzati, numeri interi con o senza segno e ho aggiunto la possibilità di stampare numeri float, su cui però devo spendere una parola.
In un bell’articolo ho illustrato come avviene la codifica dei numeri float e ho detto che sui microcontrollori (sulla stragrande maggioranza di essi) non c’è una FPU (l’unità dedicata alla gestione dei numeri in virgola mobile) per cui tutte le operazioni sulle variabili float vengono eseguite in emulazione, il che comporta un dispendio esagerato di memoria flash, memoria dati e velocità di elaborazione.
In molti progetti abbiamo sempre operato sulle variabili utilizzando aritmetica in virgola fissa piuttosto che mobile: nel momento in cui sappiamo che qualche operazione può restituirci un decimale (esempio: la lettura di un valore di temperatura da un sensore), moltiplichiamo i valori ottenuti per una potenza di 10 in modo da eliminare i decimali ottenendo un numero intero, si fanno quindi tutte le operazioni e alla fine si divide per la stessa potenza di 10 stampando separatamente la parte intera e il resto della divisione. In linea di massima io consiglio di utilizzare sempre questo sistema perchè fa risparmiare tantissima memoria di cui, forse, non sempre abbiamo idea.
Proprio perchè non ne abbiamo idea, ho incluso nella libreria una funzione per la stampa delle variabili float utilizzando semplicemente una funzione standard del C, la sprintf, che permette di convertire i numeri in stringhe fornendo uno specificatore di formato. Ho compilato la demo, presente in questo articolo, sia facendo la stampa di un numero float, che commentando quella parte (se una funzione non viene utilizzata, MPLAB X IDE tralascia tutte le funzioni collegate). Ecco quello che succede:
A sinistra c’è la demo senza la parte di stampa delle variabili float, a destra c’è la stampa delle variabili float. Direi che la differenza è mostruosa e non devo aggiungere commenti. La funzione per la stampa delle variabili float l’ho lasciata inclusa nella libreria perchè potrebbe tornare utile in molti casi ma il consiglio, ripeto, è quello di utilizzarla soltanto se strettamente necessario. Ad ogni modo se nel vostro programma non la utilizzate, non c’è il dispendio di memoria.
Segnalo soltanto che a causa di questa funzione, il compilatore rilascia una sfilza di Warning nel modulo doprnt.c (che viene richiamato dalla libreria stdio a causa dell’utilizzo di sprintf):
doprnt.c:414: warning: (373) implicit signed to unsigned conversion |
Non riesco a disabilitare questo warning nemmeno utilizzando le direttive #pragma warning disable n e sinceramente la cosa mi lascia un po’ perplesso al punto di aver pensato a qualche bug delle librerie, ci ho sbattuto un po’ su ma non ne sono venuto a capo. Ad ogni modo questo warning non causa nessun problema e, se volete, potete eliminare l’inclusione di stdio presente nel file header della libreria lcd (hd44780sz.h) e quindi la funzione LCD_Writeflo in hd447802z.c.
Le funzioni incluse in libreria sono:
LCD_Init(void); // da richiamare una volta sola all'inizio per inizializzare il display LCD_Goto(int8_t row, int8_t col); // per spostare il cursore in posizione riga (row), colonna (col) - a base 1 LCD_Clear(void); // ripulisce il display. Da richiamare anche dopo aver definito un carattere personalizzato LCD_Putchar(char c); // immette un singolo carattere fornendo il codice numerico ascii (o il carattere da tastiera ma messo tra singoli apici '') LCD_Writeuns(uint16_t c); // scrive un numero senza segno (massimo 16 bit) LCD_Writesig(int16_t c); // scrive un numero con segno (massimo 16 bit) LCD_Writeflo(float c,uint8_t p); // scrive un numero float, il secondo parametro è il numero di decimali (max 4) LCD_Writestr(const char *s); // scrive una stringa di lunghezza arbitraria LCD_Customchar(int8_t pos, const char *b); // definisce un carattere custom (vedi vecchia lezione 7 parte 3) LCD_Backlight(bool backlight); // accende (1) / spegne (0) la retroilluminazione |
Vi lascio con il download dell’esempio che include la libreria. Se potete, cliccate sul pulsante “supportaci” nella barra di navigazione destra o sul bannerino animato in basso che portano ad una pagina in cui potete leggere gli svariati sistemi con cui potete supportarci.
Esempio pilotaggio LCD HD44780 (MPLAB X) (983 download)