Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Prima parte
n° 252 - Giugno 2006
L’ambiente di sviluppo
Seconda parte
n° 253/254 - Luglio/Agosto 2006
MikroC:
Controllare le uscite del PIC
Terza parte
n° 255 - Settembre 2006
Gestione di pulsanti, tastiere
By Example:
e display LCD
altri linguaggi ad alto livello (Basic o Pascal), plesse in pochissimo tempo, come verrà
permette di scrivere programmi complessi in mostrato in questa serie di articoli.
maniera semplice e veloce, però rispetto a que- Nel prossimi paragrafi analizzeremo in dettaglio
sti produce un codice mediamente più compat- le principali caratteristiche dell’ambiente di svi-
to e veloce, simile a quello che si otterrebbe luppo.
programmando in assembler. Il C quindi per-
mette di sfruttare meglio le caratteristiche del Il compilatore
microcontrollore, e di controllare più accurata- Il MikroC comprende un compilatore ANSI C
mente il suo funzionamento e le sue periferiche. che implementa praticamente tutti gli aspetti
L’ambiente
di sviluppo di Antonio Di Stefano
Teoria
point, utilizzando per questi ultimi un formato a i diversi elementi (istruzioni, costanti, com-
32 bit compatibile con lo standard IEEE-754. In menti, tipi, etc.). Questo facilita molto la let-
quest’ultima versione è possibile richiamare le tura e la comprensione del codice, e può evi-
funzioni in maniera annidata e ricorsiva (nei denziare la presenza di eventuali errori di
limiti consentiti dallo stack del PIC). Per rendere scrittura. Esiste anche una funzione persona-
più efficiente il codice generato, il MikroC appli- lizzabile che corregge gli errori di digitazione
ca una serie di ottimizzazione automatiche in direttamente mentre si scrive il testo (!). Altre
fase di compilazione. funzioni utili sono quelle che permettono di
Oltre agli aspetti standard del linguaggio, il commentare o de-commentare le sezioni di
compilatore è dotato di alcune estensioni dedi- codice evidenziato, o di indentarlo.
cate, utili per interagire con i PIC. Ad esempio è Due strumenti utili mentre si scrive il codice
possibile gestire in maniera molto semplice le sono il “Code Assistant”, ed il “Parameter
routine d’interruzione o la posizione delle varia- Assistant”: due piccole finestre “pop-up” che
bili all’interno della memoria. servono a ricercare o a completare automati-
camente il nome delle
funzioni che si vuole
richiamare, o i loro para-
metri, evitando di consul-
tare continuamente la
guida o altri punti del
codice.
Sulla sinistra (Figura 2) si
trova il “Code Explorer”,
dove vengono riassunti
FARE ELETTRONICA - GIUGNO 2006
utilissimo sia per trovare velocemente gli ele- (usata in fase di simulazione e per determina-
menti nel codice, sia per evitare errori nel- re il valore di alcune costanti), e l’elenco dei
l’uso delle variabili globali, o con le ri-defini- files che compongono il progetto.
zioni e l’inizializzazione delle variabili. In basso trova posto la finestra dei messaggi,
Il tab posto accanto, denominato Qhelp, in cui vengono visualizzati i risultati di compi-
mostra un elenco di tutte le funzioni di libre- lazione e gli eventuali messaggi di errore.
ria integrate nel compilatore (sia quelle stan- Nella stessa zona è presente un pratico con-
dard del C che le librerie per le funzioni vertitore di dati decimali / binari / esadecima-
avanzate). Cliccando su una delle voci si apri- li, chiamato “Qconvertor”.
rà la guida in cui la funzione viene descritta
in dettaglio, spesso anche con degli esempi I tool aggiuntivi
di utilizzo. Come accennato prima, il MikroC offre una
Il piccolo riquadro sottostante riassume le grande quantità di strumenti aggiuntivi oltre a
proprietà del progetto corrente: il modello di quelli strettamente indispensabili per scrivere
PIC da utilizzare, la sua frequenza di lavoro il codice e compilarlo. Questi tool possono
aiutare moltissimo nella fase di creazione dei
82
programmi e nei test, e risulta molto comodo
Teoria
Teoria
Tra gli altri tools meritano una segnalazione
quello per creare immagini per display grafici
(Fig. 6), che tra i display annovera anche il
Nokia 3110, quello per gestire il bootloader,
per la formattazione dei dati della EEPROM, e
Figura 4 Editor per display a 7 segmenti
per la programmazione del micro via USB.
Le librerie
Uno degli aspetti più interessanti del MikroC è
che comprende un grandissimo numero di
librerie già pronte che implementano funzioni
complesse. Sarebbe troppo lungo descriverle
tutte, quindi qui ne daremo solo una veloce
panoramica (le utilizzeremo comunque nelle
prossime puntate). Chi desiderasse informazioni
più dettagliate può consultare la documentazio-
ne del MikroC, che è scaricabile dal sito del pro-
Figura 5 L’USART Terminal
duttore. Una prima classe di funzioni sono quel-
le per la gestione dell’hardware del PIC. In que-
sta classe sono comprese funzioni per la gestio-
ne della UART (sia hardware che emulata via
software), del generatore PWM e del convertito-
re Analogico/Digitale. Un'altra classe implemen-
ta algoritmi per la gestione di hardware esterno
FARE ELETTRONICA - GIUGNO 2006
zione dei pin, 0 indica che sono stati configura- automaticamente a includere le definizioni rela-
ti tutti come uscite). A questo punto inizia un tive al PIC usato (come PORTB e TRISB), e diver-
ciclo infinito realizzato con l’istruzione while. se funzioni di libreria.
Dentro al ciclo viene assegnato il valore 1 a Per compilare il nostro programma, usiamo il
PORTB, cioè viene portato alto il piedino RB0. pulsante Build Project (quello con gli ingranag-
Quindi viene richiamata una routine che genera gi in alto), o l’equivalente voce del menu
un ritardo di 500ms (mezzo secondo), viene Project. Il report di compilazione sarà visibile
portato basso il piedino RB0, e vengono attesi nella finestra in basso.
altri 500ms, quindi il loop si ripete. A questo Se diamo un’occhiata alle statistiche sull’occu-
punto è utile una piccola spiegazione: per capi- pazione di memoria vediamo che il nostro pro-
re su quale piedino della porta B agiamo, dob- grammino occupa 74 word nella Flash del PIC.
biamo considerare l’espressione binaria del Proviamo a scriverlo in un modo un po’ più
numero che abbiamo utilizzato, ciascun bit rap- ottimizzato:
presenta ordinatamente un piedino della porta.
Se avessimo voluto accendere i pin RB0 ed RB1 void main() {
assieme (valore binario 00000011), avremmo PORTB = 0;
dovuto usare il valore decimale 3. Per facilitare TRISB = 0;
questo tipo di operazioni il MikroC riconosce while(1) {
anche i numeri scritti direttamente in binario, PORTB = PORTB^0b00000001;
Delay_ms(500);
}
}
Teoria
PORTB = PORTB^0b00000011; • Alcune spiegazioni più dettagliate sugli algo-
Delay_ms(500); ritmi e sui circuiti utilizzati in alcuni degli
} esempi (compresa la scheda EasyPIC) si posso-
} no trovare nel tutorial sul MikroBasic, pubbli-
cato su Fare Elettronica (dal numero 238).
Abbiamo modificato soltanto due parametri: il
valore iniziale (all’inizio un LED sarà già acce- CONCLUSIONI
so, l’altro spento), ed abbiamo fatto in modo Nella prossima puntata considereremo degli
che venissero invertiti entrambi i bit meno esempi un po’ più complessi, che partendo da
significativi. quelli appena visti ne espanderanno molto le
possibilità utilizzando istruzioni e costrutti più
Se vogliamo provare i nostri programmi con il potenti, per gestire il flusso del programma e le
debugger, possiamo richiamare la voce “Start temporizzazioni. Non mancate!
Debugger” dal menu Run, ed usare le opzioni
di step (stesso menù, oppure tasti F7 ed F8). Codice MIP252080
Se invece vogliamo prova-
re il codice direttamente
sul circuito vero e proprio,
dopo la compilazione avre-
mo a disposizione il file
.hex da caricare nel PIC.
Potremo usare lo stesso
MikroC se stiamo usando
una delle schede EasyPIC
FARE ELETTRONICA - GIUGNO 2006
Prima parte
n° 252 - Giugno 2006
L’ambiente di sviluppo
Secondo parte
n° 253/254 - Luglio/Agosto 2006
MikroC
Controllare le uscite del PIC
Terza parte
n° 255 - Settembre 2006
Gestione di pulsanti, tastiere
by Example:
e display LCD
I n questa puntata scopriremo siderare, dal momento che ciascuna di esse può
adattarsi meglio a specifiche applicazioni.
come scrivere in C degli Supponiamo ad esempio di utilizzare 8 LED,
algoritmi dedicati alla gestione ciascuno collegato ad un piedino della porta B
come mostrato in figura 2, e di volerli accende-
delle uscite dei PIC,
re in sequenza nelle due direzioni (il classico
per comandare LED, display effetto “supercar”). Le alternative più conve-
ed altri dispositivi, utilizzando nienti sono due: in un caso possiamo utilizzare
104
gli operatori del C che permettono di manipo-
le tecniche più efficienti
Teoria
GENERAZIONE DI PATTERN
E SEQUENZE
Nella scorsa puntata abbiamo mostrato il codi-
ce per fare lampeggiare un LED collegato alla
porta RB0 del PIC. Per comodità riportiamo in
figura 1 lo schema elettrico del circuito e di
seguito il codice utilizzato:
PORTB = 0;
TRISB = 0;
while(1) {
PORTB = PORTB^0b00000001;
Delay_ms(500);
}
FARE ELETTRONICA - LUGLIO/AGOSTO 2006
una configurazione delle uscite, ed otteniamo porta B sono state configurate tutte come usci-
le altre operando sui bit. Il codice è il seguente: te (TRISB=0), e soltanto il primo piedino è stato
posto alto (PORTB=0x01). Ricordiamo che il
void main() { MikroC permette di esprimere i valori numerici
char dir; anche in binario (anteponendo “0b” al nume-
ro), ma abbiamo preferito utilizzare la notazio-
/* Direzione di scorrimento ne esadecimale per rendere il codice maggior-
1=sinistra, 0=destra */ mente portabile. Per convertire questi valori in
105
dir=1; binario si può utilizzare il convertitore
Teoria
Qconvertor, che si trova in basso nella finestra
// Inizializz. porta B del messaggi del MikroC. All’interno del loop
PORTB = 0x01; principale viene dapprima verificato se il LED
TRISB = 0; attualmente acceso è il primo o l’ultimo, e in
ciascuno di questi due casi viene cambiata la
// Loop infinito direzione dello scorrimento. Per eseguire que-
while(1) { sto controllo è stata utilizzata l’istruzione if del
C: solo se la condizione dentro le parentesi è
// Raggiunti bordi? verificata l’espressione che segue vene esegui-
if (PORTB&0x01) dir=1; ta. L’espressione che viene controllata è l’AND
if (PORTB&0x80) dir=0; binario tra i bit della porta B e 0x01 (oppure
0x08). Questa espressione darà 0x01 solo se il
// Aggiornamento direzione bit meno significativo della porta B sarà alto (lo
if (dir) { stesso per il più significativo nel caso di 0x80),
PORTB = PORTB << 1; altrimenti zero. Per maggiore chiarezza avrem-
} else { mo potuto scrivere:
PORTB = PORTB >> 1;
} if ((PORTB&0x01)==0x01) dir=1;
if ((PORTB&0x80)==0x80) dir=0;
Delay_ms(100);
} ma ricordiamo che il C considera vera qualsiasi
espressione che non valga 0, quindi anche non
FARE ELETTRONICA - LUGLIO/AGOSTO 2006
}
indicando il valore atteso otteniamo lo stesso
Il funzionamento del programma dovrebbe risultato. Abbiamo usato lo stesso accorgimen-
risultare abbastanza intuitivo: inizialmente to per il frammento di codice successivo, che è
viene dichiarata una variabile (dir) per tenere quello che si occupa dell’aggiornamento della
traccia della direzione di scorrimento, in segui- posizione. Se la variabile dir vale 1 viene esegui-
to vengono inizializzate le variabili e le porte, e to uno scorrimento binario di una posizione a
poi viene eseguito il loop principale. Durante il sinistra (a destra nell’immagine), altrimenti
funzionamento la variabile dir assumerà soltan- (else) viene eseguito uno scorrimento a destra
to due valori (scelti da noi), quindi è conve- (a sinistra nell’immagine). Gli scorrimenti (ope-
niente dichiararla del tipo più piccolo possibile ratori “<<” e “>>” del C) produrranno la
gestito dal C, cioè char (8 bit). Le linee della sequenza di valori: 0x01, 0x02, 0x04, 0x08,
TEORIA RISORSE SPECIALE PRATICA
0x10…, 0x80, e poi a ritroso (quando cambie- dichiarazione dell’array. Inoltre abbiamo dichia-
rà la direzione di scorrimento) fino a 0x01. rato un’altra variabile (n) che verrà utilizzata
Dopo ogni scorrimento attendiamo 100ms come contatore, cioè come indice per scorrere
usando l’apposita routine di libreria Delay_ms, la tabella. Nel loop principale assegniamo diret-
messa a disposizione dal MikroC, e ripetiamo tamente il valore corrente della tabella alla
l’intera routine, all’infinito. Consideriamo porta B, inoltre incrementiamo l’indice n (con
adesso un altro approccio per ottenere lo stes- l’istruzione n++). Quando l’indice raggiungerà
so risultato. In questo caso utilizzeremo una il valore 14, sarà riportato a 0, e quindi il con-
look-up table per memorizzare le configurazio- teggio ripartirà da questo valore. Notare la dif-
ni delle uscite che vogliamo ottenere. Il codice ferenza tra “==” ed “=” nell’istruzione if.
è il seguente: Ricordiamo che il primo è un operatore relazio-
nale, che controlla se il valore dell’espressione
void main() { di sinistra è uguale a quello dell’espressione di
char n=0; destra (restituendo un valore di verità). L’altro
char leds[14]={0x01, 0x02, operatore invece assegna un valore ad una
0x04, 0x08, 0x10, 0x20, variabile.
106
0x40, 0x80, 0x40, 0x20, Questa seconda versione del programma, seb-
Teoria
occorrono soltanto 14 voci per la tabella, che mico e funzionale dispositivo di visualizzazione.
sono state inizializzate direttamente nella Vedremo quindi in questo paragrafo come uti-
Figura 3 Schema di un display a catodo comune Figura 4 Schema di un display ad anodo comune
Codice MIP 253107
TEORIA RISORSE SPECIALE PRATICA
Teoria
display: se vogliamo visualizzare un carattere Il codice somiglia molto a quello visto in prece-
sul display più a sinistra, dovremo inviare il denza, le uniche differenze riguardano l’utilizzo
codice del carattere sulla porta B e portare alto di un altro array (cifra[…]), che contiene le cifre
soltanto RA0. Ovviamente soltanto un display da visualizzare nei 4 display, e l’impiego della
alla volta potrà essere acceso. Occorre quindi porta A per selezionare il display. Il loop princi-
accenderli in successione ad una velocità tale pale contiene un ciclo for, che viene ripetuto
da non farne percepire all’occhio lo spegni- per 4 volte (una per ogni cifra), al cui interno
mento. Per ottenere questo effetto è sufficiente viene impostato il valore della cifra corrente
accendere ogni cifra almeno ogni 20ms. Dal sulla porta B, ed aggiornato il contenuto della
momento che le cifre sono 4, dovremo tenerle porta A. In pratica all’inizio la porta A conterrà
accese singolarmente meno di 5ms. Per evitare il valore 0b0001, alla porta B viene assegnato il
un effetto di “sfarfallamento” possiamo anche valore adatto a rappresentare la prima cifra, si
usare una velocità maggiore (senza esagerare, attende 2ms, al valore della porta A viene appli-
altrimenti otterremo una bassa luminosità). cato uno scorrimento a sinistra di un bit, otte-
Riassumendo: nendo 0b0010, ed il ciclo for riprende con la
• Sulla porta B dovranno essere inviati ciclica- seconda iterazione, in cui viene assegnato alla
mente i valori corrispondenti alle 4 cifre che porta B il codice per la seconda cifra. Si prose-
vogliamo visualizzare. gue così fino alla quarta, e quindi si esce dal
• Sulle porta A dovrà essere portata alta una ciclo for, ma non dal loop principale, che si
sola linea alla volta, quella corrispondente alla ripeterà all’infinito. Sul display dovrebbero
cifra da visualizzare (avremo quindi ciclica- apparire le cifre 1234 indicate nell’array cifra.
mente 0b0001, 0b0010, 0b0100, 0b1000). A questo punto potremo pensare di sfruttare il
FARE ELETTRONICA - LUGLIO/AGOSTO 2006
void main() {
char n, ds, val; vare il bit più significativo della porta B.
char segs[16]={0x3F, 0x06, Questo può essere ottenuto eseguendo un OR
0x5B, 0x4F, 0x66, 0x6D, (operatore “|” del C) tra il codice del carattere
0x7D, 0x07, 0x7F, 0x6F, attualmente visualizzato ed il valore binario
0x77, 0x7C, 0x39, 0x5E, 0b10000000 (cioè 0x80 esadecimale):
0x79, 0x71}; if (punto) PORTB=PORTB|0x80;
char cifra[4];
TIMER ED INTERRUZIONI
val=-47; Il precedente esempio ha mostrato come sia pos-
sibile utilizzare un display a 7 segmenti per visua-
// Inizializz. porte lizzare il contenuto di una variabile. Come abbia-
mo visto per ottenere una buona visualizzazione prestabiliti. Nel nostro caso il codice all’interno
delle 4 cifre è necessario rispettare delle precise della routine dovrà aggiornare il display un digit
temporizzazioni. Risulta quindi piuttosto difficile alla volta. Occorrerà quindi impostare il timer ed
aggiungere altre funzioni al programma visto il suo prescaler in modo da generare un interrupt
prima, perché qualsiasi altro compito inserito nel ogni 2ms. Per abilitare le interruzioni associate al
loop principale altererebbe le temporizzazioni del TMR0 dobbiamo impostare ad 1 i bit GIE e T0IE
display, e risulterebbe a sua volta rallentato dai del registro INTCON, ed abilitare il prescaler col
tempi di attesa utilizzati per il display. Per risolve- fattore di divisione voluto sul registro
re questo problema è necessario separare e rende- OPTION_REG (per maggiori dettagli si veda il
re indipendenti le temporizzazioni e le funzioni di datasheet del PIC o il tutorial “PIC By Example”
gestione del display dalla normale esecuzione del già pubblicato su Fare Elettronica).
programma: questo può essere ottenuto utiliz- Se abbiamo una frequenza di clock di 4MHz, pos-
zando il timer del PIC e le interruzioni. siamo ottenere un’interruzione ogni 2ms usando
Il meccanismo è molto semplice: il PIC ha un un fattore di divisione pari a 8 (infatti
timer ad 8 bit (chiamato Timer0 o TMR0) che 4*256*8/4MHz=2ms).
conta da 0 ad 0xFF (in totale 256 valori), ed è Dopo avere impostato il corretto valore nei regi-
111
incrementato ad ogni ciclo macchina (4 cicli di stri, dobbiamo scrivere la routine di gestione delle
Teoria
clock) o suoi multipli. interruzioni. Per fare questo sarà sufficiente creare
Quando il valore del timer supera 0xFF, può esse- una funzione chiamata “interrupt”, il MikroC la
re generata un’interruzione. Utilizzando il timer è riconoscerà come routine di gestione delle inter-
quindi possibile richiamare un’apposita funzione ruzioni, e la richiamerà automaticamente in caso
(la routine d’interruzione) a intervalli di tempo di interruzioni. Il codice risultante è il seguente:
Software MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
FARE ELETTRONICA - LUGLIO/AGOSTO 2006
✔ Debugger
✔ Statistiche
Tutto in un ambiente
Windows facile ed intuitivo
Teoria
come si vuole l’array cifra[], ed il display ma puntata verranno presentate le routine in C
sarà aggiornato di conseguenza ed in per la gestione di dispositivi di input quali pulsan-
maniera automatica. ti, tastiere di varo tipo, e display LCD intelligenti.
Ad esempio si può realizzare un conteggio
inserendo nel loop il seguente codice: Codice MIP 253104
Scheda easyPIC3
La rivoluzionaria scheda
di sviluppo per PICmicro
✔ Programmatore USB2.0 on-board
✔ Tastiera a 32 tasti
✔ 32 LED per il monitoraggio degli I/O
✔ 4 cifre LED a 7 segmenti
✔ Predisposizione per moduli LCD alfanumerici
✔ Predisposizione per moduli LCD grafici
FARE ELETTRONICA - LUGLIO/AGOSTO 2006
Secondo parte
n° 253/254 - Luglio/Agosto 2006
Controllare le uscite del PIC
Terza parte
n° 255 - Settembre 2006
MikroC
Gestione di pulsanti, tastiere
e display LCD
Quarta parte
n° 256 - Ottobre 2006
by Example:
Generazione di segnali PWM
Gestione di
pulsanti, tastiere
e display LCD di Antonio Di Stefano
Teoria
sione del tasto e genera un segnale che può
Se carichiamo il programma sul PIC e proviamo oscillare diverse volte tra livello alto e livello
a premere un tasto, potremo osservare un com- basso prima di stabilizzarsi.
portamento diverso da quello atteso: il LED si Queste oscillazioni durano tipicamente alcuni
accenderà e si spegnerà in continuazione men- millisecondi e possono variare a seconda dalle
tre il tasto rimane premuto, ad una velocità tale caratteristiche meccaniche del pulsante.
da non vederne neanche il lampeggio, e sarà Vediamo come affrontare questo problema con-
impossibile fermarlo in uno stato prestabilito. siderando un circuito (figura 2) ed un program-
Qual è il problema? Dobbiamo ricordarci che ma un po’ più completo.
l’esecuzione del programma sul PIC è estrema- Nel circuito un display a 7 segmenti è collegato
mente più veloce di qualsiasi nostra azione, di alla porta B del PIC, mentre due pulsanti sono
conseguenza, anche premendo brevemente il collegati alla porta A. Quello che vogliamo otte-
pulsante, il LED verrà acceso e spento migliaia di nere è che ad ogni pressione del pulsante S1 il
volte! Un primo accorgimento per evitare que- numero sul display venga incrementato di uno,
ste ripetizioni consiste nell’attendere che il pul- mentre ad ogni pressione di S2 il conteggio
sante venga rilasciato prima di ripetere il ciclo. venga decrementato. Ecco il codice:
In questo modo dovremo effettivamente pre-
mere due volte il pulsante per accenderlo e spe- void main() {
gnerlo. Il codice è il seguente: signed char cont=0;
char segs[16]={0x3F, 0x06,
void main() { 0x5B, 0x4F, 0x66, 0x6D,
// Inizaliz. porta B 0x7D, 0x07, 0x7F, 0x6F,
TRISB = 0x06; 0x77, 0x7C, 0x39, 0x5E,
FARE ELETTRONICA - SETTEMBRE 2006
su entrambi, per questo è stato utilizzato il valo- re separatamente le righe e le colonne della
re 0x03 nell’AND). Infine viene corretto il valo- tastiera. In questo modo è possibile gestire 16
re del conteggio se questo supera 9 o scende tasti utilizzando soltanto 8 I/O! Lo schema è
sotto 0 (per questo motivo la variabile di con- quello mostrato in figura 3, ed è comunemente
teggio è stata dichiarata come signed char). utilizzato in diversi dispositivi commerciali. I pie-
Provando il programma si può notare lo stesso dini da RB0 a RB3 sono configurati come uscite,
difetto visto prima: ad ogni pressione si posso- e pilotano le colonne della tastiera.
no avere variazioni del conteggio maggiori di 1. I pin da RB4 a RB7 sono configurati come
Occorre infatti risolvere ancora il problema dei ingressi e vengono utilizzati per leggere il
rimbalzi. Un metodo banale per fare questo valore presente sulle 4 righe. Quando i tasti
consiste nell’inserire un’attesa di qualche decina vengono premuti, cortocircuitano una riga
di millisecondi alla fine del loop, come segue: con una colonna. Dal momento che le uscite
… vengono attivate una alla volta (come accade-
Delay_ms(50); va con i display a 7 segmenti), leggendo il
} valore delle righe è possibile sapere quale
} tasto è premuto. Ad esempio, all’inizio della
scansione RB3-RB0 varranno
0b0001, quindi sarà selezionata
la prima colonna. Se leggiamo
0b0100 su RB7-RB4 significa
che il tasto premuto è T9.
Scrivere una routine per la let-
tura di una tastiera potrebbe
FARE ELETTRONICA - SETTEMBRE 2006
Teoria
} re, etc.) sono preceduti da un codice 0xE0.
// Oppure: Anche in questo caso non sarà necessario scrive-
// attende la pressione re a mano le routine di gestione, perché il
c=Keypad_Release(); MikroC mette a disposizione delle funzioni già
… pronte che rendono estremamente semplice
Compilatore MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
✔ Debugger
FARE ELETTRONICA - SETTEMBRE 2006
✔ Statistiche
Tutto in un ambiente
Windows facile ed intuitivo
l’uso di questi dispositivi. Le funzioni che utiliz- identica a quella vista in precedenza, le uniche
zeremo sono Ps2_Init e Ps2_Key_Read. differenze risiedono nella chiamata alle due fun-
Queste funzioni restituiscono le informazioni sui zioni che gestiscono la tastiera. Inizialmente è
tasti premuti, e gestiscono anche la conversione stata richiamata la funzione di inizializzazione,
da scan code ad ASCII. indicando che la tastiera è collocata sulla porta
Per effettuare una prima prova consideriamo lo A. All’interno del loop principale viene richiama-
schema di figura 4, in cui un display a 7 seg- ta la funzione Ps2_Key_Read. Questa funzione
menti è collegato alla porta B del PIC, mentre la restituisce 1 se è stato premuto o rilasciato un
tastiera è collegata alle linee RA0 ed RA1 della tasto, oppure 0 in caso contrario.
porta A. Nel primo caso le informazioni sul tasto saranno
Il programma che segue legge i dati inviati dalla contenute nelle tre variabili, che vengono pas-
tastiera e visualizza sul display il carattere corri- sate per riferimento (e che quindi vengono
spondente se questo è un numero oppure una modificate dalla funzione). La variabile key con-
lettera da A ad F. tiene il codice ASCII del tasto premuto o rilascia-
to, la variabile special vale 1 se è stato premuto
void main() { un tasto “speciale” (e che quindi key non con-
92
unsigned short key, special, down; tiene un valido codice ASCII). La variabile down
Teoria
if ((key>='A')&&(key<='F'))
tasto=key-'A'+10;
}
}
PORTB=segs[tasto];
Delay_ms(20);
}
}
2006
un tantino laboriosa. Anche in questo caso il
MikroC ci viene incontro fornendoci delle fun-
zioni di libreria già pronte che permettono di
utilizzare in modo molto semplice ed intuitivo MILANO 20-23 SETTEMBRE
questo tipo di display. Le funzioni permettono
di visualizzare sul display delle stringhe di testo
o dei caratteri, indicandone le coordinate inizia-
li se desiderato. 32a BIENNALE INTERNAZIONALE
Vediamo subito un semplicissimo esempio, che DELL’AUTOMAZIONE, STRUMENTAZIONE,
applicato allo schema di figura 5, visualizza sul MICROELETTRONICA E
display la stringa “Fare Elettronica!” disposta su ICT PER L’INDUSTRIA
due righe:
void main() {
char *testo1 = “Fare”; Registrati on-line all’indirizzo
char *testo2 = “Elettronica!”;
www.fieremostre.it/prebs
TRISB = 0x00;
Lcd_Init(&PORTB); e riceverai un’email che,
Lcd_Cmd(LCD_CLEAR);
Lcd_Out(1,1, testo1);
presentata alle reception
Lcd_Out(2,5, testo2); dei Padiglioni 11-9 e
while(1) {}
} 18 di Fiera Milano,
ti permetterà di
Dapprima viene inizializzato il display sulla
porta B, in seguito viene inviato un comando ritirare la tessera
per pulire lo schermo (i comandi disponibili
gratuita di accesso
sono parecchi, e si rimanda al manuale del
MikroC per un elenco completo), ed infine ven-
gono stampate le due stringhe, la prima nella
posizione iniziale (in alto a sinistra), la seconda
nella riga sottostante, spostata di 5 caratteri dal
Siamo presenti al
bordo sinistro.
Mettendo assieme quello che abbiamo impara-
to fino ad ora, possiamo realizzare un’applica-
padiglione 9
stand S15
zione leggermente più complessa, che permet-
te di apprezzare la versatilità delle funzioni di
libreria viste: proviamo a collegare al PIC una
tastiera PS/2 ed un display LCD, e creare un e abbiamo riservato
programma che ci permetta di scrivere sul
display tramite la tastiera, come avviene di soli-
to sullo schermo di un normale computer. Lo
un omaggio
schema da considerare è quello di figura 5, a
cui la tastiera può essere collegata alla porta A
per i nostri abbonati
del PIC, come visto in figura 4.
void main() {
char x, y;
unsigned short key, special, down;
ACCORRETE
NUMEROSI!
DISTEFANO - MIKROC 3pt C 31-07-2006 17:54 Pagina 94
Teoria
santi si è stabilizzato, e quindi possiamo con- te. Il codice che segue mostra la tecnica
siderare il loro valore valido. descritta applicata allo schema di figura 2, in
Una volta utilizzato il valore dei pulsanti, cui i pulsanti controllano l’incremento o il
azzeriamo il contatore in modo da prepararci decremento del numero visualizzato sul
alla successiva pressione. La nostra routine in display a 7 segmenti.
while(1) { tasti=PORTA;
// Aggiorna display }
PORTB=segs[cont]; // Reset timer e flag
// Controlla polsanti TMR0 = 0;
if (tpress>200) { INTCON = 0x20;
if (tasti&0x02) cont++; }
Rispetto al codice mostrato prima le differenze estesa a più pulsanti su più porte, e può essere
sono minime, e consistono nell’impiego della integrata con la routine di gestione del display
routine d’interruzione e delle variabili tpress, vista nella scorsa puntata (o con altre che richie-
FARE ELETTRONICA - SETTEMBRE 2006
che viene usata come contatore per lo stato dei dano simili tempistiche).
pulsanti, e la variabile tasti, che è in pratica una
copia della porta A. Come si può vedere quan- CONCLUSIONI
do viene rilevata una transizione (variabile tasti Nella prossima puntata vedremo come genera-
è diversa dal valore di PORTA), il valore del con- re con il PIC ed il MikroC dei segnali PWM e
tatori riparte da 180 e non 0, quindi per rag- come utilizzarli per delle interessanti applicazio-
giungere la soglia (200) impiegherà minor ni. Vedremo anche come generare del suoni e
tempo rispetto a quando il valore viene utilizza- melodie con il PIC. Non mancate!
to (tptress è riportato a 0).
Va notato che la routine può essere facilmente Codice MIP 255088
DISTEFANO - MIKROC 4pt C 13-09-2006 9:43 Pagina 92
Terza parte
n° 255 - Settembre 2006
Gestione di pulsanti, tastiere
e display LCD
Quarta parte
n° 256 - Ottobre 2006
MikroC
by Example:
Generazione di segnali PWM
Quinta parte
n° 257 - Novembre 2006
Realizzazione di un timer
digitale programmabile
modulazione PWM (Pulse Width Modulation, ossia implementare questo meccanismo in C, utilizzan-
modulazione a larghezza di impulsi), che consen- do diverse tecniche.
te appunto di generare dei segnali analogici par-
tendo direttamente da segnali digitali.
L'idea è la seguente: si utilizza un'onda quadra, di
solito a frequenza costante, scegliendo opportu-
namente il tempo in cui essa si mantiene a livello
alto in ciascun periodo. Questo tempo è quello in
cui in ogni ciclo effettivamente forniamo energia
Figura 1 Generazione di un segnale PWM
al dispositivo collegato, nel tempo rimanente
DISTEFANO - MIKROC 4pt C 12-09-2006 19:25 Pagina 93
Generazione di
segnali PWM
di Antonio Di Stefano
Teoria
anche i più semplici, in quanto non si ricorre ad
alcuna periferica hardware specifica, ed è possibi- La variabile cont è usata come contatore, ed è
le avere l'uscita su qualsiasi piedino di I/O. Il quindi incrementata ad ogni iterazione. Dal
segnale PWM generato viene utilizzato nello sche- momento che è ampia 8 bit, raggiunto il limite di
ma di Figura 2 per fare lampeggiare un LED con 255 tornerà automaticamente a zero. La variabile
una variazione graduale della luminosità. Ci si level è usata come soglia. Se avessimo assegnato
potrebbe chiedere come mai non sia stato usato un valore fisso, avremo potuto ottenere un valore
un filtro passa basso. In effetti il LED è un disposi- stabile di luminosità del LED. In questo caso inve-
tivo abbastanza veloce, e non esegue affatto la ce il valore della soglia è variato progressivamen-
media del segnale, ma ne segue fedelmente il te, in modo da avere un duty cycle che inizia dallo
valore. Tuttavia il risultato che si ottiene è buono, 0% (level=0) al 100% (level=255). La soglia è
perché la media è eseguita dal nostro occhio, che incrementata ogni 200 iterazioni, in modo da ren-
ha un tempo di risposta di circa un ventesimo di dere visibile la variazione, per fare questo è stata
secondo! Il codice è riportato di seguito. utilizzata la variabile i, che serve proprio per con-
tare quante volte viene eseguito il loop.
void main() { Un paio di considerazioni importanti: quanti livel-
unsigned char cont, level, i; li di luminosità possiamo ottenere? Ben 256, cioè
tanti quanti sono i livelli del contatore PWM. Qual
TRISB = 0; è invece la frequenza della nostra onda PWM?
PORTB = 0; Qui la risposta è meno ovvia: per completare un
cont=0;
level=0;
FARE ELETTRONICA - OTTOBRE 2006
i=0;
// Loop infinito
while(1) {
if (cont>level) {
PORTB=0;
} else {
PORTB=1;
}
Figura 2 Schema per l'accensione del LED con onda PWM
DISTEFANO - MIKROC 4pt C 13-09-2006 9:44 Pagina 94
periodo è necessario che il contatore esaurisca il fatto che il segnale PWM generato ha una risolu-
conteggio, quindi serviranno ben 256 iterazioni zione di 16 livelli e non 256. Questo è stato otte-
del loop per completare un solo periodo! nuto incrementando il contatore di 16 invece che
Supponendo di utilizzare un PIC funzionante a di 1 (l'overflow si ha in 256/16=16 passi). Questo
4MHz, possiamo misurare quanto tempo impie- accorgimento, unito all'utilizzo delle interruzioni
ghiamo per eseguire un'iterazione del loop utiliz- permette di ottenere una frequenza PWM molto
zando il Debugger del MikroC, facendolo funzio- più alta.
nare in modalità step, e osservando il tempo di
esecuzione riportato in basso. Il risultato è 16us, unsigned char cont, level;
quindi 16us*256=4096us, cioè ben 4ms (244Hz)!
Giusto in tempo per non percepire un fastidioso void main() {
sfarfallio…Questo semplice calcolo mette in luce
un problema tipico del PWM: se vogliamo ottene- // Inizializz. porte
re una risoluzione alta, dobbiamo accontentarci di TRISA = 0x03;
frequenze basse, a meno di non "contare" a velo- PORTA = 0x00;
cità molto elevate (cosa non sempre possibile o TRISB = 0x00;
94
conveniente).
Teoria
// Inizializz. Registri
PWM CON INTERRUZIONI OPTION_REG = 0x80;
Uno dei problemi del codice presentato prima è TMR0 = 0;
che il periodo dell'onda PWM dipende dalla quan- INTCON = 0xA0;
tità delle istruzioni che sono presenti nel loop prin-
cipale. Ovviamente in programmi completi il loop cont=0;
sarà affollatissimo di istruzioni e routine e quindi la level=0;
frequenza del PWM risulterà bassissima e probabil-
mente non costante. Per risolvere questo inconve- // Loop infinito
niente, come abbiamo fatto in altre occasioni, pos- while(1) {
siamo utilizzare le interruzioni. Programmiamo il
timer TMR0 del PIC in modo da generare un'inter- if (PORTA&0x01)
ruzione ad intervalli regolari, ed utilizziamo la rou- level+=16;
tine di servizio per incrementare il contatore PWM if (PORTA&0x02)
ed aggiornare l'uscita. In questo caso la frequenza level-=16;
dell'onda generata sarà facile da calcolare essendo
data dalla frequenza delle interruzioni diviso il Delay_ms(100);
numero di passi del contatore. Questa frequenza }
risulterà inoltre indipendente dal contenuto del }
loop principale e dal resto del programma.
Il codice riportato di seguito implementa il meto- void interrupt()
do appena descritto: il segnale PWM viene utilizza- {
to per regolare la luminosità di un LED, il cui livel- if (cont>level) {
FARE ELETTRONICA - OTTOBRE 2006
I pin RA0 e RA1 della porta A sono impostati niente prescaler, etc.). Nel loop viene soltanto
come ingressi ed utilizzati per rilevare la pressio- rilevata la pressione di uno dei due pulsanti ed
ne dei pulsanti. La porta B è utilizzata per la aggiornato il livello, nella routine d'interruzione
generazione dell'onda PWM (sul piedino RB0). invece si trova lo stresso codice che prima era
Sono abilitate le interruzioni relative al TMR0, nel loop principale. Come già detto il contatore
ed impostati il suoi parametri (clock interno, è incrementato di 16 unità invece che di 1, per
ottenere una risoluzione di 16 livelli (4 bit). Si
sarebbe anche potuto resettare il contare stesso
una volta raggiunto il valore 16, in questo caso
anche il livello sarebbe stato espresso come un
numero compreso tra 0 e 15.
Teoria
re anche diversi altri compiti o la frequenza scel-
ta è piuttosto alta. Una soluzione molto efficien-
te è costituita dall'impiego di periferiche har-
Figura 3 Schema per controllo luminosità LED
dware apposite presenti su molti PIC. In questo
caso è sufficiente programmare il modulo appo-
Compilatore MikroC
Un potente
compilatore C
per PICmicro
Code Editor
Code Explorer
Debugger
FARE ELETTRONICA - OTTOBRE 2006
Statistiche
Tutto in un ambiente
Windows facile ed intuitivo
}
// Iniz. porte
TRISB = 0x01; La funzione Pwm_Init imposta la frequenza del-
PORTB = 0; l'onda PWM, la funzione Pwm_Start avvia la
PORTC = 0; generazione del segnale (esiste anche
TRISC = 0; Pwm_Stop per fermarlo), mentre
Pwm_Change_Duty serve per cambiare il valore
// Init. modulo PWM di duty cycle generato. Come si vede, utilizzan-
Pwm_Init(1000); // Freq. PWM 1000Hz do queste funzioni il codice risulta particolar-
Pwm_Start(); // Start PWM mente semplice. Ad ogni pressione del pulsante
viene attivato l'aggiornamento del livello (run=1)
delta=1; ed invertita la direzione d'incremento (il modo
run=0; da ottenere una rampa in salita ed in discesa in
level=255; maniera alternata). Una volta raggiunto uno dei
FARE ELETTRONICA - OTTOBRE 2006
LA SOLUZIONE
per il disegno tecnico
Sprint-Layout
sPrint-Layout è il compagno ideale di sPlan anche se può lavorare in modo del tutto indipendente. Il programma è studiato
appositamente per la realizzazione di circuiti stampati, il quale, oltre le funzioni standard necessarie alla creazione di
circuiti stampati, offre anche funzioni professionali quali: esportazione in formato GERBER ed EXCELLON.
Tra le numerose ed innovative caratteristiche ne troviamo una studiata appositamente per gli hobbisti, infatti, è possibile
scannerizzare un circuito stampato da una rivista o un qualsiasi supporto cartaceo ed importarlo per facilitarne il disegno
o la modifica. La funzione di “photoview” mostra il circuito stampato così come apparirebbe una volta prodotto (funzione
che utilizziamo per la rivista Fare Elettronica). Un libreria di componenti, facilmente creabili o modificabili, completa la
ricca dotazione del programma.
I disegni di Fare Elettronica sono realizzati con Sprint-Layout, da oggi potrai scaricarli dal sito e modificarli direttamente.
€ 39,00 (+Iva)
sPlan
Splan è un cad appositamente realizzato per la stesura di schemi elettrici che implementa tutti gli strumenti necessari allo
svolgimento del lavoro in modo semplice ed efficace. sPlan è dotato di molte funzioni tra le quali: numerazione automatica
di componenti, scaling e preview dei componenti, gestione delle librerie di simboli, modifica di ogni singolo elemento sullo
schermo, griglia di posizionamento, connessioni automatiche, e molto altro ancora. La libreria di simboli contiene moltissime
parti pronte all’uso, inoltre le funzioni di editing dei simboli consentono la creazione di nuovi molto velocemente. SPlan
Codice MIP 256097
implementa anche un potente motore di stampa e la possibilità di esportare i disegni in diversi formati, anche grafici.
€ 39,00 (+Iva)
Front Designer
I tempi sono cambiati ed il vostro progetto elettronico non ha più motivo di essere incluso in un vecchio pacchetto di sigari.
Oggi molti rivenditori offrono contenitori adatti a tutti i tipi di circuiti immaginabili, ma spesso i dispositivi autocostruiti
restano incompleti per la mancanza delle indicazioni sul pannello frontale.
Front Designer offre la possibilità di creare pannelli frontali veramente professionali.
€ 39,00 (+Iva)
d'onda analogica sia mantenuto per diversi cicli quenza della sinusoide occorre caricare in TMR0
dell'onda PWM. Il codice seguente mostra la un valore maggiore, in modo da aumentare la
generazione di una sinusoide utilizzando la tecni- frequenza con cui vengono generate le interru-
ca descritta, ed il circuito di Figura 5. zioni, ma occorre mantenersi sotto la frequenza
dell'onda PWM, che è stata scelta pari a
unsigned char j; 31248Hz. Per ottenere un segnale analogico
const unsigned char pulito (poco distorto) si dovrebbe fare in modo
onda[16]={128,176,218,246, da mantenere la frequenza del segnale genera-
to abbastanza più bassa di quella di campiona-
255,246,218,176, mento, o in caso contrario utilizzare un filtro
128, 79, passa basso abbastanza ripido la cui frequenza
37, 10, di taglio può essere più vicina a quella di cam-
0, 10, 37, pionamento. Nel circuito di Figura 5 è stato uti-
79}; lizzato un semplice circuito RC come filtro
passa-basso, la cui frequenza di taglio è circa
void main() { 1500Hz. Va ricordato che in questo caso il cari-
co deve avere un'impedenza sufficientemente
// Inizializz. porte e regs alta (almeno qualche Kohm), in modo da non
PORTC = 0; variare la costante di tempo de circuito.
TRISC = 0;
OPTION_REG = 0x80; GENERAZIONE DI SUONI ED
TMR0 = 192; EFFETTI
INTCON = 0xA0; Apparentemente l'argomento potrebbe sembra-
FARE ELETTRONICA - OTTOBRE 2006
stro PR2. Il primo determina il valore del contato- terno di una routine d'interruzione, in modo da
re TMR2 superato il quale l'uscita si porta a livel- lasciare spazio ad altre routine all'interno del
lo basso, mentre il secondo determina il valore loop principale.
per cui il timer viene resettato (più piccolo sarà
questo valore, più frequente sarà l'overflow). void main() {
Se vogliamo usare il modulo PWM per generare unsigned char j;
suoni dobbiamo soltanto tenere presente due
cose: 1) il prescaler di TMR2 (bit 0 e 1 del regi- // Init. porte
stro T2CON) deve essere impostato in modo che PORTC = 0;
la frequenza ottenuta risulti udibile; 2) Il valore di TRISC = 0;
duty cycle deve essere inferiore al limite di con- Pwm_Init(1000);
teggio, altrimenti non ci saranno variazioni nel Pwm_Change_Duty(128);
segnale d'uscita. Maggiori dettagli possono esse- Pwm_Start();
re trovati nel datasheet del PIC. T2CON=0x07; // Init. prescaler
Nell'esempio seguente è stato utilizzato un
PIC16F876 con clock ad 8MHz (stesso schema di // Loop infinito
99
Figura 5), il prescaler è stato impostato a 1:16, while(1) {
Teoria
ottenendo frequenze che coprono un range che for(j=70; j<255; j+=5) {
va da circa 100Hz a circa 1KHz. Il programma PR2=j;
assegna dei valori crescenti e poi decrescenti al Delay_ms(100);
registro PR2, ad intervalli di 100ms, ottenendo }
un effetto sonoro tipo scala ascendente e discen- for(j=255; j>70; j-=5) {
dente (o "sirena", se riprodotto più velocemente). PR2=j;
E' possibile anche calcolare i valori per PR2 in Delay_ms(100);
modo da ottenere le note musicali, che suona- }
te in sequenza possono produrre una melodia }
vera e propria. Invece assegnando a PR2 una }
sequenza veloce di valori "arbitrari" si possono
ottenere degli interessanti effetti sonori (molto CONCLUSIONI
simili a quelli dei vecchi videogame!). Com'è Gli esempi visti in queste quattro puntate
facile immaginare anche in questo caso l'ag- dovrebbero avere fornito un'idea relativamente
giornamento dei valori può essere fatto all'in- chiara di come si possano scrivere dei semplici
programmi in C per i microcon-
trollori PIC. Nella prossima pun-
tata verrà utilizzato quanto visto
fino ad ora per realizzare un'ap-
plicazione completa e legger-
mente più complessa di quelle
viste fino ad ora: un utilissimo
timer digitale programmabile.
FARE ELETTRONICA - OTTOBRE 2006
Quarta parte
n° 256 - Ottobre 2006
Generazione di segnali PWM
Quinta parte
n° 257 - Novembre 2006
Realizzazione di un timer
MikroC
by Example:
digitale programmabile
Sesta parte
n° 258 - Dicembre 2006
Uso delle interfacce seriali
Prima di passare alla descrizione del codice e potuto utilizzare un micro più piccolo, ma si è
delle tecniche implementative utilizzate però è il preferito puntare sul 16F876 perché avendo a
caso di descrivere in dettaglio le specifiche del- disposizione diverse porte libere, permette di
l’applicazione che ci proponiamo di realizzare. aggiungere e sperimentare funzioni aggiuntive
Il timer che vogliamo implementare deve essere (si veda in seguito).
capace di memorizzare l’ora corrente ed il giorno
della settimana, e di gestire un certo numero di STRUTTURA DEL CODICE
eventi che controllano quando l’uscita (ossia un Il programma è costituito da un unico modulo
relè a cui può essere collegato un carico arbitra- (Timer.c) e dal suo header (Timer.h). Nel primo è
rio) deve essere attivata. Per ciascun evento è contenuto il corpo di tutte le funzioni (compreso
di stefano - TEORIA - mikroC 5 17-10-2006 15:25 Pagina 87
Realizzazione di
un timer digitale
programmabile di Antonio Di Stefano
Teoria
gestire da due entità: la macchina a stati princi- che non è possibile dividere la frequenza del timer
pale, che si occupa in pratica di gestire l’interfac- TMR0 del PIC per un fattore tale da avere a disposi-
cia utente, e la routine d’interruzione, che invece zione un interrupt ogni secondo (o sue frazioni deci-
provvede ad aggiornare l’ora corrente e ad ese- mali), è necessario utilizzare un contatore (il campo
guire la lettura dello stato dei pulsanti con la fun- tck) per ottenere l’incremento dei secondo con la
zione anti-rimbalzo. Questa suddivisione è stata giusta cadenza. In particolare, dal momento che
scelta dal momento che l’aggiornamento dell’ora l’interruzione avviene ogni 1/125 secondi (si vedano
e lo stato dei pulsanti sono prioritari, e in qualche le impostazioni del TMR0 nella routine Init), i
caso determinano la visualizzazione dei dati ed il secondi verranno incrementati quando il contatore
comportamento del circuito. raggiunge 125 (valore di TCK_SEC).
[Listato 1]
char *onoff[2]={“Off”, “On “};
char *blank=””;
/*** Timer.h ***/
// - Tipo evento -
// Stato modifica ora
typedef struct {
void Set_Ora(void);
unsigned char hr; // Ora
unsigned char min; // Minuti
// Stato visualizza eventi
unsigned char sec; // Secondi
void Vis_Evento(void);
unsigned char grn; // Gionro
FARE ELETTRONICA - NOVEMBRE 2006
Teoria
il valore di reset è diverso rispetto al coso di rila-
// Aggiornamento ora
scio del pulsante (in questo caso la soglia è rag-
if (ora.tck==TCK_SEC) {
giunta in 20/250s = 160ms). Questo permette di
ora.tck=0;
differenziare tra ritardo anti-rimbalzo o ritardo di
ora.sec++;
ripetizione se il tasto è continuamente premuto.
secondo=1;
if (ora.sec==60) {
Funzione main
ora.sec=0;
La funzione main, come si può vedere dal codi-
ora.min++;
ce, è piuttosto snella ed implementa soltanto il
if (ora.min==60) {
loop principale del programma che contiene la
ora.min=0;
macchina a stati che gestisce l’interfaccia utente.
ora.hr++;
Questa struttura è stata utilizzata dal momento
if (ora.hr==24) {
che le funzioni dei tasti ed i dati visualizzati sul
ora.hr=0;
display variano a seconda del contesto e delle
ora.grn++;
azioni che si sono compiute in precedenza.
if (ora.grn==7) ora.grn=0;
Occorre quindi considerare lo stato in cui ci si
}
trova e aggiornarlo in base alle azioni dell’utente.
}
La variabile “stato”, di tipo enumerativo, svolge
}
questo compito. Il diagramma degli stati è
}
mostrato in Figura 2, il codice che li implementa
invece è mostrato nel listato 3.
// Stato pulsanti
In pratica lo stato attuale determina quale delle 4
if ((PORTC&0x01)&&(Pcnt[0]<P_SOGLIA))
funzioni è eseguita ad ogni iterazione del loop.
FARE ELETTRONICA - NOVEMBRE 2006
[Listato 3]
Funzione di visualizzazione
void main() {
Le funzioni utilizzate per la visualizzazione sono
tre: Display_Ora(), Display_Eventi() e Cursore().
Init();
Le prime due visualizzano l’ora attuale e la lista
while(1) {
di eventi rispettivamente. Esse prendono in
switch (stato) {
ingresso un parametro che può valere 0 nel
caso della visualizzazione normale, o 1 nel caso
case S_VIS_ORA:
si voglia fare apparire il cursore sul valore da
Vis_Ora();
modificare. Il posizionamento e la visualizzazio-
break;
ne del cursore in base al parametro da modifi-
care sono gestiti dalla funzione Cursore(). A
case S_SET_ORA:
scopo di esempio, la funzione Display_Ora(), è
Set_Ora();
riportata nel listato 6. Come si può vedere sono
break;
state utilizzate le funzioni di libreria del MikroC
case S_VIS_EVENTI:
per convertire i valori numerici in stringhe e per
visualizzarli sull’LCD (funzione Lcd_Out).
90 Vis_Evento();
break;
Teoria
MODIFICHE E
case S_SET_EVENTI:
MIGLIORAMENTI
Set_Evento();
Modificando il valore delle macro presenti
break;
nel file Timer.h è possibile personalizzare le
}
caratteristiche del timer in base alle proprie
} [Listato 4]
} void Vis_Ora(void)
{ if (secondo) { Display_Ora(0);
prime due gestiscono gli stati in cui sono visua-
Test_Eventi();
lizzati l’ora corrente o gli eventi, mentre gli altri
secondo=0;
gestiscono la fase di modifica dei valori in que-
}
sti stati. Ciascuna di queste funzioni è compo-
// Pulsante +
sta da una parte che si occupa della visualizza-
if (PTest(0)) { uscita = USCITA_ON;
zione (richiamando una funzione apposita), e
}
da una serie controlli sulla pressione dei pulsan-
// Pulsante -
ti, che generano il cambiamento di stato o del
if (PTest(1)) {
valore di alcune variabili. A titolo di esempio nel
uscita = USCITA_OFF;
listato 4 è riportato il codice della funzione
}
Vis_Ora. Allo scadere di ogni secondo, la varia-
// Select
bile “secondo” viene impostata ad 1 dalla rou-
if (PTest(2)) {
tine d’interruzione. In questo caso viene richia-
stato=S_VIS_EVENTI;
mata la funzione di visualizzazione dell’ora
Display_Eventi(0);
Display_Ora (per aggiornare il display) e quella
FARE ELETTRONICA - NOVEMBRE 2006
Delay_ms(250);
che controlla la scadenza degli eventi, che
}
determina se l’uscita deve essere attivata o
// Adjust
disattivata. Il codice di questa funzione, chia-
if (PTest(3)) {
mata Test_Eventi, è riportato nel listato 5.
Display_Ora(1);
In questa routine viene verificato, per ciascun
stato=S_SET_ORA;
evento, se l’ora di attivazione coincide con l’ora
start_stop=0;
attuale, o se è trascorso l’intervallo di attivazio-
Delay_ms(250);
ne associato a ciascun evento. In base a questo
}
controllo viene aggiornata la variabile “uscita”,
}
che poi viene assegnata alla porta C del PIC.
di stefano - TEORIA - mikroC 5 17-10-2006 15:25 Pagina 91
Teoria
gestione di più uscite indipen-
denti o l’utilizzo di segnali
esterni per condizionare deter-
minati eventi. In particolare, si
Figura 2 Diagramma degli stati del timer
può utilizzare la porta A per
Compilatore MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
✔ Debugger
FARE ELETTRONICA - NOVEMBRE 2006
✔ Statistiche
Tutto in un ambiente
Windows facile ed intuitivo
[Listato 5] [Listato 6]
void Test_Eventi(void) void Display_Ora(char edit)
{ {
char i, ora_fine, min_fine, grn_fine; Lcd_Cmd(LCD_CURSOR_OFF);
for(i=0; i<N_EVENTI; i++) { ByteToStr(ora.hr, thr);
// - Disattiva uscita - ByteToStr(ora.min, tmin);
min_fine=eventi[i].min+eventi[i].d_min; ByteToStr(ora.sec, tsec);
ora_fine=eventi[i].hr+eventi[i].d_hr; if (thr[1]==’ ‘) thr[1]=’0’;
grn_fine=eventi[i].grn; if (tmin[1]==’ ‘) tmin[1]=’0’;
if (min_fine>59) { if (tsec[1]==’ ‘) tsec[1]=’0’;
min_fine=min_fine-60; thr[3]=’:’;
ora_fine++; tmin[3]=’:’;
} Lcd_Out(1,1,nomegrn[ora.grn]);
if (ora_fine>23) { Lcd_Out(2,1,(thr+1));
ora_fine=ora_fine-24; Lcd_Out(2,4,(tmin+1));
92 if (grn_fine!=7) { Lcd_Out(2,7,(tsec+1));
if (uscita)
Teoria
grn_fine++;
if (grn_fine==7) grn_fine=0; Lcd_out(2, 14, onoff[1]);
} else
} Lcd_out(2, 14, onoff[0]);
if((ora.grn==grn_fine)|| if (edit) {
(eventi[i].grn==7)) { Cursore(pos+1);
if (ora.hr==ora_fine) { } else {
if (ora.min==min_fine) { Lcd_Cmd(LCD_CURSOR_OFF);
if (eventi[i].attivo) uscita = }
USCITA_OFF; }
}
} acquisire segnali digitali o analogici esterni da
} utilizzare come abilitazione per alcuni eventi.
Quinta parte
n° 257 - Novembre 2006
MikroC
Realizzazione di un timer
digitale programmabile
Sesta parte
n° 258 - Dicembre 2006
Uso delle interfacce seriali
Settima parte
n° 259 - Gennaio 2007
by Example
Interfacce SPI, I2C e 1-Wire
PORTB=0;
tensioni di segnalazione piuttosto alte (circa
TRISB=0xFF; // PORTB[0-7]: ingressi
12V). Nella versione più semplice, l’interfaccia è
costituita da soli tre fili: TX (trasmissione), RX
// Inizializzazione
(ricezione) e massa. I dati sono trasmessi serial-
Usart_Init(2400);
mente in maniera asincrona, cioè senza l’uso di
pb=0;
un clock. Per rendere possibile questo è neces-
mpb=0;
sario che il ricevitore ed il trasmettitore utilizzi-
while(1) {
no lo stesso formato di dati (velocità di trasmis-
pb=PORTB;
sione, numero e tipologia di bit).
if (pb!=mpb)
L’interfaccia RS-232 costituisce un metodo
DiStefano- TEORIA -mikroC 6 23-11-2006 13:30 Pagina 85
Uso
dell’interfaccia
seriale di Antonio Di Stefano
85
Teoria
Figura 1 Schema utilizzato negli esempi
connessione, nella finestra sono presenti altre e lo memorizza in un buffer interno). Quando
opzioni, tra cui quella che permette di selezionare è stato ricevuto un carattere la funzione resti-
la modalità di visualizzazione dei dati ricevuti. In tuisce un valore diverso da zero (che equivale
questo caso l’impostazione scelta è Hex, in modo ad una condizione vera). Una volta letto il
da potere leggere il valore binario inviato. Negli carattere (con la funzione Usart_Read), que-
altri esempi sarà utilizzata la modalità ASCII, dal sto viene elaborato secondo l’algoritmo
momento che sarà scambiato del testo. descritto prima (controllando che si tratti
effettivamente di una lettera dell’alfabeto
CIFRATURA REMOTA maiuscola o minuscola, grazie alle funzione
Per mostrare come la comunicazione possa isupper e islower della libreria standard
avvenire anche nell’altra direzione, e si possa istau- ctype.h), ed inviato di nuovo al PC. Il risulta-
rare un primo esempio di colloquio tra il PC ed il to sarà che se inviamo la parola “Ciao”, otter-
PIC, è riportato nel listato 2 il codice di un pro- remo come risposta “Pvnb”. Se re-inviamo
gramma che riceve un testo dal PC e lo cifra secon- quest’ultima otterremo di nuovo la versione
do il codice ROT13, utilizzato spesso su Internet in chiaro. Come si può notare già da questo
come semplice forma di cifratura del testo. Il codi- esempio, la comunicazione tramite RS-232 è
86
ce consiste in pratica nel ruotare l’alfabeto anglo- orientata e ordinata a singoli byte. Per scambia-
Teoria
sassone (26 lettere) di 13 posti, in questo modo A re messaggi più complessi è necessario ideare
diventa N, la Z la M e così via. L’algoritmo è rever- o usare dei protocolli che definiscano la strut-
sibile, e quindi quando viene applicato ad un testo tura dei messaggi, come mostrato di seguito.
già cifrato, lo riporta in chiaro.
CONTROLLO DI UN DISPLAY DA PC
Listato 2 Supponiamo di volere inviare da PC il testo da
/* ROT13 remoto */ visualizzare su un display LCD. Il testo potrebbe
essere generato da un apposito software
void main() { oppure essere utilizzato soltanto come mes-
unsigned short i; saggio remoto. L’utilizzo della porta RS-232
costituisce una buona soluzione. Utilizzando
Usart_Init(2400); lo schema di Figura 1, ed il programma
while (1) { mostrato nel listato 3 è possibile ottenere in
// Se riceve un carattere maniera molto semplice quanto detto. In pra-
if (Usart_Data_Ready()) { tica il programma consente di inviare dei
// Legge il dato ricevuto comandi e delle stringhe al display in modo
i = Usart_Read(); da controllare il testo visualizzato. Inviando la
// Rotazione maiuscole stringa “C” è possibile cancellare il testo visua-
if (isupper(i)) lizzato, inviando la stringa “T x Abcd” è possi-
i=((i-’A’)+13)%26+’A’; bile scrivere la stringa “Abcd” nella riga x (che
// Rotazione minuscole
if (islower(i))
i=((i-’a’)+13)%26+’a’;
FARE ELETTRONICA - DICEMBRE 2006
// Invio risultato
Usart_Write(i);
}
}
}
Teoria
}
PORTB=0;
TRISB=0; // Elaborazione stringa
if (stringa) {
Usart_Init(2400); switch(buf[0]) {
Scheda easyPIC4
La rivoluzionaria scheda
di sviluppo per PICmicro
✔ Programmatore USB2.0 on-board con ICD
✔ Tastiera a 32 tasti
✔ 32 LED per il monitoraggio degli I/O
✔ 4 cifre LED a 7 segmenti
✔ Predisposizione per moduli LCD alfanumerici
✔ Predisposizione per moduli LCD grafici
✔ Predisposizione per comunicazione RS232
FARE ELETTRONICA - DICEMBRE 2006
Listato 4
n=0; /* Controllo seriale remoto
while(str[n]) { UART HW con int. */
Usart_Write(str[n]); #define MAX_LEN 32
n++;
} char stringa, bpnt;
} char buf[MAX_LEN];
Dopo una prima inizializzazione della UART, del void SendString(char *);
display e delle variabili, inizia il loop principale. Al char Hex2Dec(char *);
DiStefano- TEORIA -mikroC 6 23-11-2006 13:30 Pagina 89
void Dec2Hex(char, char *); funzioni disponibili sono quasi le stesse, anche
... il loro uso richiede una più accurata pianifica-
void main() { zione dei tempi del programma (che deve fer-
… marsi ad attendere l’arrivo dei caratteri, e non
Usart_Init(2400); può gestire la comunicazione in full duplex).
// Set RCIE Nel listato 5 è mostrato un esempio imple-
PIE1|=0x20; mentato in versione “software”:
// Set GIE e PEIE
INTCON|=0xC0; Listato 5
… /* ROT13 remoto con
while(1) { UART software */
void main() {
if (stringa) { unsigned short ro = 0, *recOK, i;
Teoria
} while(1) {
… do {
} i = Soft_Uart_Read(recOK);
} while (*recOK);
interrupt()
{ if (isupper(i))
if (!stringa) { i=((i-’A’)+13)%26+’A’;
buf[bpnt] = Usart_Read(); if (islower(i))
if ((buf[bpnt]==’\n’)|| i=((i-’a’)+13)%26+’a’;
(bpnt==MAX_LEN-1)) { Soft_Uart_Write(i);
stringa=1; }
} }
bpnt++;
} Notare che i piedini di comunicazione specifi-
} cati sono RA0 ed RA1 invece di RC6 ed RC7,
questo rende possibile riscrivere i programmi
In pratica il codice è rimasto quasi invariato, presentati prima anche per PIC privi di UART,
tranne per il fatto che sono state attivate le quale il 16F84.
interruzioni associate alla ricezione dei singoli
caratteri, e la funzione di ricezione stringhe è CONCLUSIONI
stata confinata nella routine d’interruzione. Si Va ricordato che le routine mostrate possono
può notare anche che la comunicazione tra le essere provate anche su PC privi di porta seria-
due routine avviene ancora tramite la variabile le, utilizzando un adattatore USB-RS232
FARE ELETTRONICA - DICEMBRE 2006
“stringa”, che questa volta però è stata dichia- (ricordarsi di settare il numero corretto di
rata come globale. porta COM). Nella prossima puntata si conti-
nuerà a parlare di protocolli seriali, in partico-
SOFTWARE UART lare di SPI, I2C e 1-Wire, utilizzati per comuni-
Se il PIC utilizzato non dispone di una UART care con dispositivi quali memorie EEPROM,
integrata è comunque possibile implementare timer, sensori di temperatura, e tanto altro.
una comunicazione seriale. Questo grazie alle Verrà mostrato come usare le routine di libre-
routine della libreria Software_Uart del ria e come comunicare con questi dispositivi.
MikroC, che emulano il dispositivo via softwa-
re utilizzando due qualsiasi piedini di I/O. Le Codice MIP 258084
DiStefano- TEORIA -mikroC 7 19-12-2006 15:36 Pagina 76
Sesta parte
n° 258 - Dicembre 2006
Uso delle interfacce seriali
Settima parte
n° 259 - Gennaio 2007
MikroC
by Example
Interfacce SPI, I2C e 1-Wire
Ottava parte
n° 260 - Febbraio 2007
Uso del convertitore A/D
Interfacce I2C,
SPI e 1-Wire di Antonio Di Stefano
I/O. Il MikroC mette a disposizione due librerie sul bus. Come si può vedere dal codice delle fun-
dedicate alla gestione dell’interfaccia I2C che per- zioni EEPROM_Rd e EEPROM_Wr le operazioni
mettono di sfruttare entrambe le possibilità. Le eseguite per la lettura e scrittura della memoria
funzioni delle due librerie sono quasi identiche, sono esattamente quelle riportate in Figura 2. Il
quindi risulta molto semplice passare da un’im- programma memorizza alcune configurazioni
plementazione hardware ad una software e vice- nella EEPROM in indirizzi successivi, e poi li legge
versa. Per mostrare in dettaglio l’utilizzo delle fun- sequenzialmente (e ciclicamente) riportandoli sui
zioni di libreria verrà utilizzato il circuito di Figura LED collegati alla porta B.
77
1, in cui una memoria EEPROM 24LC02 (2Kbit, Per mostrare l’impiego della libreria “Soft I2C”,
Teoria
organizzata in 256 parole da 8bit) è collegata al ricorreremo allo schema riportato in Figura 3. Il
PIC, e verrà utilizzata per memorizzare i pattern circuito utilizza questa volta un PIC 16F84 (che
da visualizzare sui LED. I dati e le temporizzazioni non dispone di una periferica MSSP) e consente di
da inviare alla memoria per effettuare le operazio- copiare il contenuto di una EEPROM in un’altra.
ni di lettura e scrittura sono riportate in Figura 2. Come si può vedere entrambe le memorie sono
Nel listato 1 è invece riportato il codice che poste sullo stesso bus, ma hanno un indirizzo
mostra come leggere e scrivere singoli byte. diverso grazie al diverso livello applicato ai piedini
A0. Il Listato 2 mostra il codice che effettua la
L’interfaccia I2C deve essere inizializzata richia- copiatura della memoria.
mando la funzione I2C_Init, in cui viene specifica- Il codice è abbastanza semplice: per ciascun indi-
ta la velocità di comunicazione (frequenza del rizzo (da 0 a 255) il dato viene letto dalla EEPROM
clock seriale). È quindi possibile utilizzare le altre 0 e scritto sulla EEPROM 1. L’indirizzo della
funzioni, che eseguono le operazioni elementari EEPROM da utilizzare è passato come parametro
[Listato 1] [Listato 2]
void EEPROM_Wr(char addr, char data); void EEPROM_Wr(char addr, char data, char d);
char EEPROM_Rd(char); char EEPROM_Rd(char addr, char d);
PORTB=0; PORTA=0;
TRISB=0; TRISA=0;
// Inizializzazione
I2C_Init(400000); // Inizializzazione
Soft_I2C_Config(PORTB,0,1);
// Scrittura dati
EEPROM_Wr(0, 0x00); // ———— Delay_ms(100);
EEPROM_Wr(1, 0x81); // *———*
78
EEPROM_Wr(2, 0xC3); // **——** PORTA=0x01;
Teoria
return k; return k;
} }
DiStefano- TEORIA -mikroC 7 19-12-2006 15:36 Pagina 79
79
Teoria
Figura 3 Schema usato per la copiatura di dati tra due EEPROM
Compilatore MikroC
Un potente
compilatore C
per PICmicro
Code Editor
Code Explorer
Debugger
Statistiche
FARE ELETTRONICA - GENNAIO 2007
Tutto in un ambiente
Windows facile ed intuitivo
alle funzioni e viene inglobato nel primo coman- dell’ambiente, di convertirla in un valore digitale
do inviato. Per segnalare l’inizio e la fine delle ope- a 9 bit (risoluzione di 0.5°C), e di comunicarla su
razioni vengono utilizzati due LED collegati alla richiesta al master. Il valore letto in questo caso
porta A. Va notato che le EEPROM seriali permet- viene visualizzato su un display LCD 16x2 ad
terebbero di leggere e scrivere sequenzialmente i intervalli di circa un secondo. Il codice relativo
dati, senza la necessità di inviare nuovamente l’in- all’esempio è riportato nel Listato 3.
dirizzo. Utilizzando questa modalità di accesso si Le funzioni disponibili per gestire l’interfaccia per-
sarebbe potuto ottenere una copiatura notevol- mettono di iniziare la comunicazione (Ow_Reset),
mente più veloce ed efficiente (l’esempio però scrivere (Ow_Write) e leggere (Ow_Read) un dato
DiStefano- TEORIA -mikroC 7 19-12-2006 15:36 Pagina 81
81
Teoria
Figura 4 Schema del termometro digitale con DS1820
Scheda easyPIC4
La rivoluzionaria scheda
di sviluppo per PICmicro
Programmatore USB2.0 on-board con ICD
Tastiera a 32 tasti
32 LED per il monitoraggio degli I/O
4 cifre LED a 7 segmenti
Predisposizione per moduli LCD alfanumerici
Predisposizione per moduli LCD grafici
Predisposizione per comunicazione RS232
Predisposizione per tastiera PS2
FARE ELETTRONICA - GENNAIO 2007
dal dispositivo. Ciascuna di queste funzioni pren- ste in un bus seriale sincrono, che utilizza 4 fili (3
de in ingresso un puntatore alla porta a cui è col- in alcuni casi): uno è associato al clock seriale,
legato il dispositivo, il numero del piedino (in que- comandato dal master, due sono utilizzati rispet-
sto caso RA0), e l’eventuale dato da trasmettere. tivamente per i dati in ingresso e per quelli in usci-
Per eseguire la lettura della temperatura dal ta, ed il quarto, non sempre presente svolge la
DS1820 è necessario iniziare la comunicazione funzione di Chip Select, cioè abilita o meno un
con un reset, specificare se si vuole indirizzare un particolare slave a ricevere i comandi. L’interfaccia
particolare dispositivo o meno (codice “skip SPI è utilizzata in maniera simile (o a volte in
ROM”, 0xCC), comandare un inizio di conversio- luogo) dell’interfaccia I2C, e quindi i dispositivi
ne della temperatura (codice 0x44), e successiva- che la utilizzano sono anche in questo caso molti
mente leggere il valore (codice 0xBE). Alla richie- e molto vari. Vista la similitudine utilizzeremo lo
sta di lettura il DS1820 risponde inviando l’intero stesso esempio visti prima per l’interfaccia I2C,
contenuto della memoria locale, seguito dal CRC. utilizzando però una memoria EEPROM seriale
In questo caso vengono letti soltanto i primi due SPI, in particolare la 25LC020, che è funzional-
byte, che sono quelli relativi alla temperatura mente simile alla 24LC02 vista in precedenza. Le
(rispettivamente l’LSB e l’MSB del valore a 9 bit temporizzazioni dei segnali richiesti per la lettura
82
con segno). Per visualizzare sul display il valore è e scrittura dei dati sono mostrate in Figura 5. Lo
Teoria
stato prima di tutto ricomposto il valore intero schema utilizzato è quello visto in Figura 1, in cui
(utilizzando una variabile a 16 bit), poi è stata ese- però la EEPROM I2C è sostituita da quella SPI (i
guita una divisione per 2, in modo da eliminare il collegamenti sono mostrati in Figura 6). Il codice
bit relativo ai 0.5°C. In questo modo il valore bina- per leggere e scrivere la memoria è riportato nel
rio ottenuto corrisponde al valore della tempera- Listato 4.
tura in gradi centigradi. Questo valore binario è La struttura e le funzioni del codice sono identiche
convertito in stringa utilizzando la funzione di a quelle viste nel caso dell’interfaccia I2C, in que-
libreria IntToStr del MikroC, e visualizzato con la sto caso si può notare una certa semplificazione
consueta funzione Lcd_Out. nelle funzioni di lettura e scrittura data dal fatto
che non è necessario gestire le condizioni di start
INTERFACCIA SPI e stop. Una differenza importante rispetto a quan-
L’interfaccia SPI (Serial Peripheral Interface) consi- to visto in precedenza consiste nel fatto che in
FARE ELETTRONICA - GENNAIO 2007
LA SOLUZIONE
per il disegno tecnico
Sprint-Layout
sPrint-Layout è il compagno ideale di sPlan anche se può lavorare in modo del tutto indipendente. Il programma è studiato
appositamente per la realizzazione di circuiti stampati, il quale, oltre le funzioni standard necessarie alla creazione di
circuiti stampati, offre anche funzioni professionali quali: esportazione in formato GERBER ed EXCELLON.
Tra le numerose ed innovative caratteristiche ne troviamo una studiata appositamente per gli hobbisti, infatti, è possibile
scannerizzare un circuito stampato da una rivista o un qualsiasi supporto cartaceo ed importarlo per facilitarne il disegno
o la modifica. La funzione di “photoview” mostra il circuito stampato così come apparirebbe una volta prodotto (funzione
che utilizziamo per la rivista Fare Elettronica). Un libreria di componenti, facilmente creabili o modificabili, completa la
ricca dotazione del programma.
I disegni di Fare Elettronica sono realizzati con Sprint-Layout, da oggi potrai scaricarli dal sito e modificarli direttamente.
€ 39,00 (+Iva)
sPlan
Splan è un cad appositamente realizzato per la stesura di schemi elettrici che implementa tutti gli strumenti necessari allo
svolgimento del lavoro in modo semplice ed efficace. sPlan è dotato di molte funzioni tra le quali: numerazione automatica
di componenti, scaling e preview dei componenti, gestione delle librerie di simboli, modifica di ogni singolo elemento sullo
schermo, griglia di posizionamento, connessioni automatiche, e molto altro ancora. La libreria di simboli contiene moltissime
parti pronte all’uso, inoltre le funzioni di editing dei simboli consentono la creazione di nuovi molto velocemente. SPlan
Codice MIP 259083
implementa anche un potente motore di stampa e la possibilità di esportare i disegni in diversi formati, anche grafici.
€ 39,00 (+Iva)
Front Designer
I tempi sono cambiati ed il vostro progetto elettronico non ha più motivo di essere incluso in un vecchio pacchetto di sigari.
Oggi molti rivenditori offrono contenitori adatti a tutti i tipi di circuiti immaginabili, ma spesso i dispositivi autocostruiti
restano incompleti per la mancanza delle indicazioni sul pannello frontale.
Front Designer offre la possibilità di creare pannelli frontali veramente professionali.
€ 39,00 (+Iva)
[Listato 4]
void SPI_EEPROM_Wr(char addr, char data);
char SPI_EEPROM_Rd(char);
void main() {
char i;
PORTB=0;
TRISB=0;
PORTC=0xFF;
TRISC=0;
// Inizializzazione
Spi_Init();
Settima parte
n° 259 - Gennaio 2007
MikroC
Interfacce SPI, I2C e 1-Wire
Ottava parte
n° 260 - Febbraio 2007
Uso del convertitore A/D
Nona parte
n° 261 - Marzo 2007
Realizzazione di un dataloger
by Example
(Iª parte)
Uso del
Convertitore A/D di Antonio Di Stefano
Teoria
letto è sufficiente quindi moltiplicarlo questa
while(1) { costante. Nell’esempio, così come in molte appli-
dato = Adc_Read(2); cazioni comuni, una risoluzione di 10 bit risulta
PORTB = dato>>2; eccessiva, per cui si è scelto di eliminare (con uno
Delay_ms(20); scorrimento a destra) i due bit meno significativi,
}; ottenendo così un valore ad 8 bit (risoluzione di
} 19mV). Il valore binario risultante è riportato sui
LED in modo da potere essere visualizzato.
La funzione Adc_Read prende come parametro il
numero di canale analogico che si intende legge- REGOLAZIONE DI LUMINOSITÀ
re (cioè quale pin della porta si intende usare Nell’esempio riportato di seguito utilizzeremo il
come ingresso), esegue la conversione, e soltanto valore analogico letto dal convertitore A/D per
quando questa è terminata restituisce il valore regolare la luminosità di una lampadina (o di un
convertito. Dal momento che il dato sarà a 10 bit LED). Per fare questo verrà generato un segnale
PWM il cui duty cycle sarà determinato in base realizzare un semplice VU meter, cioè un misu-
al valore analogico letto. Il segnale analogico ratore del livello di un segnale audio. Il circuito
che verrà utilizzato per comandare la regolazio- utilizzato è uguale a quello mostrato in Figura 1,
ne di luminosità potrà essere prelevato da un con l’unica differenza che il segnale audio viene
potenziometro, come mostrato in Figura 2, o da accoppiato all’ingresso analogico del PIC utiliz-
un fotodiodo, in modo da realizzare un interrut- zando la rete mostrata in Figura 3 invece del
tore crepuscolare (che cioè aumenta la lumino- semplice trimmer. Se il segnale audio utilizzato
sità della sorgente quanto maggiore è il buio). Il ha un’impedenza sufficientemente bassa ed
codice che implementa l’applicazione è riporta- un’ampiezza di alcuni Vpp attorno a 0V, il
to nel Listato 2. segnale ottenuto all’ingresso analogico avrà
come valore medio 2.5V, e rientrerà completa-
[Listato 2] mente nella gamma dinamica del convertitore
// *** Regolazione luminosità *** (cioè tra 0 e 5V). Il programma visualizza l’am-
void main() { piezza dei campioni acquisiti accendendo un
unsigned int level; numero di LED proporzionale. In più, dal
momento che le variazioni d’ampiezza del
82
TRISC = 0; segnale sono molto veloci, è stato implementa-
Teoria
Teoria
CONVERSIONE DI PIÙ CANALI USO DELLE INTERRUZIONI
Come già anticipato, nonostante il convertitore Si può notare che l’algoritmo utilizzato nel pre-
AD integrato del PIC sia uno solo, è possibile cedente esempio, sebbene adeguato all’appli-
comunque acquisire il valore di più tensioni ana- cazione, non è molto efficiente, in quanto le
Compilatore MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
✔ Debugger
FARE ELETTRONICA - FEBBRAIO 2007
✔ Statistiche
Tutto in un ambiente
Windows facile ed intuitivo
[Listato 5]
// *** Gestione AD con interruzioni *** while(1) {
unsigned int dato, maxi; if (dato>maxi) maxi=dato;
char dis[9]={0,1,3,7,15,31,63,127,255}; PORTB = dis[((maxi+16)>>7)];
void main() { if (maxi>dato) maxi—;
ADCON0 = 0x91; // Config. input Delay_ms(1);
ADCON1 = 0x80; // Config. input };
TRISA = 0xFF; // PORTA = input }
TRISB = 0x00; void interrupt()
PORTB = 0x00; {
// Abilitazione interruzioni dato=(ADRESH<<8)+ADRESL;
PIR1=0x00; // ADIF
PIE1=0x40; // ADIE // Reset ADIF Flag
85
Teoria
INTCON = 0xC0; // GIE + PEIE PIR1=0x00;
dato = 0;
maxi = 0; // Avvio nuova conversione
// Avvio prima conversione ADCON0=ADCON0|0x04;
ADCON0=ADCON0|0x04; }
Scheda easyPIC4
La rivoluzionaria scheda
di sviluppo per PICmicro
✔ Programmatore USB2.0 on-board con ICD
✔ Tastiera a 32 tasti
✔ 32 LED per il monitoraggio degli I/O
✔ 4 cifre LED a 7 segmenti
✔ Predisposizione per moduli LCD alfanumerici
✔ Predisposizione per moduli LCD grafici
✔ Predisposizione per comunicazione RS232
✔ Predisposizione per tastiera PS2
FARE ELETTRONICA - FEBBRAIO 2007
tempo impiegato per completare la conversione Grazie all’impiego del Timer TMR0 si ottiene
e dal codice eseguito. In molti casi invece è utile una frequenza di campionamento di 1KHz esatto.
campionare dei segnali con una frequenza ben Come si può vedere dal codice sono state abili-
definita e costante. Per fare questo occorre uti- tate le interruzioni relative al timer e al conver-
lizzare il timer, come mostrato nel Listato 6. titore AD, quindi la routine d’interruzione verrà
richiamata sia all’overflow del timer, sia al com-
[Listato 6]
pletamento di ogni conversione. All’interno
// *** Campionamento a 1KHz ***
della routine pertanto è necessario distinguere
unsigned int dato, maxi;
quale delle due periferiche ha generato l’inter-
char dis[9]={0,1,3,7,15,31,63,127,255};
ruzione (controllando lo stato dei flag). Se l’in-
void main() {
terruzione è stata generata dal timer, viene
ADCON0 = 0x91; // Config. input
avviato il convertitore e resettato il timer. Se l’in-
ADCON1 = 0x80; // Config. input
terruzione è stata generata dal convertitore,
TRISA = 0xFF; // PORTA = input
viene salvato il dato convertito e resettato il flag.
TRISB = 0x00;
In questo modo la frequenza di campionamen-
PORTB = 0x00;
to è stabilita dal timer, e l’aggiornamento della
86 // Inizializz. Registri
variabile avviene solo quando il convertitore ha
OPTION_REG = 0x82; // CLK/4/8
Teoria
Ottava parte
n° 260 - Febbraio 2007
Uso del convertitore A/D
Nona parte
n° 261 - Marzo 2007
Realizzazione di un dataloger
MikroC
by Example
(Iª parte)
Decima parte
n° 262 - Aprile 2007
Realizzazione di un dataloger
(IIª parte)
da sensori o apparati esterni. I datalogger sono si analogici oppure 2 analogici, uno digitale
utilizzati per tenere sotto controllo sistemi o ed uno relativo alla temperatura.
apparati di vario genere, che necessitano un • L’avvio e l’arresto del campionamento avven-
monitoraggio continuo. I dati registrati durante gono tramite un pulsante o un comando
l’intero intervallo di osservazione possono esse- seriale.
re successivamente scaricati su PC per essere • Un LED rosso lampeggiante indica che il cam-
visualizzati ed analizzati meglio con software pionamento è attivo, un LED verde invece la
dedicati. Il progetto qui presentato ha delle fine del campionamento (se nessun LED è
caratteristiche abbastanza interessanti e può acceso significa che il campionamento non è
DiStefano- TEORIA -mikroC 9:DiStefano- TEORIA -mikroC 8 14-02-2007 15:39 Pagina 85
Realizzazione di
un datalogger di Antonio Di Stefano
iniziato e quindi non ci sono dati validi in guate. Si è scelto di utilizzare una EEPROM seria-
memoria). le I2C da 64Kbit per via delle ridotte dimensio-
ni del suo package, della semplicità di utilizzo e
Da queste specifiche risulta che il datalogger è per il fatto che il suo interfacciamento richiede
in grado di campionare ininterrottamente i dati soltanto due piedini.
per un intervallo di tempo compreso tra circa Per rilevare la temperatura si è scelto di collega-
33 minuti e quasi un anno, ed è abbastanza ver- re un sensore digitale del tipo DS1820 al piedi-
satile da potere essere utilizzato in una grande no RA5. Il sensore della Dallas fornisce diretta-
85
varietà di applicazioni! mente la temperatura in formato digitale con
Teoria
una buona accuratezza, utilizzando l’interfaccia
SCHEMA ELETTRICO 1-Wire, che richiede soltanto un collegamento.
Lo schema elettrico utilizzato per il datalogger è Dal momento che il pin RA5 è anche un ingres-
riportato in Figura 1. Il cuore del circuito è un so analogico, non è comunque difficile sostitui-
comune PIC16F876, che viene fatto funzionare re questo componente con un sensore di tem-
a 8MHz. Questo PIC è dotato di un convertito- peratura analogico come l’LM35 se desiderato,
re A/D a 10 bit e di 5 ingressi analogici, e può ed utilizzare il convertitore interno per campio-
quindi soddisfare le specifiche. Gli 8 ingressi nare il dato.
digitali possono essere ricavati dalla porta B. Per La comunicazione con il PC avviene utilizzando
memorizzare i dati è necessaria una memoria la periferica UART integrata nel PIC. È necessa-
non volatile, ma non è possibile utilizzare la rio però utilizzare un MAX232 per adattare i
EEPROM del PIC per via delle sue ridotte dimen- livelli di segnalazione a quelli dello standard RS-
sioni. E’ necessario pertanto collegare una 232. I due LED che segnalano lo stato di cam-
memoria non volatile esterna di dimensioni ade- pionamento in corso/completato sono collegati
pre nella EEPROM esterna il puntatore all’indi- routine sarà eseguito e genererà dei segnali di
rizzo dell’ultimo dato memorizzato (utile nel controllo per attivare le altre funzioni. Queste
caso di memorizzazione continua) ed il numero
complessivo di campioni. Queste informazioni
saranno utili quando occorrerà scaricare i dati su
PC. Dal momento che la EEPROM scelta può
contenere 8KB, ed in ciascuna registrazione
vengono memorizzati 4 byte di dati, sarà possi-
bile memorizzare 2048 campioni per ciascuno
dei 4 dati. Considerando che i dati da memoriz-
zare sono solo 2000, gli indirizzi più alti della
EEPROM saranno liberi per memorizzare le
informazioni di servizio descritte prima.
Come visto nelle specifiche il datalogger ha una
serie di parametri configurabili, come la veloci-
tà di campionamento, la scelta dei dati da
memorizzare e la modalità di memorizzazione
(singola o in continua). Queste informazioni
vengono impostate dal PC tramite RS-232 e
devono essere memorizzate in maniera non
volatile (in modo tale da permettere lo spegni-
mento del dispositivo dopo la configurazione).
Anche in questo caso è utilizzata la EEPROM
esterna.
FARE ELETTRONICA - MARZO 2007
funzioni sono gestite dal loop principale, e ven- mento eseguito), le due variabili vengono ripor-
gono eseguite solo se prima sono stati attivati i tate al valore 0, in attesa di un nuovo evento.
rispettivi segnali di controllo. Ovviamente i
segnali di cui si parla, e che consentono la Comandi, decodifica e configurazione
comunicazione tra la routine d’interruzione ed il I comandi gestiti dal datalogger sono i seguenti:
loop principale, non sono altro che delle varia- • Axxx: imposta l’intervallo di campionamento
bili globali, settate da una routine e resettate a xxx minuti. Il valore di xxx può variare da 0
dall’altra. a 255, se viene specificato 0 i dati vengono
Più in dettaglio i compiti da gestire sono due: il campionati ogni secondo.
campionamento più la memorizzazione dei dati, • Bx: imposta se campionare i 4 canali analogi-
e la decodifica dei comandi inviati dal PC, usati ci (x=0) o due analogici, 8 digitali (porta B) e
per impostare la configurazione e richiedere l’in- uno di temperatura (x=1).
vio dei dati memorizzati. Anche le variabili di • Cx: se x=0 vengono registrati soltanto 2000
segnalazione sono due, chiamate “stringa” e campioni, se x=1 la registrazione è continua, i
“trig”. La prima viene impostata ad 1 dalla routi- dati vengono sovrascritti in continuazione ed
ne d’interruzione quando è stata ricevuta e in memoria sono presenti sempre gli ultimi
87
memorizzata (in un apposito buffer) una stringa 2000.
Teoria
completa (terminata da un “a capo”). Il secondo • D: mostra la configurazione attuale.
segnale viene generato quando il timer raggiun- • L: attiva o disattiva la modalità “monitor” (i
ge l’intervallo di tempo di campionamento pre- dati campionati sono anche inviati alla porta
fissato. Una volta che i due compiti sono stati seriale, e quindi visualizzati sul PC in tempo
espletati (la stringa decodificata o il campiona- reale).
Compilatore MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
✔ Debugger
✔ Statistiche
FARE ELETTRONICA - MARZO 2007
Tutto in un ambiente
Windows facile ed intuitivo
vertiti da testo a intero). In base a questi dati delle costanti, alcune come macro (riferite alla
viene eseguita l’operazione corrispondente. La lunghezza del buffer dei comandi ed al nume-
maggior parte dei comandi va a modificare la ro di campioni da memorizzare), altre grazie
configurazione e/o lo stato del sistema, che è al qualificatore “const”. Queste ultime sono
rappresentato dai seguenti parametri, rag- delle stringhe che vengono utilizzate nella
gruppati nella struttura “config”: comunicazione seriale. Dichiarare le stringhe
in questo modo fa si che esse vengono memo-
struct cnf { rizzate nella flash invece che nella RAM del PIC
char periodo; (dove non potrebbero essere contenute a
char canali; causa della ridotta dimensione di questa).
char loop; Successivamente vengono dichiarate le varia-
char logging; bili globali utilizzate per condividere dati e
char monitor; scambiare informazioni tra le routine. In parti-
unsigned data_ptr; colare le variabili “stringa” e “trig” sono le
unsigned n_campioni; variabili di segnalazione descritte prima. La
} config; variabile “buf” (un array) è usata come buffer
per memorizzare le stringhe passate dalla
Oltre alle impostazioni già viste sono presenti il seriale, “msec”, “sec” e “mins” sono usate per
puntatore all’indirizzo della memoria EEPROM tenere il tempo, mentre “pulsante” è un con-
riferito al dato attuale, ed il numero di campio- tatore usato per l’antirimbalzo del pulsante di
ni memorizzati. start/stop. La struttura “config” contiene la
configurazione e lo stato attuale, come
Misura del tempo descritto prima. Tra le funzioni presenti alcune
Per misurare gli intervalli di tempo viene utiliz- sono utilizzate per visualizzare le stringhe.
FARE ELETTRONICA - MARZO 2007
zato il timer hardware del PIC (il TMR0), più In particolare risulta interessante
alcune variabili e contatori. Il TMR0 è stato SendFlashString, che trasmette alla seriale una
programmato per contare ad una frequenza delle stringhe memorizzate nella flash, usando
pari a quella dei cicli macchina diviso 16. la funzione Flash_Read del MikroC. La funzio-
Partendo dalla frequenza di 8MHz, diviso 4 ne main è molto semplice: richiama una serie
cicli di clock per ciclo macchina, e ancora divi- di funzioni di inizializzazione, e poi avvia il
so 16, si ottiene una frequenza di 125KHz. Se loop principale, che contiene la funzione
si imposta un valore di reset tale da avere un “Comandi” usata per la decodifica dei coman-
overflow dopo 125 cicli, si ottiene una fre- di inviati via RS-232. Essa non fa altro che veri-
DiStefano- TEORIA -mikroC 9:DiStefano- TEORIA -mikroC 8 15-02-2007 14:44 Pagina 89
Teoria
ne del pulsante di start/stop, con un conteg- alcun numero:
gio che serve sia come anti-rimbalzo che per il nuovo abbonamento va in
ritardare l’esecuzione del comando di circa un coda e ti garantisci la
secondo (per evitare di attivare o fermare acci- continuità e il risparmio!
dentalmente il campionamento).
Scheda easyPIC4
La rivoluzionaria scheda
di sviluppo per PICmicro
✔ Programmatore USB2.0 on-board con ICD
✔ Tastiera a 32 tasti
✔ 32 LED per il monitoraggio degli I/O
✔ 4 cifre LED a 7 segmenti
✔ Predisposizione per moduli LCD alfanumerici
✔ Predisposizione per moduli LCD grafici
✔ Predisposizione per comunicazione RS232
✔ Predisposizione per tastiera PS2
FARE ELETTRONICA - MARZO 2007
Nella scorsa puntata è stato descritto possono essere notate già nel codice riportato nel
Listato 1, in cui è visibile la parte iniziale, che com-
l’hardware e la struttura del software prende le dichiarazioni (la tabella delle stringhe
del datalogger e sono state mostrate non è riportata per intero per brevità), i prototipi e
la funzione main.
alcune routine. In questa verranno
analizzate con maggiore dettaglio le Listato 1
Realizzazione di
un datalogger
di Antonio Di Stefano
void EEPROM_Wr(unsigned addr, char data); dati relativi alla configurazione (nella memoria
char EEPROM_Rd(unsigned addr); non volatile), e l’indirizzo finale della memoria
void SendString(char *); riservata ai dati. Si può notare che il tipo struttu-
void SendFlashString(unsigned); rato che memorizza la configurazione è stato
void Show_Menu(void); definito in maniera un po’ diversa rispetto a
void Show_Config(void); quello presentato nella scorsa puntata: dal
void Download(void); momento che alcuni campi assumono soltanto
void Print_data(unsigned m, char a, char b, due valori durante il funzionamento (in partico-
char c, char d); lare 0 o 1), si è specificato “:1” accanto al loro 107
nome. Questa particolare notazione (prevista dal
TEORIA
// *** Main *** C standard), consente di specificare proprio il
void main() { numero di bit da utilizzare, limitando così le
richieste di memoria (più campi saranno “impac-
Init(); chettati” in un unico byte).
SendFlashString(str_intro);
Show_Menu(); La funzione main ed il loop principale in essa
contenuto è, come si può vedere, molto sempli-
while(1) { ce. Dopo avere richiamato le funzioni di inizializ-
zazione, nel loop vengono eseguite soltanto le
if (trig) { funzioni di campionamento, memorizzazione e
Campiona(); decodifica dei comandi. Le prime sono eseguite
Memorizza(); solo quando la variabile “trig” è posta ad 1 dalla
if (config.monitor) routine d’interruzione. La seconda invece con-
Print_data(secs, dato[0], dato[1], trolla, come spiegato nello scorso articolo, che la
dato[2], dato[3]); variabile “stringa” valga 1 (stringa completa rice-
trig=0; vuta dal PC) prima di eseguire la decodifica.
} else {
if (config.n_campioni==N_SAMP) { Descrizione delle funzioni
PORTC|=0x02; Alcune funzioni, come quella d’interruzione o
Delay_ms(20); quella di decodifica dei comandi, sono state pre-
PORTC&=0xFD; sentate già nella precedente puntata, le altre ver-
Delay_ms(900); ranno descritte di seguito. Queste funzioni si
} occupano essenzialmente del campionamento
} dei dati, della scrittura e lettura dei dati e della con-
figurazione nella EEPROM, e l’invio dei dati al PC.
FARE ELETTRONICA - APRILE 2007
Comandi();
} Funzione di campionamento
} La funzione che acquisisce i dati è riportata nel
Listato 2. Il funzionamento è molto semplice: a
Si può notare che sono state definite alcune seconda della configurazione scelta per i canali ven-
costanti come macro. Queste facilitano la perso- gono letti i valori analogici relativi ai primi 4 canali,
nalizzazione del programma se si intende utiliz- oppure soltanto due di questi, il valore della porta
zare memorie di dimensioni diverse. Le costanti B (che comprende lo stato digitale di ciascuna delle
specificano in particolare il numero massimo di sue 8 linee), ed il valore della temperatura, letto dal
campioni da memorizzare, l’indirizzo di inizio dei sensore DS1820. Per eseguire tutte queste opera-
Di Stefano- TEORIA - MikroC 10:- PRATICA 20-03-2007 9:54 Pagina 108
zioni vengono utilizzate le funzioni Adc_Read(), e numero 259. In questo caso però la EEPROM
quelle della libreria One-Wire del MikroC, già impiegata, una 24LC64, richiede due byte per
discusse ed utilizzate nelle scorse puntate. La ruoti- l’indirizzamento, ed è quindi necessario ricavare
ne di lettura della temperatura è esattamente ugua- la parte alta (MSB) e quella bassa (LSB) dell’indi-
le a quella utilizzata nel numero 259 di FE. rizzo. Queste due funzioni sono richiamate da
tutte le altre che necessitano di accedere alla
Listato 2 EEPROM. Questo significa che modificandole è
possibile impiegare tipi di memoria diversi (ad
void Campiona(void) esempio la EEPROM interna al PIC, o una flash
{ seriale esterna).
int tt;
Listato 3
if (!config.canali) {
// Modalità AAAA void EEPROM_Wr(unsigned addr, char data)
dato[0] = (char)(Adc_Read(0)>>2); {
dato[1] = (char)(Adc_Read(1)>>2); // Issue I2C start signal
dato[2] = (char)(Adc_Read(2)>>2); I2C_Start();
dato[3] = (char)(Adc_Read(3)>>2); // Send byte via I2C (command to 24LC64)
} else { I2C_Wr(0xA0);
// Modalità AABT // Send byte (MSB address)
108 dato[0] = (char)(Adc_Read(0)>>2); I2C_Wr((addr>>8)&0xFF);
dato[1] = (char)(Adc_Read(1)>>2); // Send byte (LSB address)
TEORIA
ADCON1=0x82; return k;
PORTA=0; }
TRISA=0xFF;
} Memorizzazione dei dati
} La funzione di memorizzazione, scrive i 4 dati
acquisiti sulla memoria (sequenzialmente), prov-
Scrittura e lettura dalla EEPROM vedendo anche ad aggiornare il puntatore all’ul-
Anche in questo caso le routine utilizzate (visibili timo dato scritto, ed il numero complessivo dei
nel Listato 3) sono simili a quella descritte nel campioni (questa caratteristica è utile per recu-
Di Stefano- TEORIA - MikroC 10:- PRATICA 20-03-2007 9:54 Pagina 109
TEORIA
EEPROM_Wr(ADDR_INFO+2, per il campionamento, che può avvenire anche in
(config.n_campioni)&0xFF); maniera autonoma. I parametri della configura-
EEPROM_Wr(ADDR_INFO+3, zione sono memorizzati in due byte: il primo con-
(config.n_campioni>>8)&0xFF); tiene il periodo di campionamento, mentre il
Compilatore MikroC
Un potente
compilatore C
per PICmicro
✔ Code Editor
✔ Code Explorer
✔ Debugger
✔ Statistiche
FARE ELETTRONICA - APRILE 2007
Tutto in un ambiente
Windows facile ed intuitivo
Print_data(i, a, b, c, d);
void Config_Load(void) }
{
unsigned char x; Config_Store();
}
config.periodo=EEPROM_Rd(ADDR_INFO);
x=EEPROM_Rd(ADDR_INFO+1); Conclusioni
Per questioni di spazio non è possibile riportare il
config.canali=(x>>2)&0x01; codice completo, che può comunque essere sca-
config.loop=(x>>1)&0x01; ricato dal sito di Fare Elettronica (www.farelettro-
config.monitor=x&0x01; nica.com) nella sezione “rivista”. I frammenti di
codice riportati dovrebbero essere comunque
config.n_campioni=EEPROM_Rd(ADDR_INFO+2)+ sufficientemente rappresentativi dell’intero fir-
(EEPROM_Rd(ADDR_INFO+3)<<8); mware e delle tecniche adottate per il suo svilup-
config.data_ptr=EEPROM_Rd(ADDR_INFO+4)+ po. Una volta compreso il suo funzionamento è
(EEPROM_Rd(ADDR_INFO+5)<<8); possibile apportare diverse modifiche per miglio-
} rare l’efficienza e la flessibilità del programma.
Una delle più interessanti consiste ad esempio
Download dei dati nell’impiegare un Real Time Clock I2C esterno
Una volta completata l’acquisizione è possibile (come il MAX1307) per fornire sia un riferimen-
scaricare i dati memorizzati inviando il comando to temporale più preciso, sia per attivare periodi-
“S” via seriale. Questo comando richiama la fun- camente (ad esempio ogni secondo) il PIC, per-
zione riportata nel Listato 6, che legge sequen- mettendogli di entrare nello stato di sleep duran-
zialmente i dati dalla EEPROM e li trasmette al te i periodi di inattività. Questo permette di
PC. Se era stata imposta una registrazione singo- ridurre significativamente i consumi del sistema,
FARE ELETTRONICA - APRILE 2007
la, i dati vengono letti a partire dall’inizio della e quindi di assicurarne una maggiore autonomia
memoria. Se è stata effettuata una registrazione se si usa un’alimentazione a batteria.
continua, viene controllato il numero dei dati
registrati, se questo è inferiore alla capacità di
memorizzazione, i dati vengono letti a partire
dall’inizio e fino al numero registrato. Se è supe-
riore, significa che i dati più vecchi presenti in
memoria inizieranno dalla locazione successiva a Codice MIP 262106
all’ultima impiegata, e dovranno essere letti in www.farelettronica.com/mip
maniera circolare.
Di Stefano- TEORIA - MikroC 11:- PRATICA 17-04-2007 16:43 Pagina 102
In questa puntata conclusiva della serie Con pochissimi componenti è quindi possibile
interfacciare un PIC a Ethernet. Occorre però
dedicata al MikroC verrà presentata implementare il firmare la gestione dei protocolli:
una delle più interessanti e promettenti questa operazione può essere più o meno com-
plessa a seconda delle funzionalità che si deside-
possibilità offerte da questo compilatore ra ottenere.
e dagli strumenti di sviluppo forniti dalla Come verrà mostrato nei prossimi paragrafi,
anche in questo caso il MikroC permette di sem-
102 Mikroelektronika: l’interfacciamento di plificare molto il lavoro necessario per realizzare
un PIC con una rete Ethernet. un’applicazione dotata di connettività di rete,
TEORIA
Utilizzo
dell’interfaccia
Ethernet di Antonio Di Stefano
TEORIA
zioni vengono svolte dalle
librerie.
Figura 2
Collegamento tra la scheda Ethernet e la EasyPIC3
La libreria SPI-Ethernet
La libreria che il MikroC mette a
disposizione per la gestione del 28J60 si chiama
tipico connettore RJ-45. Una volta inizializzato il SPI-Ethernet. Essa comprende diverse funzioni, tra
28J60, il componente gestisce completamente le
funzionalità del livello fisico e MAC (filtraggio dei N. BYTE CONTENUTO
pacchetti in base al loro indirizzo, ritrasmissione 6 Indirizzo MAC desinazione
in caso di errore, controllo della correttezza dei
6 Indirizzo MAC sorgente
pacchetti ricevuti, etc), mostrando al PIC soltanto
2 Tipo Ethernet (0x8000)
i registri di configurazione ed un buffer da 8KB
1 Versione e lunghezza (0x45)
che contiene sia i pacchetti ricevuti, che quelli
che si intende trasmettere. La scrittura e la lettu- 1 Tipo di Servizio (0x00)
ra dei pacchetti dal buffer avviene in modo simi- 2 Lunghezza totale
le a quanto visto a proposito delle EEPROM seria- 2 Identificativo pacchetto
li (si veda FE n.259). Una tipica applicazione quin- 2 Flag e offset frammento
di non deve fare altro che leggere i pacchetti che 1 Time to live (0xFF)
vengono ricevuti, decodificarli e generare gli
1 Protocollo (0x06=TCP, 0x11=UDP)
eventuali pacchetti di risposta. Le ultime due ope-
2 Checksum
razioni dipendono dal protocollo utilizzato. La
struttura di un pacchetto Ethernet che impiega il 4 Indirizzo IP sorgente
cui quelle più utili sono le seguenti: lizzate, e la lunghezza dei dati. Le funzioni devono
restituire la lunghezza dell’eventuale risposta gene-
void SPI_Ethernet_Init( rata, oppure 0.
unsigned char *resetPort, Per leggere e scrivere i dati dal buffer del 28J60 si
unsigned char resetBit, usano le due funzioni seguenti:
unsigned char *CSportPtr,
unsigned char CSbit, void SPI_Ethernet_putByte(unsigned char v);
unsigned char *mac, unsigned char SPI_Ethernet_getByte();
unsigned char *ip,
unsigned char fullDuplex); I dati vengono letti o scritti sequenzialmente nel
buffer. L’indirizzo di inizio è quello relativo all’inizio
Il suo scopo è quello di inizializzare il 28J60 e le del campo dati del pacchetto (sia in lettura che
porte del PIC, la funzione andrà quindi invocata scrittura). Nel caso della scrittura del pacchetto, le
prima di utilizzare le altre. I parametri sono rispet- routine provvederanno ad aggiungere gli header
tivamente: la porta e il bit usato per resettare il ed a trasmettere il tutto.
componente, la porta ed il bit usati come CS Nella libreria sono disponibili anche altre funzioni
(segnale di selezione per i dispositivi SPI), i punta- utili, che però non sono pubbliche. Queste posso-
tori agli array da 6 e 4 byte relativi all’indirizzo no comunque essere richiamate includendo il file
MAC ed IP da assegnare al dispositivo, e un flag “enc28j60_libprivate.h”, che contiene le intesta-
che indica se la linea che si sta utilizzando è full- zioni. Tra queste funzioni sono presenti quelle per
104 duplex o half-duplex. La funzione deve essere leggere e scrivere i registri del 28J60 o copiare
richiamata dopo avere richiamato la funzione blocchi di memoria.
TEORIA
TEORIA
SPI_Ethernet_doPacket(); unsigned int reqLength)
} {
} unsigned char len = 0;
rizzo dovrebbe essere unico!), l’IP è stato scelto tarsi che il pacchetto sia stato ricevuto corretta-
in uno dei range tipici usati per le reti locali, e mente dalla scheda. Dal momento che il protocol-
risulta statico (chiaramente anche in questo caso lo UDP non prevede meccanismi per garantire il
deve essere unico e nel formato utilizzato nella recapito dei pacchetti, può essere utile adottare
rete locale). Per testare il programma occorre tecniche di questo tipo.
collegare la scheda ad uno switch o router, a cui
è stato collegato anche un PC. Lanciando il Chiaramente i dati prelevati dal pacchetto possono
comando “ping 10.0.0.10” dalla linea di coman- essere utilizzati in modo arbitrario: ad esempio è
do, si dovrebbe ottenere la risposta da parte possibile includere comandi e dati per modificare
della scheda. lo stato delle porte di I/O.
Di Stefano- TEORIA - MikroC 11:- PRATICA 17-04-2007 16:43 Pagina 106
tura via SPI. Un elenco completo dei comandi e dei // Sel Bank 1
void main() }
{ len=buf[2];
int i; len=len|(buf[3]<<8);
ADCON1 |= 0x0F; }
PORTA = 0;
TRISA = 0x00; if (len&0x01) Spi_Read(temp);
PORTC=PORTC|0x02;
PORTB = 0;
TRISB = 0x0F; // Dec Pktcnt
Reg_Write(0x9E, 0x40);
FARE ELETTRONICA - MAGGIO 2007
i=0; }
temp[2]=’ ‘; SendString(“\n\r”);
temp[3]=’ ‘; Delay_ms(1000);
temp[4]=0; };
}
Usart_Init(9600); }
Spi_Init();
SPI_Ethernet_Init( void SendString(char *str)
&PORTC, 0, {
Di Stefano- TEORIA - MikroC 11:- PRATICA 17-04-2007 16:43 Pagina 107
Figura 3
Dump di un pacchetto UDP. I colori si riferiscono alle sezioni mostrate in Tabella 1, la parte gialla è quella aggiunta dal 28J60
TEORIA
if (c<10) e sugli eventuali errori. Letti i primi 6 byte, viene
c=c+’0’; estratta l‘informazione sulla lunghezza, ed utilizza-
else ta per leggere l’esatto numero di byte, che sono
c=c+’A’-10; inviati alla UART, dopo essere stati convertiti in esa-
str[0]=c; decimale e ASCII. Se il numero di byte è dispari
occorre fare una lettura aggiuntiva in modo che il
c=n&0x0F; puntatore si trovi ad un indirizzo pari (che sarà
if (c<10) quello di inizio del prossimo pacchetto). Il conte-
c=c+’0’; nuto di uno dei pacchetti ricevuti è visibile in
else Figura 3.
c=c+’A’-10;
str[1]=c; Conclusioni
Va ricordato che il MikroC ha un utile “UDP
} Terminal” che può essere richiamato dal menu
Tools. Questo programma permette di inviare pac-
void Reg_Write(char addr, char val) chetti UDP dal contenuto arbitrario e di riceverli,
{ può essere quindi utilizzato per provare i program-
PORTC=PORTC&0xFD; mi descritti. Occorre tenere presente inoltre che
Spi_Write(addr); potrebbe essere necessario modificare l’indirizzo IP
Spi_Write(val); usato nei programmi in base all’intervallo utilizza-
PORTC=PORTC|0x02; to nella propria rete locale. Un intervallo alternati-
} vo a quello riportato, utilizzato da molti router, è
{192, 168, 20, x}, dove x è un indirizzo unico asse-
char Reg_Read(char addr) gnato al dispositivo.
{ Si conclude con questa puntata la serie di articoli
FARE ELETTRONICA - MAGGIO 2007