Come abbiamo accennato nella prima parte di questa lezione, alcune posizioni della CGROM del controller sono vuote e scrivibili: abbiamo a disposizione 64byte liberi in cui scrivere.
Essendo ogni carattere composto da 8 byte, vuol dire che possiamo personalizzare 8 caratteri (64/8).
Come vedremo, la personalizzazione dei caratteri è in realtà molto molto semplice.
Innanzitutto immaginiamo ogni carattere costituito da 8 righe, di 5 pixel ognuna (carattere 5×8).
Ricordo che in altri documenti si fa invece riferimento ai caratteri come 5×7 : non c’è differenza in quanto l’ultima riga generalmente viene lasciata vuota per far posto al cursore, ma in fase di personalizzazione nulla ci vieta di utilizzare anche quest’ultima riga (quella identificata come byte7 nell’immagine successiva).
Ogni riga del carattere rappresenta un byte della CGROM (anche se costituito da solo 5 “posizioni”: le rimanenti 3 – per formare l’intero byte – si possono intendere poste sempre a zero: il loro valore è ininfluente).
Per disegnare, ad esempio, una freccia rivolta a destra, costruiamo una griglia 5×8, e per ogni riga, calcoliamo il valore del byte considerando i pixel pieni posti a 1, come da immagine seguente :

(grazie ancora un’altra volta a Dincer Aydin per la gentile concessione)
Per andare a caricare il nuovo carattere nella CGROM, andremo ad eseguire le seguenti operazioni (tenendo sempre conto che il pin RW è messo a massa per consentire la sola scrittura):
Si pone RS a livello logico basso per dire che dobbiamo impartire un comando.
Inviamo il comando per impostare l’indirizzo della CGROM in cui scrivere (guardiamo la tabella dei comandi nella prima parte di questa lezione). La prima posizione in cui scrivere sarà 0100 0000 (64); essendo il carattere di 8 byte, la seconda posizione (o forse meglio: il secondo quadrante) in cui incominciare a scrivere (per poter cioè personalizzare il carattere successivo), sarà invece 64+8 = 72 e così via (la routine inclusa in lcd.c fa già tutto da sè).
In pratica il primo carattere personalizzato sarà richiamabile inviando, con LCD_PUTCH, il codice 0 (prima locazione della CGROM).
Dopo aver impostato l’indirizzo della CGROM in cui scrivere, inviamo uno dopo l’altro gli 8 bytes che costituiscono il nostro carattere (nel caso della freccia, preso ad esempio poco fa, invieremo 0, poi 4, poi 2, poi 31 ecc): in questo momento il controller incrementerà in automatico la posizione del byte della CGROM in cui scrivere, per cui, dopo aver inviato il primo byte nella posizione 64, non sarà necessario specificare che il secondo byte lo vogliamo scrivere in posizione 65: basterà soltanto inviare il valore del byte.
Finita la personalizzazione dei caratteri dobbiamo lasciare la modalità di scrittura nella CGROM, per cui basterà inviare un altro comando (es.: cancellazione schermo).
I caratteri personalizzati saranno ora visibili inviando i codici da 0 a 7 (es.: con LCD_PUTCH).
Attenzione: Le locazioni in cui andremo a scrivere i nuovi caratteri sono RAM, il che vuol dire che tolta alimentazione al display, i caratteri verranno persi e al loro posto ci saranno byte posti a caso, pertanto il programma che andremo ad implementare sul picmicro dovrà prevedere, dopo l’inizializzazione del display, anche la rigenerazione dei caratteri.
Calcolo dei byte per personalizzare i caratteri
Ho preparato per i lettori che mi stanno seguendo in queste lezioni, (ma anche per tutti gli altri), un semplicissimo programmino con cui disegnare i simboli e ricavarne i valori dei byte da caricare nella CGROM: CustomCharHD44780.
Il suo utilizzo è semplicissimo, se avete capito quanto esposto sopra, non devo spiegarvi nulla:
Basta cliccare nelle celle per colorarle (settare/resettare il bit), nella textbox inferiore viene riportata la sequenza di byte del carattere, è inoltre possibile salvare il carattere e quindi riaprirlo. Nel download sono inclusi alcuni semplici caratteri che ho realizzato per questo tutorial. Quello che ci interessa è la sequenza di byte: basta cliccarci sopra e viene automaticamente copiata negli appunti, pronta per essere incollata nella routine. E’ possibile scaricare questo programma dall’apposita pagina o in fondo all’articolo.
Questo software richiede il .NET Framework 2.0 o superiore per poter funzionare.
Personalizziamo i caratteri
Nella parte precedente di questa lezione, ho esposto le funzioni disponibili con la routine lcd.c. Abbiamo visto che c’è una funzione dedicata alla personalizzazione dei caratteri:
void LCD_CUSTOMCHAR(unsigned char pos,unsigned char byte0,unsigned char byte1,unsigned char byte2,unsigned char byte3,unsigned char byte4,unsigned char byte5,unsigned char byte6,unsigned char byte7)
Il suo utilizzo è molto semplice: il primo parametro è il numero del carattere da personalizzare (valori validi: da 0 a 7), i successivi 8 parametri da passare alla funzione rappresentano la sequenza di byte calcolata col programma visto prima. Nel caso del carattere a forma di cuore (come illustrato nell’immagine di presentazione del programma) volendo personalizzare il carattere n°0 scriveremo nel main:
LCD_CUSTOMCHAR(0,0,10,31,31,14,4,0,0);
Per poter poi richiamare il carattere, possiamo utilizzare la normale funzione LCD_PUTCH:
LCD_PUTCH(0);
E’ tutto più semplice da ricordare se utilizziamo dei define per ricordarci dei numeri associati ai caratteri:
#define cuore 0 LCD_CUSTOMCHAR(cuore,0,10,31,31,14,4,0,0); LCD_PUTCH(cuore);
Quindi come avete visto, è tutto molto semplice e ci possiamo divertire in tutti i modi, creando anche semplici animazioni.

Codici sorgente
Nel file zippato che segue è possibile scaricare 3 programmi di esempio: il primo genera la schermata così come presentato ad inizio articolo: vengono generati 8 simboli e stampati (caratteri_custom).
Il secondo genera l’immagine che vedete qui sopra (pacman_example).
Il terzo è un semplice esempio di animazione, con due pacman che mangiano i “pallini” (pacman_animated)
Gli ultimi due esempi, fanno conto di utilizzare un display lcd 16×2, per cui se state utilizzando un display di formato differente, dovrete effettuare degli aggiustamenti al codice per visualizzare il tutto in maniera ottimale. Per lo schema elettrico potete fare riferimento a quello già utilizzato nella parte precedente, facendo a meno dei pulsanti e dei led, anche il cicalino non è essenziale pur venendo utilizzato nell’esempio dell’animazione giusto per dare uno spunto.
File di supporto alla settima lezione (parte 3) del corso di programmazione picmicro in C (222)
Articoli che potrebbero interessarti:




#1 da Ferdinando il 9 novembre 2009
Fantastico! Era da una vita che cercavo una guida così ben fatta! Complimenti!
#2 da S.D.R. il 9 novembre 2009
Buon caffè ! ;-)
Miraccomando continua con la guida .
A proposito ,cosa ne pensi del software MikroC , non sembra male , ha un sacco di funzioni che aiutano ?!
#3 da Giovanni Bernardo il 9 novembre 2009
Grazie assai, ho gradito molto :)
Mikroc a me, personalmente, non piace. Primo perchè non segue lo standard ansi, e questo può causare difficoltà se vuoi eseguire il “salto” da C a C18 o ad altri C ansi. Il non seguire lo standard ansi è dovuto proprio al fatto che ci sono queste funzioni che “aiutano”, e per me è un male perchè ti tengono all’oscuro di ciò che accade. E’ una scelta personale. Io preferisco affrontare le difficoltà una volta, imparare le cose a fatica, così le fisso meglio, ma soprattutto so cosa accade realmente. Premetto che comunque non ho mai usato MikroC, ho imparato direttamente l’ansi C sapendo di seguire uno standard universalmente riconosciuto. Ho tanto sentito parlare del MikroC e della sua semplicità dovuta a semplificazioni e alle librerie già belle e pronte, ho letto il manuale e alcune cose non mi piacciono. Un buon esercizio che puoi fare, se vuoi semplificarti la vita ma senza rinunciare a imparare uno standard, sarebbe usare il mikroc e poi riscrivere il codice per usarlo con l’hitec. E’ un po quello che sto facendo io. Ho trovato alcuni programmi di esempio scritti in MikroC e ho trovato delle sintassi a dir poco assurde, ho dovuto faticare un po’ per capire alcune parti di codice a cosa servivano e quindi convertirle in Ansi.
Se decidi di imparare il MikroC, comunque, deve essere una tua scelta personale e il mio personale commento non deve influenzarti assolutamente, ho esposto soltanto come la penso ma ovviamente ognuno deve fare ciò che più si sente a suo agio fare, è chiaro. Se il MikroC ti fa sentire più a tuo agio, allora ben venga, puoi anche pubblicare i codici che presento nelle lezioni convertiti in MikroC, cosi magari gli utenti possono capire la differenza.
#4 da S.D.R. il 17 novembre 2009
Ciao come va ;
Ho provato ad eseguire il listato proposto alla lezione 2 (led e pulsanti)del sito http://www.fisertek.it (quello in fondo alla pagina) , li usa la funzione switch , solo che non mi funziona e non riesco a capire il perchè .
Poi ho notato che inizia la main principale con “main(void)” , si può scrivere anche così ?
Alla prossima lezione che argomento tratterai ?
#5 da Giovanni Bernardo il 18 novembre 2009
Ciao tutto ok.
La funzione main la puoi scrivere anche senza il void davanti, il compilatore la accetta lo stesso, è implicito che quando ometti il void la funzione non restituisce nulla, io cerco sempre di non rimanere nulla di implicito perchè non ho idea se tutti i compilatori si comportano allo stesso modo, per cui il void lo metto sempre. Il costrutto switch è conveniente utilizzarlo quando bisogna verificare più condizioni: in questo caso invece di mettere una serie di if…else, metti lo switch così il codice è anche più leggibile, adesso non so perchè non ti funziona, se hai copiato il codice di Sergio e seguito il suo schema, ti deve funzionare, se hai fatto delle modifiche fammi vedere che modifiche hai fatto e posso esserti d’aiuto. Nella prossima lezione vorrei parlare dell’eeprom interna, per imparare come si fa a memorizzare dei dati in maniera permanente e richiarmarli anche dopo che la tensione di alimentazione è andata via. L’eeprom esterna, invece, sarà oggetto di altra trattazione perchè utilizza il protocollo I2C (almeno le memorie eeprom più diffuse – le 24xx- utilizzano questo) che è un altro paio di maniche ma penso che su questo non dirò nulla dal momento che ci sono già tanti ottimi tutorial che lo spiegano, tra cui quello di Mauro Laurenti, per cui mi limiterò a fare degli esempi di codice.
#6 da S.D.R. il 21 novembre 2009
Ciao ;
Credo di aver fatto una cosa mooooooooolto sbagliata , ossia ho incominciato a smanettare con MPLAB su Debugger ed ora non riesco più a programmare il pic ,Mannaggia a me :-S
Devo buttare via il pic , qualche consiglio !?
Uso PICkit2 e il pic 16F873A
#7 da S.D.R. il 21 novembre 2009
Dimenticavo , questo è l’errore che mi da :
PK2Error0027: Failed verify (Address = 0×0 – Expected Value 0×3FFF – Value Read 0×118A)
#8 da Giovanni Bernardo il 21 novembre 2009
La verifica fallisce quando si effettua il confronto tra il programma caricato sul pic e il programma caricato nel software di programmazione, in pratica qui ti dice: ho verificato la prima cella (0×00) della memoria programma, io (software) in quella posizione ho il valore 0×3FFF, invece sul pic ho trovato 0×118. Stai facendo la verifica del pic tenendo caricato o nessun programma sul software o un programma diverso. Esegui la cancellazione e poi fai la verifica della cancellazione (blank), se per sbaglio hai programmato i fuse per la protezione, allora non puoi piu fare niente, ma se li hai programmati così, il pickit2 te lo dice: esce scritta una cosa del tipo “ALL PROTECT” in rosso (però, a dirti il vero, questa cosa è successa pure a me anche se non era vero: avevo usato un pic vecchio che probabilmente aveva un po di ossido sui pin, ripulito non ho piu avuto problemi).
#9 da S.D.R. il 21 novembre 2009
scolleegando tutto , ossia pulsanti e led e alimentazione , quindi è alimentato solo con il PICkit2 mi da l’errore :
PK2Error0027: Failed verify (Address = 0×5 – Expected Value 0×3000 – Value Read 0×0)
#10 da Giovanni Bernardo il 21 novembre 2009
Quindi effettui la programmazione e in fase di verifica ti da il problema… Stacca il pic, passa un po di aria compressa sul pic e sullo zoccolo (non si sa mai, a me è capitato), cancellalo un paio di volte e poi riprova.
#11 da S.D.R. il 21 novembre 2009
Alla fine ci sono riuscito , però usando il software PICkit2 , ho fatto erase e poi blank check , MPLAB non lo cancellava .
Grazie
#12 da Giovanni Bernardo il 21 novembre 2009
;)
#13 da S.D.R. il 21 novembre 2009
Sicuramente smanettando con mplab ho fatto qualche casino perchè con il software PICkit2 funziona bene .
Allora torno ad un altro problema di cui ti ho accennato l’altro giorno , ossia l’istruzione switch il listato che ho creato è questo :
io uso un pic16f873A
#define XTAL_FREQ 8MHZ // questo è utilizzato dalle routine di ritardo contenute in Delay.C
#include // contiene i nomi mnemonici di registri e porte
__CONFIG (HS & WDTDIS & PWRTEN & BORDIS & LVPDIS & DUNPROT & WRTEN & DEBUGDIS & UNPROTECT);
#include “delay.c” // routine per ritardi
#define asp 120
void main(void)
{
TRISA=0b00000111;
TRISB=0b00000000;
TRISC=0b00000000;
while(1) //ripete il ciclo all’infinito
{ //graffa di apertura di while
switch (PORTA) //lettura PORTA
{ //graffa di apertura di switch
case 1: //se PORTA è 1 (0001) esegue la sequenza sotto, altrimenti salta
PORTB = 0b00000001; DelayMs(asp); //sequenza da 0 a 7
PORTB = 0b00000010; DelayMs(asp);
PORTB = 0b00000100; DelayMs(asp);
PORTB = 0b00001000; DelayMs(asp);
PORTB = 0b00010000; DelayMs(asp);
PORTB = 0b00100000; DelayMs(asp);
PORTB = 0b01000000; DelayMs(asp);
PORTB = 0b10000000; DelayMs(asp);
break; //interrompe il programma switch e torna a while
case 2: // se PORTA è 2 (0010) esegue, altrimenti salta
PORTB = 0b10000000; DelayMs(asp); //sequenza da 7 a 0
PORTB = 0b01000000; DelayMs(asp);
PORTB = 0b00100000; DelayMs(asp);
PORTB = 0b00010000; DelayMs(asp);
PORTB = 0b00001000; DelayMs(asp);
PORTB = 0b00000100; DelayMs(asp);
PORTB = 0b00000010; DelayMs(asp);
PORTB = 0b00000001; DelayMs(asp);
break;
case 4: //se PORTA è 4 (0100) esegue, altrimenti salta
PORTB = 0b10000001; DelayMs(asp); //sequenza incrociata
PORTB = 0b01000010; DelayMs(asp);
PORTB = 0b00100100; DelayMs(asp);
PORTB = 0b00011000; DelayMs(asp);
PORTB = 0b00100100; DelayMs(asp);
PORTB = 0b01000010; DelayMs(asp);
PORTB = 0b10000001; DelayMs(asp);
break;
} //graffa di chiusura di switch
PORTB=0; //spegne tutti i led
} //graffa di chiusura di while
}
#14 da Giovanni Bernardo il 21 novembre 2009
allora… manca #include <pic.h> alla seconda riga (ma penso sia piu un problema di wordpress che ha cancellato), hai messo include senza includere niente… per il resto sembra a posto…
Sei sicuro che poi il circuito sia a posto? Mettere “se PORTA è 1 (0001)” implica che hai messo la porta normalmente a massa e la “tiri su” quando premi il pulsante, probabile che hai messo la resistenza di pullup (e quindi si viene a trovare sempre a livello logico alto) e quando premi va a massa (che è la cosa piu logica da fare come illustrato nelle precedenti lezioni). Se è cosi (premendo la porta va a massa) devi cambiare i valori degli switch… 110 (6) per il primo caso, 101 (5) per il secondo e 011 (3) per il terzo
#15 da S.D.R. il 22 novembre 2009
Infatti la gestione dei tasti era invertita , ora ho messo i valori che mi hai detto tu però non riesco a capire come mai non mi funziona , premo i tasti e non si accendono il led .
Ho provato a fare il debugger-MPLABSIM con mplab per vedere come cambia lo stato delle porte solo che non so come forzare i bit della PORTA per vedere come reagisce.
Come si fa a cambiare di stato i bit per simulare la pressione dei tasti ?
#16 da Giovanni Bernardo il 24 novembre 2009
Non ho mai utilizzato il sistema di simulazione di mplab per cui non posso esserti d’aiuto, per il resto non so che dire, il programma di Sergio è corretto, il problema suppongo sia da ricercare nel circuito.
#17 da S.D.R. il 24 novembre 2009
Lo so che sono un po’ stressante però sono alle prime armi anche se anni fa ho programmato parecchio con il basic e con il PASCAL e il C è una cosa nuova per me , quindi porta pazienza .
Oltretutto sto scrivendo sulla pagina dove l’argomento è il display quindi il mio non centra molto , hai una sezione per argomenti generici così scrivo altrove .
Tornando al mio problema ho provato a fare la stessa cosa sfruttando il ciclo if else riprendendo la tua lezione sull’accensione di 2 led e funziona tutto alla perfezione quindi il circuito funziona bene , hai qualche suggerimento perchè mi scoccia questa cosa .
Grazie per l’infinita pazienza .
#18 da Giovanni Bernardo il 25 novembre 2009
Puoi scrivermi il codice che hai fatto con gli IF e che ti funziona?
#19 da S.D.R. il 25 novembre 2009
Ecco quà :
uso sempre il pic 16F873A
———————————————————–
Setting.h
#define XTAL_FREQ 8MHZ // questo è utilizzato dalle routine di ritardo contenute in Delay.C
#define BTN1 RB0
#define BTN2 RB1
#define BTN3 RB2
void settings(void)
{
TRISA=0b00000000; // Tutte output
TRISB=0b00000111;
TRISC=0b00000000;
}
———————————————-
main.c
void main(void)
{
settings(); // eseguo la funzione settings contenuta nel file header settings.h, così imposto le porte e i registri
while(1)
{
// controllo pulsante 1
if (!BTN1) // se pulsante1 premuto (quando è premuto, porta il pin allo stato logico basso)
{
DelayMs(100);// ritardo per antirimbalzo
if (!BTN1) // se dopo 100ms il pulsante è ancora premuto, non si tratta di un rimbalzo
{
PORTC=0b00000001;
DelayMs(100);
PORTC=0b00000010;
DelayMs(100);
PORTC=0b00000100;
DelayMs(100);
PORTC=0b00001000;
DelayMs(100);
PORTC=0b00010000;
DelayMs(100);
PORTC=0b00100000;
DelayMs(100);
PORTC=0b01000000;
DelayMs(100);
PORTC=0b10000000;
DelayMs(100);
}
}
else
{
PORTC=0;
}
// controllo pulsante 2
if (!BTN2) // se pulsante1 premuto (quando è premuto, porta il pin allo stato logico basso)
{
DelayMs(100); // ritardo per antirimbalzo
if (!BTN2) // se dopo 100ms il pulsante è ancora premuto, non si tratta di un rimbalzo
{
PORTC=0b10000000;
DelayMs(100);
PORTC=0b01000000;
DelayMs(100);
PORTC=0b00100000;
DelayMs(100);
PORTC=0b00010000;
DelayMs(100);
PORTC=0b00001000;
DelayMs(100);
PORTC=0b00000100;
DelayMs(100);
PORTC=0b00000010;
DelayMs(100);
PORTC=0b00000001;
DelayMs(100);
}
}
else
{
PORTC=0;
}
// controllo pulsante 3
if (!BTN3) // se pulsante1 premuto (quando è premuto, porta il pin allo stato logico basso)
{
DelayMs(100); // ritardo per antirimbalzo
if (!BTN3) // se dopo 100ms il pulsante è ancora premuto, non si tratta di un rimbalzo
{
PORTC=0b10000001;
DelayMs(100);
PORTC=0b01000010;
DelayMs(100);
PORTC=0b00100100;
DelayMs(100);
PORTC=0b00011000;
DelayMs(100);
PORTC=0b00100100;
DelayMs(100);
PORTC=0b01000010;
DelayMs(100);
PORTC=0b10000001;
DelayMs(100);
}
}
else
{
PORTC=0;
}
}// Fine ciclo continuo
} // Fine main
——————————————–
Grazie!
#20 da Giovanni Bernardo il 25 novembre 2009
Scusa un attimo… i pulsanti sulla porta B e lo switch lo fai sulla A ?!? Se i pulsanti li hai sulla porta B è la porta B che devi verificare non la A…
#21 da S.D.R. il 26 novembre 2009
No con lo switch i pulsanti sono sulla porta A infatti TRISA=0b00000111 e switch (PORTA) .
Poi ho fatto la prova di usare la porta B per i tasti e la porta C per i led però non ha funzionato lo stesso , poi ho sviluppato il software con if-else sulle ultime porte usate .
Non è che magari le limitazioni del software gratuito inibiscono questa istruzione ?
#22 da Giovanni Bernardo il 26 novembre 2009
Che io sappia l’unica limitazione della versione LITE è il fatto delle 2000H word di programma… Per il resto lo switch deve funzionare… è molto strano…
Prova con
switch(PORTA & 7)
{
case 6: // primo pulsante su porta RA0
//…
break;
case 5: // secondo pulsante su porta RA1
//…
break;
case 3: // terzo pulsante su porta RA2
//…
break;
}
in pratica: in condizioni normali (pulsanti non premuti), avendo la resistenza di pullup, il valore di PORTA è 0b00000111.
Se premo RA0, il valore di porta diviene 0b00000110, quindi facendo l’and con 0b00000111 il valore diviene 0b00000110 (ovvero 6 in decimale) ecc, mettendo l’AND con valore 7 portiamo a zero tutti i bit da 4 a 8, concentrandoci soltanto sui primi 3 bit che ci interessano, lo facciamo eventualmente qualche altro bit ci falsa il valore… Prova così e fammi sapere… devi solo aggiungere &7
#23 da S.D.R. il 27 novembre 2009
Si funziona !!!
Se non ho capito male erano gli ingressi da 4 a 8 che influivano sul funzionamento allora avrei dovuto metterli elettricamente a 5 volt ma su TRISSB da 4 a 8 sono uscite quindi dovevo mettere tutta la porta come input altrimenti bruciavo la porta ……….
Allora ho provato a mettere tutta la PORTA come INPUT ed ho fatto il CASE1 254, CASE2 253 , CASE1 251 non ho messo &7 e funziona anche così .
Ma dentro le parentesi dello switch non si può indicare solo gli ingressi che mi interessano in vece di indicare tutta la PORTA in modo che gli altri non li consideri e mi semplifico la vita ?.
In che altri contesti si può usare lo SWITCH ?
#24 da Giovanni Bernardo il 27 novembre 2009
Ecco vedi, con un po di sforzo i problemi si risolvono sempre :).
Lo switch si può usare in tutti i contesti in cui una singola variabile (PORTA in questo caso) può assumere più di due valori (fino a due soli valori si può usare l’if, ma anche lo switch). Se hai capito bene il concetto di come funziona lo switch, capisci anche che non lo puoi usare per testare una singola porta: ogni pin preso singolarmente sarebbe una variabile, nel tuo caso 3 variabili: quindi non le puoi testare tutte e 3 con un unico switch… In questo caso devi per forza ricorrere a 3 if, per rendere piu leggibile il codice si usa lo switch, ma per forza di cose in questo caso, potendo operare su una sola variabile, devi metterci per forza dentro tutto il banco di porte A. Io ti ho illustrato un sistema per mascherare le porte che non vuoi considerare, che torna utile proprio in contesti come questo.
#25 da bmx88 il 17 marzo 2010
Ciao , la tua guida è veramente bella ma non capisco perche mi succede sempre quasta cosa
Quando compilo (l’ho provato su due pc diversi)
mi da questo errore
Error [1098] C:\****\lcd.c; 248. conflicting declarations for variable “_DelayMs” (C:\****\delay.c:12)
non ho modificato niente,
nei precedenti esempi ad esempio mi dava un errore simile
definendo
#include “delay.c”
ho risolto con
#include “delay.h”
uso lo stesso pic 16f877 ma da lo stesso problema con il 16f84
uso vista sarà quello il problema.
Ciao e grazie in anticipo
#26 da Giovanni Bernardo il 17 marzo 2010
Devi includere delay.c e non delay.h, altrimenti non hai disponibile la funzione DelayMs ma solo quella DelayUs. Non arrivo a capire dove ti da l’errore… In lcd.c riga 248? E quindi riga 12 di delay.c
Ma non puo darti errore alla riga 248 di lcd.c, non ha senso, devi aver per forza modificato qualcosa se ti da l’errore li, scarica di nuovo l’esempio, non modificare nulla e compilalo per pic16f877a e vedi se ti da ancora l’errore, non è un errore causato da vista, c’è qualche problema nel codice (E’ come se DelayMs venisse dichiarato due volte), ma quello distribuito qui l’ho ricontrollato ed è ok, vedi bene il tuo.
#27 da bmx88 il 18 marzo 2010
ad esempio i sorgenti della prima lezione mi da errore in compilazione
Error [237] C:\Users\Pasquale\Desktop\PIC\Altro\delay.c; 12. function “_DelayMs” redefined
solo se cambio delay.c in delay.h compila e esegue correttamente.
Sicuramente non è un problema di codice , ma forse qualche impostazione di MPLAB?
#28 da bmx88 il 18 marzo 2010
Ok risolto , il mio problema è che aggiungevo in fase di creazione del progetto anche i file delay.c ecc. (abituato ad Eclipse o Visual cpp)
Quindi devo aggiungere solo il main , qualsiasi header o file c accessorio faccia?
Ciao e grazie
#29 da Giovanni Bernardo il 18 marzo 2010
Ecco… se seguivi le lezioni dall’inizio lo capivi subito. Devi includere solo main nel progetto e basta. Gli altri file vengono inclusi dal main con gli “include”
#30 da Livio il 7 giugno 2010
Ciao Giovanni, mi associo alla miriade di persone che ti fanno i complimenti per il sito, e per il corso sulla programmazione dei PICMicro, io sono arrivato alla lezione n..7 e ho riscontrato un problema con l’uso del display RC162051YFHLYB della APEX (non so se questi display siano di buona qualità o meno, comunque “funzionano”), quando ho caricato il programma “HELLO WORLD” il dispettoso faceva solo la sua inizializzazione interna e si fermava lì. Se invece caricavo i programmi dove si definivano dei caratteri con il comando CUSTOMCHAR funzionava tutto. Poi con un colpo di “Genio” (leggi errore di programmazione) ho scoperto che inserendo questa linea nel main , cioè:
………..
20 LCD_INIT();
21 DelayMs(100);
22 LCD_CUSTOMCHAR(bb,0,0,0,0,0,0,0,0,); // linea inserita per far funzionare il display
23 LCD_CLEAR();
………………………………
il display funzionava.
Pensando che fosse un problema di temporizzazione ho provato a inserire dei ritardi e a variare i tempi del file lcd.c, anche consultando il data sheet del display (tieni conto che io l’inglese lo fischio alla perfezione ma non so ne leggerlo ne scriverlo) non mi sembra che sia diverso dagli altri. Comunque ora funziona, ma mi è rimasta una domanda che non mi fa dormire la notte BECAUSE, WHY, PERCHE’ ???????
Non so se a altre persone è successo questo problema, ma se tu sai rispondere a questo quesito potrebbe essere utile anche ad altri (oltre a farmi dormire la notte) .
Saluti
Livio
#31 da Giovanni Bernardo il 7 giugno 2010
I display Apex sono buoni e il problema che hai non me lo so spiegare… prova a mettere un altro delay al posto dell’istruzione per il customchar, perchè alla fine non ha senso…
#32 da Livio il 11 giugno 2010
Ciao Giovanni, seguendo il tuo consiglio ho provato a sostituire l’istruzione customchar con il delay, ma il risultato non cambia, ho pure provato a mettere altre istruzioni tipo putch o puts o ancora putun, però l’unico comando che fa funzionare il display e il customchar. Come dici tu non ha senso, però ti assicuro che è così, i due display Apex
che ho funzionano solo in questo modo. Io ho scaricato i tuoi file EXE e ho usato la freedom due con il pic 16f877a mettendo il display in dotazione alla scheda di sviluppo o una di un tipo qualsiasi il tutto funziona ma mettendo le due dispettose si vedono solo i quadratini dei caratteri appena accennati, e anche regolando il trimmer del contrasto, questi diventano neri ma niente di più. A questo punto incomincio a pensare a un difetto di fabbrica, voglio provare a acquistare un’altro display di questi da un’altro centro di distribuzione di materiale elettronico e poi ti faccio sapere.
Saluti
Livio
#33 da Giovanni Bernardo il 11 giugno 2010
boh… non ti saprei dire… ma non è la prima volta che mi capitano cose strane
#34 da imugno il 13 luglio 2010
anche questo è un gran bel tutorial!! Mi sai dire però perchè se aumento la velocità di un animazione diminuendo il valore di delay di ogni ciclo non si vede quasi piu nulla? Il pacman diventa una linea verticale!!
#35 da Giovanni Bernardo il 13 luglio 2010
Se tieni conto che il carattere deve essere cancellato e poi ridisegnato in un’altra posizione è ovvio che se lo fai troppo velocemente l’immagine non ha il tempo per rimanere bene impressa nell’occhio e quindi non la vedi completa.