Dopo aver visto tutta (o quasi) la teoria che c’è alla base del pilotaggio dei display LCD basati sul controller Hitachi HD44780 (o compatibile) eccoci qui pronti a scrivere qualche programmino di esempio da caricare sul nostro picmicro.
In questa lezione sfrutteremo una libreria per il pilotaggio degli LCD scritta dal sig. Andrea Bonzini e disponibile anche sul sito di Sergio Fiocco.
Tale libreria prevede il controllo dell’LCD in modalità 4 bit e in sola lettura (il pin RW, difatti, andrà collegato a massa e non sarà pilotabile via software). Ho apportato delle piccole modifiche a tale libreria in maniera da avere disponibili anche altre funzioni. L’elenco delle modifiche da me apportate è descritto nel file changelog.txt allegato alla libreria, ho inoltre incluso la libreria originale.
Se spulciate nella cartella “samples” dell’installazione Hitec-C, troverete una routine simile in “LCDemo”
Passiamo a vedere come montare il circuito.
Schema e montaggio del circuito
Anche se in apparenza può sembrare complicato, lo schema in realtà è abbastanza semplice, non vi impressionate:
A parte le porzioni di circuito che abbiamo già visto nelle precedenti lezioni, ci sono le seguenti novità:
- I 4 led: ogni led avrà la sua resistenza da 330Ohm in serie, il terminale lungo del led andrà verso il pic (con la resistenza in serie), il terminale corto verso massa. Il led contrassegnato come LED1 andrà collegato ad RB7 fino ad arrivare a LED4 collegato a RB4.
- I 3 pulsanti: sono contrassegnati sullo schema come BTNOK (collegato a RB2), BTNDOWN (collegato a RB1) e BTNUP (collegato a RB0). I 3 pin del picmicro ai quali sono collegati i pulsanti sono costantantemente alimentati ognuno da una propria resistenza di pullup da 1KOhm. Premendo il pulsante, il pin relativo viene a trovarsi a massa, quindi intercetteremo via software la pressione del pulsante verificando che il pin relativo sia a livello logico basso.
Se si abilitano le resistenze di pullup sulle porte B, non è necessario includere le resistenze da 1KOhm.
- Cicalino: collegato su RE1. Per questa prova è assolutamente necessario utilizzare un cicalino non autooscillante dal momento che genereremo un diverso tono per ogni funzione. La resistenza in serie al cicalino può anche essere omessa.
- Il display LCD. Controllate bene la piedinatura del display che avete in vostro possesso. Il terminale GND va a massa, il terminale Vcc va ai 5 volt positivi, il terminale V0 (contrasto) va collegato al cursore (pin centrale) di un trimmer da 10KOhm, le altre due estremità del trimmer vanno una ai 5 volt e l’altra a massa.
Il terminale dell’LCD contrassegnato come RS (Register Select) lo collegheremo sul pin 21 del 16F877 (RD2).
Il terminare dell’LCD E o EN (Enable) va al pin 22 (RD3)
I terminali da D4 a D7 vanno rispettivamente collegati ai pin da 27 a 30 (da RD4 a RD7)
Se vogliamo, possiamo collegare all’alimentazione i due pin del display destinati alla retroilluminazione.
I rimanenti pin del display vanno posti a massa.
Se utilizzate la scheda Freedom di Mauro Laurenti, è disponibile il connettore LCD, i quali pin portano già alle porte del picmicro qui definite.
La libreria per il pilotaggio dell’LCD
La libreria (lcd.c) è scaricabile in fondo all’articolo insieme ai programmi presentati in queste pagine, è caldamente raccomandata la lettura del codice sorgente da effettuarsi confrontandola con la prima parte di questa lezione: solo così potete capire perfettamente tutta la tecnica che c’è alla base.
Tale libreria comprende numerose utili funzioni, basterà semplicemente includerla nel nostro programma nel modo consueto:
#include "lcd.c"Tale libreria ha bisogno delle routine Delay per poter funzionare, tali routine sono comunque incluse nel download e sono le stesse presenti nelle lezioni precedenti.
Riassumo qui le funzioni disponibili:
LCD_INIT();
Serve ad effettuare l’inizializzazione del display come detto nella parte precedente, va richiamata una solta volta e prima di qualsiasi altra funzione, altrimenti il display non sarà in grado di operare.
LCD_CLEAR();
Effettua la pulizia del display, ovvero cancella il contenuto della DDRAM e porta il cursore nella prima posizione (riga 1, colonna 1).
LCD_CMD(char);
Invia un comando al display, tale funzione viene utilizzata, ad esempio da LCD_CLEAR e da altre, è anche possibile inviare comandi personalizzati, come ad esempio i codici numerici associati ai vari entry mode, sarà comunque una funzione molto poco sfruttata direttamente.
LCD_GOTO(riga,colonna);
Posiziona il cursore per la scrittura alla riga e alla colonna specificata. La numerazione è in base 1, per cui scrivendo:
LCD_GOTO(1,1);
Il cursore si posizionerà alla prima riga, prima colonna.
LCD_PUTCH(char);
Scrive un unico carattere sul display, char ovviamente può essere immesso in qualsiasi formato numerico (decimale, binario -anteponendo come sempre 0b-, esadecimale -anteponendo 0x- o formato carattere -scrivendo il carattere tra singoli apici ”-), è utile per scrivere quei caratteri che non hanno corrispondenza del codice ascii sulla tastiera, come specificato nella precedente parte della lezione: basta avere sottomano la tabella con l’elenco dei codici carattere del controller che abbiamo a disposizione sull’LCD. Esempio:
LCD_PUTCH(0b11110100); //scrive il simbolo omega
LCD_PUTS(“stringa”);
Scrive una stringa intera sul display. Se ci posizioniamo alla prima colonna della prima riga, e abbiamo a disposizione un LCD 16×2 e in tale stringa scriviamo una parola superiore ai 16 caratteri, ovviamente i caratteri dal diciassettesimo in poi non saranno visibili, per cui stiamo attenti quando utilizziamo questa funzione se non vogliamo avere effetti indesiderati sul display. Esempio:
LCD_PUTS("Settorezero.com");
LCD_PUTUN(numero);
Scrive un numero privo di segno sul display, come numero sono accettati il formato CHAR (8bit) o INT (16 bit), per cui sono ammessi numeri interi da 0 fino a 65535.
LCD_PUTSN(numero);
Scrive un numero compreso di segno. Per numeri positivi il segno non viene rappresentato, per numeri negativi, viene anteposto il segno meno davanti al numero. Supporta sia CHAR che INT in ingresso, ovviamente accettando un numero “signed” i valori ammissibili vanno da -32768 a 32767.
LCD_CUSTOMCHAR(pos,byte1…byte8);
Permette la personalizzazione del carattere in posizione “pos”. Vedremo questa funzione nei dettagli nella terza parte di questa lezione, che sarà dedicata soltanto alla personalizzazione dei caratteri.
Il file lcd.c va impostato prima di poter essere utilizzato. Innanzitutto apriamolo e andiamo alla riga 94:
94 95 96 97 98 99 | #define LCD_RS RD2 // Register select #define LCD_EN RD3 // Enable #define LCD_D4 RD4 // LCD data 4 #define LCD_D5 RD5 // LCD data 5 #define LCD_D6 RD6 // LCD data 6 #define LCD_D7 RD7 // LCD data 7 |
Qui impostiamo le linee dati. Se seguite lo schema elettrico proposto in cima alla lezione, vedete che i pin del display (indicati come LCD_XX) sono già associati ai rispettivi pin del picmicro.
Successivamente dalla riga 110 fino alla riga 115 incontriamo altri parametri da impostare:
110 | #define LCD_ROWS 2 // valid numbers are: 1,2 (set to 2 for 2 or more rows) |
Qui va impostato il numero di righe che ha il nostro display, per le nostre prove terremo conto di avere un display da 2 righe, se avete un display da 4 righe dovete comunque lasciare il valore 2, se avete un display da una riga dovrete cambiare il 2 con l’1, ma poi dovrete anche modificarvi i programmi mostrati in questa lezione.
111 | #define LCD_COLS 16 // valid numbers are: 8,16,20 |
numero di colonne dell’LCD, qui utilizzo un display da 16 colonne, se avete un display da 20 colonne, modificate il numero, se avete un display da 8 colonne, oltre al numero dovrete modificarvi anche i programmi.
112 | #define LCD_CURSOR_VISIBLE 0 // 1:cursor on 0:cursor off |
se mettiamo 0, il cursore non sarà visibile, se mettiamo 1, potremo vedere il cursore visualizzato sul display, il quale si presenterà come una lineetta in basso ai caratteri.
113 | #define LCD_CURSOR_BLINK 0 // 1:cursor blinks 0:cursor doesn't blinks |
se mettiamo 0, il cursore rimarrà fisso, impostando ad 1 il cursore lampeggerà
114 | #define LCD_TYPEWRITE 0 // 1:delay between characters |
se mettiamo 0, la scrittura sul display sarà immediata, impostando ad 1, ci sarà un breve ritardo tra la scrittura di un carattere e l’altro, dando un effetto “macchina da scrivere”.
115 | #define LCD_TW_DELAY 50 // milliseconds between characters |
questo rapprenta il ritardo espresso in millisecondi tra la scrittura di un carattere e il successivo, se abilitiamo il settaggio precedente.
Gli ultimi 4 settaggi, relativi per lo più ad effetti grafici, sono già impostati ai valori più adatti per gli esempi, difatti avere la scrittura rallentata, col cursore, in un menù può essere molto fastidioso.
Impostati questi parametri, non abbiamo bisogno più di niente per far funzionare il display (a parte richiamare la funzione LCD_INIT prima di usarlo).
In questa lezione farò 2 esempi di programma: il primo, molto semplice, è il classico “HELLO WORLD!” che non poteva mancare, serve soltanto a farvi capire in maniera molto elementare come scrivere sul display, ed è un tutorial che si trova un po dappertutto, pertanto in questo esempio non faremo uso ne dei led, ne dei pulsanti ne del cicalino. Il secondo esempio, un po’ più elaborato è un semplice menù mostrato sul display, nel quale potremo navigare con i pulsanti e attivare/disattivare le 4 uscite alle quali sono collegati i led, visualizzandone lo stato sul display.
Hello World!
Il file settings è molto semplice, abbiamo soltanto impostato tutte le porte del pic come uscita.
Nel file main.c, dopo la config word, abbiamo le 3 inclusioni:
#include "settings.h" #include "delay.c" #include "lcd.c"
Come già detto in precedenza, è necessario includere prima delay.c e poi lcd.c, in quanto lcd.c fa uso delle funzioni delay.
Abbiamo quindi il main:
void main(void) { settings(); // imposto le porte LCD_INIT(); // inizializzo l'LCD DelayMs(100); // piccolo ritardo iniziale LCD_CLEAR(); // ripulisco il display LCD_GOTO(1,1); // posiziono il cursore sull'LCD: riga1, colonna1 LCD_PUTS("HELLO"); LCD_GOTO(2,1); // riga2, colonna1 LCD_PUTS("WORLD !"); while(1) { } }
Come vedete, dopo aver eseguito le impostazioni, inizializzamo il display come detto prima con l’apposita funzione, personalmente dopo l’inizializzazione do sempre un piccolo ritardo per stabilizzare le linee di comunicazione, in realtà non ce ne sarebbe bisogno.
Effettuo quindi la pulizia del display con LCD_CLEAR(), mi posiziono alla prima riga, prima colonna e scrivo “HELLO”, mi posiziono quindi alla seconda riga, prima colonna e scrivo “WORLD !”, effettuo quindi il ciclo continuo, vuoto, per non far bloccare il pic. Il risultato è il seguente:

Avendo impostato il cursore lampeggiante e l’effetto macchina da scrivere, vedrete il cursore muoversi mentre compone la scritta.
Come vedete, utilizzando una apposita routine, scrivere su un LCD è un gioco da ragazzi: bastano poche righe di codice per avere una gran bella soddisfazione!
Spero non vi siate accontentati di questo semplice esempio, preparatevi perchè vi attende qualcosa di molto più complicato (ma non troppo).
Esempio di semplice menù con LCD e PICmicro
In questo programma, controlleremo lo stato di 4 uscite del picmicro dal display: due tasti (BTNUP e BTNDOWN) ci permetteranno di muoverci su e giù nel menù, un terzo tasto (BTNOK) ci permetterà di cambiare lo stato dell’ uscita selezionata. Lo stato dell’uscita sarà segnalato sul display (e comunque evidenziato anche dall’accensione/spegnimento del led ad essa collegato: tenete conto che al posto dei led potete anche montare dei relè come spiegato nelle precedenti lezioni). Premendo i tasti di navigazione, sarà udibile un suono prodotto dal cicalino, la pressione del tasto OK, invece, produrrà un suono di tipo diverso.
Il menù avrà questo aspetto:

In pratica con i tasti su e giù spostiamo la freccia, posizionandola affiando alla voce desiderata (L1 sta per LED1), premendo OK, cambiamo lo stato dell’uscita selezionata, la scritta affianco quindi si aggiornerà riflettendo lo stato dell’uscita (ON se livello logico alto e quindi relativo led acceso).
Analizziamo prima il file di configurazione, settings.h:
#define BTNUP RB0 #define BTNDOWN RB1 #define BTNOK RB2 #define LED1 RB7 #define LED2 RB6 #define LED3 RB5 #define LED4 RB4 #define PRESSED 0 // per verifica pulsante premuto #define ARROW 0x7E // codice del carattere freccia #define ON 1 #define OFF 0 #define CICALINO RE1
Qui ci sono i vari define, abbiamo soltanto dato dei nomi più semplici da ricordare alle varie uscite/ingressi.
Ho definito un simbolo PRESSED che utilizzerò per fare la verifica del pulsante premuto, avrei difatti potuto fare come sempre:
if (!BTNOK) // oppure if(BTNOK==0) { // istruzioni }
Ma qui espongo invece un metodo alternativo, che può aiutare a capire meglio:
if (BTNOK==PRESSED) { // istruzioni }
avendo definito PRESSED come zero, la sostanza non cambia, ma forse, scritto così, il programma è più semplice da leggere.
C’è quindi un simbolo “ARROW” che corrisponde al codice carattere della freccia rivolta verso destra sul controller HD44780 (vedete la tabella caratteri nella prima parte di questa lezione), ho espresso il codice in esadecimale (come vedete infatti il numero è preceduto da 0x).
Ho quindi definito due simboli ON e OFF, difatti per alcuni il codice è più leggibile se scriviamo:
LED1=ON; // anzichè LED1=1;
Segue quindi il define del cicalino. Proseguendo troviamo:
signed char menupos=0; // variabile che tiene conto della posizione della freccia nel menù
Questa variabile la utilizzo per tenere in memoria la posizione attuale della freccia che utilizzo per navigare nel menù: in alto a sinistra (posizione L1) questa variabile varrà zero, fino ad arrivare al valore 3 nell’ultima posizione (4 posizioni in totale). Le do l’attributo signed perchè può accadere che assuma anche valore negativo.
Segue quindi la funzione settings che non ha nulla di particolare: tutte le porte impostate come uscita, tranne quelle destinate ad alloggiare i pulsanti. I led e il cicalino vengono posti a livello logico basso all’accensione.
La routine lcd.c allegata al progetto (scaricabile insieme al resto in fondo all’articolo per gli utenti iscritti) è configurata in maniera tale da non visualizzare il cursore e da fornire una scrittura diretta (senza ritardi).
Analizziamo quindi il main.c, notiamo qualcosa che fino ad ora non avevamo utilizzato, ovvero i prototipi di funzione:
// prototipi di funzione void main(void); // programma principale void beep(char beeptype); // esegue il beep, usato quando premo i tasti void posizionafreccia(char posizione); // posiziona la freccia nel menù void cambiastato(char posizione); // inverte lo stato del led void scrivistato(char posizione,char stato); // scrive lo stato del led sul display
Come vedete, un prototipo di funzione è la funzione scritta normalmente, ma seguita dal punto e virgola anzichè dalle parentesi graffe contenenti le routine da eseguire (una funzione definita, ma vuota). Questo viene fatto per avvisare il compilatore delle funzioni (che verranno poi definite realmente), in maniera tale da non generare errori se incontra un simbolo che non è stato precedentemente dichiarato, è la stessa cosa che si fa con le variabili: così come dichiaramo una variabile scrivendo:
signed char menupos=0;
Così dichiaramo una funzione, dicendo anche se restituisce o meno un valore e se accetta o meno parametri in ingresso
Ricordo ancora una volta che il void indica che non ci sono valori: il void davanti indica che la funzione non ritorna valori, il void tra parentesi indica che la funzione non prevede argomenti da elaborare.
Nel main prepariamo quindi il display, in maniera da farlo apparire come l’immagine presentata più in alto.
Nel ciclo infinito controlliamo unicamente la pressione dei 3 pulsanti. Ogni pulsante è dotato di antirimbalzo software come spiegato nelle precedenti lezioni. La pressione del tasto BTNUP (SU) decrementa la variabile menupos (che come abbiamo detto serve per tener traccia di dove si trova la freccia: un indice, in pratica, che ci permette di ricordarci in tutto il programma, in quale punto del menù ci troviamo), se il valore di questa variabile diviene minore di zero, allora le assegno il valore 3, in maniera tale che se ci troviamo in posizione 0 e premiamo ancora SU, la freccia verrà a trovarsi in posizione 3 (ultima posizione):
// pressione tasto SU // decremento il contatore che mi posiziona la freccia if (BTNUP==PRESSED) { DelayMs(100); if (BTNUP==PRESSED) { beep(0); // suono menupos--; // decremento la posizione // se in posizione 0 ho premuto su // vado in posizione 3 if (menupos<0) { menupos=3; } // posiziono quindi la freccia posizionafreccia(menupos); } } // fine pressione tasto su
Per chi non lo ricordasse: la seconda verifica della pressione del pulsante, dopo un ritardo, costituisce l’antirimbalzo software come spiegato in una lezione precedente.
All’atto della pressione, richiamo la funzione beep per emettere il suono. La funzione beep accetta in ingresso un valore numerico (da 0 a 2) in maniera tale da emettere un suono diverso (una diversa frequenza) in base al valore che passiamo:
void beep(char beeptype) { char F; switch (beeptype) { case 0: F=70; break; case 1: F=90; break; case 2: F=110; break; } for (char a=40; a--; a!=0) { DelayUs(F); CICALINO=ON; DelayUs(F); CICALINO=OFF; } }
Questa funzione in pratica è uguale a quella vista nelle precedenti lezioni con due sostanziali differenze: il ritardo necessario a generare l’onda quadra è variabile e dipendente dall’argomento passato alla funzione, e inoltre viene eseguito un ciclo di 40 ripetizioni, ma anzichè andare da 0 a 40 come normalmente è spontaneo scrivere, il ciclo viene eseguito al contrario: da 40 verso zero. La sostanza non cambia, ma scritto in questo modo ci permette di rendere il ciclo più efficiente come spiegato in questo articolo su microchipc.
Le funzioni svolte dal tasto BTNDOWN sono pressochè identiche ma eseguite al contrario: il contatore verrà incrementato, se supera il valore di 3, gli verrà dato il valore zero in maniera tale da far ricomparire la freccia in prima posizione.
La pressione di questi due pulsanti (BTNUP e BTNDOWN), richiama la funzione “posizionafreccia” la quale accetta in ingresso il valore di posizione attuale. Tale routine esegue 3 funzioni principali. Prima di tutto cancella (scrive uno spazio) nelle 4 posizioni in cui deve apparire la freccia, in maniera tale da cancellare il carattere freccia precedente:
LCD_GOTO(1,1); LCD_PUTCH(32); // 32=codice dello spazio LCD_GOTO(2,1); LCD_PUTCH(32); LCD_GOTO(1,10); LCD_PUTCH(32); LCD_GOTO(2,10); LCD_PUTCH(32);
Facile capire che quei LCD_GOTO puntano alle posizioni dove le frecce devono comparire:

Successivamente si fa utilizzo di un costrutto switch (vedi manuale Tricky C per sapere come si usa) per analizzare la posizione attuale (passata alla funzione): in base al numero di posizione, viene piazzato il cursore nella “casella” giusta del display:
switch (posizione) { case 0: LCD_GOTO(1,1); break; case 1: LCD_GOTO(2,1); break; case 2: LCD_GOTO(1,10); break; case 3: LCD_GOTO(2,10); break; }
Infine, viene stampato il carattere della freccia:
LCD_PUTCH(ARROW);
Ricordo che abbiamo definito il valore di “ARROW” in settings.h. Come vedete utilizzo la funzione LCD_PUTCH che mi permette di scrivere un solo carattere.
Spero che fin qui sia tutto chiaro: premiamo i pulsanti su e giù e quindi posizioniamo la freccia sul display. Andiamo avanti.
La pressione del tasto BTNOK, produce un beep differente e richiama un’altra routine: cambiastato, alla quale viene sempre passato il valore di posizione attuale. Tale routine definisce innanzitutto una variabile:
char STATO_LED;
la quale serve per tener conto dello stato attuale dell’uscita dopo il cambio. Viene quindi effettuato uno switch in base alla posizione nel menù, in maniera tale da invertire lo stato dell’uscita relativa:
switch (posizione) { case 0: LED1=LED1^1; STATO_LED=LED1; break; case 1: LED2=LED2^1; STATO_LED=LED2; break; case 2: LED3=LED3^1; STATO_LED=LED3; break; case 3: LED4=LED4^1; STATO_LED=LED4; break; }
La variabile STATO_LED, come vedete, memorizza lo stato attuale dell’uscita (del led) che abbiamo selezionato. Infine viene richiamata l’ultima funzione:
scrivistato(posizione,STATO_LED);
la quale ha la funzione di scrivere ON oppure OFF nella posizione relativa sul display: per fare questo dovremo sempre passare la posizione in cui ci troviamo e quindi anche lo stato dell’uscita. Quest’ultima funzione si articola nella stessa maniera delle altre, tranne che per la posizione in cui andare a scrivere. Da notare che ON sarà scritto con uno spazio finale, in maniera tale da cancellare l’ultima lettera (F) di OFF, se tralasciamo lo spazio, apparirà sul display una cosa del genere: L1:ONF
Downloads
Il file zip contiene lo schema elettrico, la routine lcd.c e i codici sorgente e compilati dei due programmi di esempio qui esposti, per ognuno dei due programmi c’è la copia della routine lcd.c già impostata, ho inoltre incluso il foglio excel che ho utilizzato io per disegnare come appare il display, che può essere utile per fare i vostri progetti di menù e ricavare quindi la posizione del cursore.
File di supporto alla settima lezione (parte 2) del corso di programmazione picmicro in C (1417)
Lasciate commenti.
Articoli che potrebbero interessarti
Se desiderate che settorezero continui a rimanere gratuito e fruibile da tutti, non copiate il nostro materiale e segnalateci se qualcuno lo fa

Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza 








#1 da mAx il 23 gennaio 2011
Ciao Complimenti per il corso sul C le lezioni sono veramente utili!!! Sto seguendo la parte del pilotaggio dell’lcd,vorrei far scorrere un testo lungo 40 caratteri e piu’, sulla seconda linea da sinistra a destra, sto provando utilizzando il comando 0×07 ma dopo il 16° carattere scrollato a sx l’lcd s’incastra. Esiste un metodo per risolvere il problema?
saluti mAx
#2 da odessos il 5 febbraio 2011
Le librerie, in generale, sono sempre utilissime per sviluppare programmi con funzioni già pronte all’uso, ma nascondono delle insidie che non tutti prendono in considerazione al momento dell’utilizzo.
L’insidia più ricorrente è il numero di funzioni nidificate che vengono usate nelle librerire, che sommate alle funzioni create all’interno del nostro programma, possono portare il processore ad un errore di STACK OVERFLOW
Tanto per saperne di più l’utilizzo della funzione LCD_GOTO(x,x) all’interno della libreria lcd.c, fa uso di ben 4 livelli di STACK più il livello utilizzato per puntare alla funzione stessa fanno 5.
Qunindi con un PIC 16f877 che ha 8 livelli di STACK rimangono 3 livelli utili.
Quindi puntatore ad una funzione sotto una funzione ecc. crea dei limiti se si utilizzano certe librerie.
#3 da Giovanni Bernardo il 5 febbraio 2011
Possibili problemi vengono sempre segnalati dal compilatore con un warning “possible stack overflow”.
#4 da FABRIZIO il 5 febbraio 2011
Ciao Giovanni io mi chiamo Fabrizio e sono un appassionato di programmazione. Ho deciso da poco di cimentarmi nella programmazione dei microprocessori PIC in C e cercando su internet, ho trovato il tuo corso che, tra l’altro mi complimento per la precisione con cui e’ stato fatto. Siccome vorrei stamparmi le lezioni e studiarmele senza dover guardare il monitor del pc, e’ possibile scaricare i file pdf? Ho provato a salvare la pagina web di ogni singola lezione ma viene stampata solo la prima pagina. Per il momento grazie e complimenti di nuovo.
#5 da Cicche il 9 marzo 2011
Ciao Giovanni,
mi è arrivata da poco la FreedomII (ver.3), ho sostituito il Pic con un 16F877A per seguire il corso.
Per ora le lezioni sono riuscito a seguirle, non senza problemi perchè cambiavo un po i programmi per capire meglio il funzionamento però ho sempre trovato la soluzione per farli andare :)
Qui invece mi ritrovo bloccato. Lcd è compatibile al modello proposto, unica differenza dello schema è che RD1 è collegato a R/W. Per mia logica ho impostato nei setting il livello 0 per questo pin ma ancora non vuole funzionare.
Lcd all’avvio si accende ma non fa nulla rimane schermo vuoto (contrasto regolato).
Se non imposto lo stato di Rd1 il display si accende e riempie tutta la riga 1 di pixel.
Dove posso sbattere la testa?
ps. Ho provato a disabilitare uno alla volta i jumper della scheda ma il risultato non cambia
#6 da Giovanni Bernardo il 9 marzo 2011
Uhm… è strano. Nel registro TRIS sei sicuro di aver impostato RD1 come uscita?
#7 da Cicche il 9 marzo 2011
void settings(void)
{
TRISA=0b00000000;
TRISB=0b00000000;
TRISC=0b00000000;
TRISD=0b00000000;
TRISE=0b00000000;
INTCON=0b00000000;
RD1=0;
}
Ho provato anche le Delay della microchip come suggerivi ad un’altro utente.
Sto provando il tuo main di “Hello World”, provando a tenere anche solo la parte di inizializzazione Lcd, cancellazione e poisizionamento cursore..
Quindi penso che ci deve essere qualche problema con l’inizializzazione. Come posso controllare se i delay generati dal pic corrispondono a quelli che vorrei? non ho un oscillatore.
#8 da Giovanni Bernardo il 9 marzo 2011
Basta soltanto che nella funzione init aumenti un po’ i ritardi di una/due unità. Altri utenti dicevano che risolvevano aggiungendo un’istruzione… leggi un po tutti i commenti che da qualche parte c’è la soluzione.
#9 da Cicche il 9 marzo 2011
Questa sera farò qualche prova, possibile che l’errore dei Delay sia dovuto che sulla FreedomII ci sono i 2 condensatori da 15pF?
Sequendo quello che descrivi nella lezione 2 questi valori sarebbero al limite per il pic 16F877A.
#10 da Cicche il 10 marzo 2011
Trovata la modifica che dicevi, posto nei commenti della lezione 7 – 3/3
Grazie!
#11 da slavin89 il 2 aprile 2011
ciao a tutti..
ho un problema con questa parte del corso.. ho creato il circuito descritto però quando vado ad accenderlo l’unica cosa che appare sull’LCD è che la prima riga è tutta nera e niente altro..ho provato con il vostro programma ma niente di nuovo sempre l’ennesimo risultato, ho verificato più e più volte il circuito ed è tutto corretto. ho provato anche a mettere RD1=0 come avevo letto di fare su un post di cicche ma niente da fare..
mi sapete aiutare? il display è un dysplay corrispondente di quello usato da voi
#12 da Giovanni Bernardo il 3 aprile 2011
Leggi nei commenti, c’è la soluzione
#13 da slavin89 il 3 aprile 2011
proprio non riesco a trovare la soluzione nei commenti mi puoi indicare dov’è?..l’unica che ho letto è di mettere una R di pull up sulle uscite se sono analogiche ma nello schema non ci sono porte analogicher utilizzate
#14 da slavin89 il 6 aprile 2011
ciao a tutti ho davvero bisogno del vostro aiuto..ho montato il circuito tale e quale allo schema sul mio pic 16f 877 , il mio display è questo http://www.epm.it/schede/P03.pdf e dopo aver programmato il pic con il vostro file nella maniera corretta ancora non ne vengo a capo quando do alimentazione lo schermo rimane bianco o nero a seconda di come regolo il contrasto ma nessuna scritta. premetto ce ho letto tutti i commenti e fatto le varie prove ma non è cambiato nulla non so proprio cosa fare vi prego datemi un aiutino
saluti Luca
#15 da Giovanni Bernardo il 7 aprile 2011
modificato il delay nella funzione strobe? provato a mettere i pin non utilizzati a massa o a lasciarli non connessi? provato ad aggiungere nell’inizializzazione quella funzione di cui si parla nei commenti?
#16 da slavin89 il 7 aprile 2011
si ho provato a modificare sia il delay nello strobe che aggiunta l’inizializzazione ma niente e i i pin del display non usati sono a gnd non capisco se è il dislay ma a me sembra che tutto sia compatibile
#17 da slavin89 il 9 aprile 2011
qualcuno può aiutarmi?..continuo ad avere entrambe le righe nere non so proprio cosa fare…
#18 da Giovanni Bernardo il 9 aprile 2011
Entrambe le righe nere è un problema di contrasto
#19 da slavin89 il 10 aprile 2011
è ma cosa devo fare?..ho il trim collegato ma muovendolo l’unica differenza è che da nere diventano trasparenti non c’è nessuna scritta
#20 da Giovanni Bernardo il 10 aprile 2011
Allora il trimmer funziona, quindi il display non si inizializza
#21 da slavin89 il 12 aprile 2011
scusate ma quali sono in particolare i ritardi riportati sul datasheet del display per inizializzarlo?..cioè sul file lcd quali ritasrdi corrispondono a quelli messi sullo schema del datasheet?
#22 da slavin89 il 14 aprile 2011
potete provare ad aiutarmi a modificare il file di inizializzazione di questo display ?http://www.epm.it/schede/P03.pdf
io ci ho provato ma davvero non ce la faccio fatemi questo piacere
#23 da Giovanni Bernardo il 14 aprile 2011
L’inizializzazione sta a pagina 14, i tempi sono indicati chiaramente
#24 da slavin89 il 14 aprile 2011
si ho capito ma io ho provato a modificarli ma non so se ho sbagliato o seppure c’è qualche altro problema per piacere potreste farmi un piccolo listato dell’inizializzazione per quel display?
ve lo chiedo per favore non capisco cosa non va
#25 da michelep3916 il 23 aprile 2011
Salve, sono nuovo del forum, complimenti per gli articoli e le lezioni. Io avrei un problema in quanto MPLAB non mi compila il progetto (creato inserendo tutti i sorgenti in un nuovo progetto) senza modificare nulla perchè sono ancora ai primi esperimenti. Grazie!!
#26 da Giovanni Bernardo il 23 aprile 2011
Per me la frase “ho un problema” è priva di significato. La sfera magica mi si è appena guastata. Un mio amico è andato dal dottore e ha detto “non mi sento bene” e l’hanno seppellito direttamente.
#27 da leyfon il 20 giugno 2011
non riesco a capire come devo collegare i pin read/write
#28 da Giovanni Bernardo il 20 giugno 2011
Perchè, dallo schema non si capisce?
#29 da marcolindo94 il 21 ottobre 2011
Buonasera, innanzitutto mi complimento per i contenuti, in quanto molto utili, e volevo chiedere una cosa:
perchè quando compilo il sorgente con MPLAB IDE 8.5 (per il progetto di Hello World, con tutti i file inclusi), mi da il seguente errore?:
..\programmazione_picmicro_04\routine_LCD\lcd.c; 163. function “_LCD_STROBE” redefined
Questo errore è ripetuto per ogni funzione dell’LCD (_LCD_WRITE, _LCD_GOTO, _LCD_CLEAR eccc….)
Come si potrebbe fare per risolvere il problema?
Grazie, Marco
#30 da Giovanni Bernardo il 22 ottobre 2011
Leggendo più attentamente quanto c’è scritto nella lezione 3, nella parte dove si spiega come creare il progetto.
#31 da davsto il 2 novembre 2011
Buon giorno,
innanzi tutto mi complimento per la qualità e la precisione delle informazioni presenti su questo sito.
Ho montato il circuito come da schema, con questo LCD, (http://www.farnell.com/datasheets/40247.pdf) che è compatibile con quanto descritto per quanto riguarda controller,piedinatura e tempi di inizializzazione.
Il fatto è che non si accende!…ho notato che i piedini 15 e 16, che nel datasheet risultano come anodo e catodo, non sono in realtà collegati(facendo il test di continuità con il tester). Infatti ho notato che le piste sono interrotte poiché mancano due resistenze che dovrebbe esserci, perché indicate nel layout…Comunque non penso che il problema sia questo, dato che nemmeno collegando direttamente gli ingressi A e K a 5V e massa il display si accende. Rimane spento completamente. Come posso verificare se il display è guasto?almeno per verificare se la retroiiluminazione funziona?Variando il trimmer su V0 nulla cambia. La tensione precisamente è di 4,98 Volt, regolata dal solito 7805.
Ringrazio infinitamente
#32 da Giovanni Bernardo il 2 novembre 2011
La retroilluminazione è una cosa e il display ne è un’altra. La retroilluminazione è fatta tramite leds ed è indipendente dal funzionamento del display. Il contrasto quindi non c’entra niente con la retroilluminazione. Lasci perdere i due pin della retroilluminazione e provi soltanto ad alimentare il display e a mettere il trimmer del contrasto, girando il trimmer tutto in una direzione, il display deve dare tutti rettangolini neri, girando dalla parte opposta spariscono, se così non funziona, controlli meglio i collegamenti.
#33 da Gianni_90 il 2 novembre 2011
buongiorno, come sempre vi ringrazio e congratulo per il vostro sito, io ho acquistato lo stesso display di davsto e lo stesso non riesco a visualizzare nulla; il contrasto funziona, il problema è che o vedo tutti i rettangolini accesi oppure nulla, ho anche provato a variare i ritardi e a mettere nel programma la sola istruzione di pulizia del display ma ottengo sempre lo stesso effetto..se qulcuno può darmi un indizio ne sarei grato; buona giornata a tutti!
#34 da MBrix il 6 novembre 2011
Ciao a tutti,
anche io sto trovando qualche problema con il powertip (il mio è un 20×2: PC2002LRS).
Dal data sheet mi sembra che l’inizializzazione sia diversa da quella del corso (Sempre Grazie di cuore a Giovanni per questo corso che fino a prima del LCD ero riuscito a seguire con successo seppur con altro PIC).
Per Gianni_90: Questo è un indizio… ma per ora anche per me non ho avuto progressi.
Per esempio Clear diplay nel file lcd originale è:
LCD_WRITE(0b00000000); // clear display
invece nel powertip richiede un 1 finale:
LCD_WRITE(0b00000001); // clear display
Anche il quarto invio di inizializzazione DB4 = 1 anzichè 0 come nella lezione
Però al momento sono bloccato ancora con prima riga tutta nera (da quello che sono riuscito a capire non si inizializza) ci sto lavorando, se trovi qualcosa ti chiedo di pubblicarla. Grazie in anticipo. Ciao!
#35 da davsto il 28 novembre 2011
Scusa il ritardo. Ti ringrazio per la puntuale risposta.
Ho risolto il problema cambiando LCD! Aveva evidentemente un problema di fabbrica.
Ne ho montato uno identico e funziona!
saluti!
Davide Stocchero
#36 da Titti il 20 novembre 2011
hello! complimenti per la guida fin ora ho trovato molto intressante la programmazione dei pic ma solo con questa guida sto inizziando a conoscerli! la domanda che vorrei fare è se è possibile disabbilitare il LCD_TYPEWRITE a meta esecuzzione del programma.
GRAZZIE!
#37 da Crowdp il 5 dicembre 2011
Ciao Giovanni! Sono alle prime armi nella programmazione dei pic e a volte mi inchiodo su cose veramente stupide come probabilmente sarà questa. Sto usando un pic 18f452 e ho adattato il tuo codice per questo pic. Purtroppo appena compilo però ottengo questo errore
delay.c:
11: {
^ (1098) conflicting declarations for variable “DelayMs” (delay.c:11)
Veramente non capisco il perchè dato che viene sempre dichiarata come “void DelayMs (unsigned char cnt)”
Oltretutto nella lezione 6 i delay funzionavano quindi proprio non vedo dove venga ridefinita in modo sbagliato la funzione!
Ti ringrazio in anticipo!
#38 da gaudenzio il 6 dicembre 2011
ciao,
scusa se ti infastidisco con stupide domande…. siccome non riesco a scrivere sul display (scheda freedomII) e ho visto dai commenti che molti prob. sono stati risolti alzando i tempi con la f() Delay(…)
testando la tua funzione Delay(unsegned char valore) accendendo e spegnendo dei led mi sono accorto che il tempo di spegnimento del led non varia passando diversi valori alla funzione….
questo potrebbe essere la causa del non funzionamento del display…
Domanda: i tempi di ritardo da impostare per l’inizializzazione del display ecc.. devono rientrare in un range particolare oppure basta che siano più lunghi di…(un minimo) perché in tal caso li allungherei di molto per sicurezza richiamando + volte la Delay(…)
grazie per la gentile collabirazione
gaudenzio
#39 da Arighi Alberto il 3 gennaio 2012
Ciao
complimenti per questa guida che ho trovato molto interessante e mi ha permesso di avvicinarmi al mondo dei Pic. Sono alle prime armi nella programmazione dei Pic e mi sono bloccato sulla lezione 7 LCD. Sono riuscito a far funzionare tutti gli esercizi della lezione 7 tranne quello riguardante la visualizzazione del menu. I led e i pulsanti funzionano ma sul display non si vede niente. Ho provato anche a scaricare il tuo .hex ma succede la stessa cosa.
Cosa posso fare?
Per il momento grazie e complimenti di nuovo.
#40 da Giovanni Bernardo il 9 marzo 2011
metti quelli da 22pF. Comunque un condensatore sbagliato puo si indurre qualche errore di temporizzazione, ma non cosi esagerato
#41 da Cicche il 9 marzo 2011
Proverò a trasportare il tutto su una breadboard o un millefori, per ora la Freedom non la tocco.
Appena posso posto il risultato.
Grazie di tutto per ora!
#42 da Giovanni Bernardo il 9 marzo 2011
Ok ma non penso affatto che siano i condensatori il problema. Prova a includere quell’istruzione come hanno detto alcuni tra i commenti.