Fare Elettronica - MikroC by Example

  • Upload
    alonsoty

  • View
    4.739

  • Download
    112

Embed Size (px)

DESCRIPTION

Examples of MikroC Projects found on "Fare Elettronica" magazine.

Citation preview

TEORIAPrima parte n 252 - Giugno 2006

RISORSE

SPECIALE

PRATICA

Lambiente di sviluppoSeconda parte n 253/254 - Luglio/Agosto 2006

Controllare le uscite del PICTerza parte n 255 - Settembre 2006

MikroC: By Example:Dal momento che su Fare Elettronica si gi parlato estesamente sia dei PIC che del linguaggio C, non dedicheremo molto spazio alla teoria, ma ci concentreremo soprattutto sugli aspetti pratici, sulle applicazioni e sugli esempi. Inizieremo con dei programmi molto semplici, per cui anche chi si fosse perso qualcosa, non dovrebbe avere alcun problema a seguirci (alla fine dellarticolo comunque verranno indicati alcuni riferimenti bibliografici per recuperare). IL MIKROC Il MikroC un ambiente di sviluppo prodotto dalla Mikroelektronika, societ jugoslava molto conosciuta per altri suoi prodotti di successo quali il MkroBasic o le schede di sviluppo EasyPIC. Il MikroC in particolare un compilatore che stato specificamente pensato per i microcontrollori PIC, ed quindi in grado di gestire tutte le caratteristiche peculiari dei vari modelli e produrre codice ottimizzato per questi dispositivi. In realt definirlo compilatore C piuttosto restrittivo, dal momento che il MikroC integra anche una grande quantit di strumenti ausiliari, sia per la scrittura del codice, sia per soddisfare molte delle esigenze che sorgono quando si programmano sistemi a microcontrollore. Altro aspetto molto interessante la presenza di una completa documentazione interattiva ed di una nutrita serie di funzioni di libreria pronte per essere utilizzate nelle applicazioni. Grazie a queste caratteristiche, utilizzando il MikroC possibile scrivere applicazioni complesse in pochissimo tempo, come verr mostrato in questa serie di articoli. Nel prossimi paragrafi analizzeremo in dettaglio le principali caratteristiche dellambiente di sviluppo. Il compilatore Il MikroC comprende un compilatore ANSI C che implementa praticamente tutti gli aspetti

Gestione di pulsanti, tastiere e display LCD

D80TeoriaFARE ELETTRONICA - GIUGNO 2006

opo il notevole successo riscosso dalla serie di articoli sul MikroBasic, vogliamo presentarvi, a partire da questa puntata, il MikroC: un ambiente di sviluppo, in ANSI C per PICmicro prodotto della MikroElektronika, simile al MikroBasic per semplicit di utilizzo ed efficienza. In questa puntata conosceremo gli strumenti messi a disposizione dal programma ed inizieremo ad usarlo con alcuni semplici esempi. Nelle prossime puntate utilizzeremo il MikroC per realizzare progetti sempre pi complessi ed interessanti.

Quello che ci proponiamo di fare a partire da questa puntata mostrare come realizzare una serie di interessanti applicazioni utilizzando i microcontrollori PIC ed il linguaggio C. Lambiente di sviluppo che utilizzeremo sar il MikroC v5.0, che inizieremo a conoscere in tutte le sue caratteristiche gi dal prossimo paragrafo. Com noto il linguaggio C, al pari di altri linguaggi ad alto livello (Basic o Pascal), permette di scrivere programmi complessi in maniera semplice e veloce, per rispetto a questi produce un codice mediamente pi compatto e veloce, simile a quello che si otterrebbe programmando in assembler. Il C quindi permette di sfruttare meglio le caratteristiche del microcontrollore, e di controllare pi accuratamente il suo funzionamento e le sue periferiche.

Lambiente di sviluppostandard del linguaggio, e che stato appositamente pensato per i microcontrollori PIC (tutti i modelli della serie 12, 16 e 18). Il compilatore in grado di generare dal codice C direttamente il codice oggetto (cio i file .hex caricabili sul PIC) o anche codice assembler leggibile, ed eventualmente modificabile dallutente. Il compilatore supporta tutti i tipi di dati previsti dallANSI C, sia quelli interi che quelli floating point, utilizzando per questi ultimi un formato a 32 bit compatibile con lo standard IEEE-754. In questultima versione possibile richiamare le funzioni in maniera annidata e ricorsiva (nei limiti consentiti dallo stack del PIC). Per rendere pi efficiente il codice generato, il MikroC applica una serie di ottimizzazione automatiche in fase di compilazione. Oltre agli aspetti standard del linguaggio, il compilatore dotato di alcune estensioni dedicate, utili per interagire con i PIC. Ad esempio possibile gestire in maniera molto semplice le routine dinterruzione o la posizione delle variabili allinterno della memoria.

di Antonio Di Stefano

Figura 1 Lambiente di sviluppo MikroC

Lambiente di sviluppo La Figura 1 mostra unimmagine panoramica del ricco ambiente di sviluppo (IDE) offerto dal MikroC. Nonostante labbondanza di strumenti, scrivere e compilare un programma molto semplice. Larea pi grande visibile in figura quella riservata alla scrittura del codice (Code Editor). Il codice scritto viene automaticamente colorato per distinguerne i diversi elementi (istruzioni, costanti, commenti, tipi, etc.). Questo facilita molto la lettura e la comprensione del codice, e pu evidenziare la presenza di eventuali errori di scrittura. Esiste anche una funzione personalizzabile che corregge gli errori di digitazione direttamente mentre si scrive il testo (!). Altre funzioni utili sono quelle che permettono di commentare o de-commentare le sezioni di codice evidenziato, o di indentarlo. Due strumenti utili mentre si scrive il codice sono il Code Assistant, ed il Parameter Assistant: due piccole finestre pop-up che servono a ricercare o a completare automaticamente il nome delle funzioni che si vuole richiamare, o i loro parametri, evitando di consultare continuamente la guida o altri punti del codice. Sulla sinistra (Figura 2) si trova il Code Explorer, dove vengono riassunti tutti gli elementi inseriti nel codice: funzioni, etichette, costanti, e variabili con il loro valore e ambito di visibilit. Cliccando su una qualsiasi delle voci verr evidenziato nel codice la sua posizione. Questo risulta

81TeoriaFARE ELETTRONICA - GIUGNO 2006

TEORIAPrima parte

RISORSE

SPECIALE

PRATICA

MikroC By Example: Lambiente di sviluppo

utilissimo sia per trovare velocemente gli elementi nel codice, sia per evitare errori nelluso delle variabili globali, o con le ri-definizioni e linizializzazione delle variabili. Il tab posto accanto, denominato Qhelp, mostra un elenco di tutte le funzioni di libreria integrate nel compilatore (sia quelle standard del C che le librerie per le funzioni avanzate). Cliccando su una delle voci si aprir la guida in cui la funzione viene descritta in dettaglio, spesso anche con degli esempi di utilizzo. Il piccolo riquadro sottostante riassume le propriet del progetto corrente: il modello di PIC da utilizzare, la sua frequenza di lavoro

(usata in fase di simulazione e per determinare il valore di alcune costanti), e lelenco dei files che compongono il progetto. In basso trova posto la finestra dei messaggi, in cui vengono visualizzati i risultati di compilazione e gli eventuali messaggi di errore. Nella stessa zona presente un pratico convertitore di dati decimali / binari / esadecimali, chiamato Qconvertor. I tool aggiuntivi Come accennato prima, il MikroC offre una grande quantit di strumenti aggiuntivi oltre a quelli strettamente indispensabili per scrivere il codice e compilarlo. Questi tool possono aiutare moltissimo nella fase di creazione dei programmi e nei test, e risulta molto comodo averli integrati in un unico ambiente. Un primo strumento legato al compilatore quello che permette di analizzare il codice prodotto, in termini di occupazione di memoria (Fig. 3). E possibile tenere sotto controllo loccupazione della ROM (o Flash) e della RAM del PIC, lo spazio occupato dalle diverse funzioni del programma e la loro distribuzione in memoria. Analizzando questi dati possibile in modo molto rapido capire come ottimizzare il codice dal punto di vista delloccupazione di memoria. Gli altri strumenti, dai pi semplici a quelli pi

82Teoria

Figura 2 Il Code Explorer

FARE ELETTRONICA - GIUGNO 2006

Figura 3 Strumenti di analisi delloccupazione di memoria

sofisticati, sono richiamabili dal menu Tools. Tra quelli pi semplici abbiamo una sempre utile tabella ASCII ed un editor per caratteri a 7 segmenti (Fig. 4), che permette di disegnare il carattere voluto, ed ottenere il valore numerico corrispondente ai segmenti accesi e spenti. Tra gli strumenti pi sofisticati spiccano lUSART Terminal (Fig. 5) che pu essere utilizzato per comunicare via seriale (RS232) con un qualsiasi dispositivo o sistema esterno. E possibile gestire la comunicazione impostando tutte le consuete opzioni, inviare i dati (digitandoli) e visualizzare in tempo reale quelli ricevuti dal dispositivo esterno. Esistono

Figura 4 Editor per display a 7 segmenti

anche altri tipi di terminali, che hanno un utilizzo simile, ma ambiti diversi: lHID Terminal, usato per comunicare con dispositivi USB HID e che ingloba anche una funzione per la creazione dei descrittori USB (la classe HID utilizzata da dispositivi come joysick, mouse o tastiere, ma utilizzabile anche per trasmettere in maniera semplice dati ad un PC via USB); lUDP Terminal permette di scambiare dati utilizzando una connessione di rete ed il protocollo UDP. LMMC Card Terminal invece utilizzato per leggere blocchi di dati da una memoria tipo Multimedia Card (MMC) o Secure Digital (SD). Come vedremo la presenza di questi strumenti dovuta al fatto che il MikroC offre delle funzioni di libreria per interfacciarsi a questi tipi di dispositivi. 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 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 documentazione del MikroC, che scaricabile dal sito del produttore. Una prima classe di funzioni sono quelle per la gestione dellhardware del PIC. In questa classe sono comprese funzioni per la gestione della UART (sia hardware che emulata via software), del generatore PWM e del convertitore Analogico/Digitale. Un'altra classe implementa algoritmi per la gestione di hardware esterno comune: tasti, display a LED, display LCD e display grafici, tastiere (a matrice o anche PS2), generazione di suoni, EEPROM seriali, Flash, etc. Unaltra classe ancora permette di gestire diversi tipi di interfacce e protocolli, anche molto complessi, quali SPI, I2C, RS485, CAN, Ethernet, memorie Compact Flash, e memorie MMC o SD (con il supporto del file system FAT). Sono anche presenti delle librerie con funzioni

83Teoria

Figura 5 LUSART Terminal

FARE ELETTRONICA - GIUGNO 2006

Figura 6 Editor per display grafici

TEORIAPrima parte

RISORSE

SPECIALE

PRATICA

MikroC By Example: Lambiente di sviluppo

che facilitano la conversione tra tipi diversi (es. da numero float a stringa e viceversa), ed alcune operazioni trigonometriche. Il debugger Il MikroC comprende anche un source code debugger cio un simulatore che permette di eseguire il codice creato sul PC, per capire se si comporta come voluto. Questo strumento molto importante per eseguire un primo test del programma o di alcune sue routine. Il funzionamento molto semplice: una volta compilato il programma, possibile eseguirlo (anche in modalit passo-passo), ed osservare il suo comportamento. Lesecuzione del programma pu essere seguita sia sulla finestra del codice, sia su delle finestre aggiuntive che mostrano il contenuto della RAM, quello dei registri interni e dello stack, e sulla finestra del clock, che pu essere usata per valutare il tempo di esecuzione delle routine. I valori della RAM e dei registri possono essere modificati dallutente durante lesecuzione, modificando quindi il comportamento del programma. Questo risulta indispensabile in alcuni casi, in quanto il debugger non simula in dettaglio il comportamento di alcuni dei circuiti interni del PIC, come ad esempio i timer, gli ADC, le interruzioni, etc. Per facilitare losservazione dei valori assunti in particolari punti del programma, si possono piazzare dei breakpoint, che interrompono momentaneamente lesecuzione.

84Teoria

IL PRIMO PROGETTO Per prendere confidenza con lambiente di sviluppo iniziamo con un progetto molto semplice, il classico Hello world! del mondo dei microcontrollori: faremo lampeggiare un LED. Il programma molto semplice e si presta bene a essere usato come cavia per le prime sperimentazioni: una volta capito come fare lampeggiare un LED non difficile creare pattern via via pi complessi, iniziare a giocherellare con le altre periferiche, e creare programmi molto pi vari ed interessanti. Lo schema elettrico che utilizzeremo quello mostrato in Figura 7: il PIC collegato nel modo usuale allalimentazione, ad un quarzo da 4MHz, e sul primo piedino della porta B stato collegato un LED con una resistenza per limitare la corrente. Va notato che useremo un PIC 16F84, ma questo particolare potrebbe essere del tutto irrilevante: un programma scritto in C infatti, a differenza di uno scritto in assembler praticamente indipendente dal microcontrollore usato! Se scriviamo bene il nostro codice, con piccole modifiche esso potr funzionare non solo su diversi modelli di PIC, ma anche su diversi tipi di microcontrollori o processori (ad esempio AVR, 8051, ARM, etc.). Questo uno dei maggiori vantaggi offerti dal C. Per creare il nostro primo progetto iniziamo avviando il MikroC, e selezionando dal menu Project la voce New Project. Si aprir la finestra visibile in Figura 8. Inseriamo il nome del progetto (in questo caso LEDBlink), il percorso in cui vogliamo salvare i file prodotti, una breve descrizione del progetto (in generale documentare i progetti importante!). Scegliamo come dispositivo un PIC16F84 ed una frequenza di clock di 4MHz. Dalle opzioni sottostanti possibile modificare i fuses del dispositivo, in questo caso usiamo il pulsante Default per selezionare quelli predefiniti (oscillatore HS, e Watchdog disabilitato). Dopo avere dato conferma, potremmo scrivere nellapposita finestra il seguente codice:

FARE ELETTRONICA - GIUGNO 2006

Figura 7 Schema usato per fare lampeggiare il LED

TEORIAPrima parte

RISORSE

SPECIALE

PRATICA

MikroC By Example: Lambiente di sviluppo

void main() { PORTB = 0; TRISB = 0; while(1) { PORTB = 1; Delay_ms(500); PORTB = 0; Delay_ms(500); } }

86Teoria

Il codice non scritto in modo molto elegante, per utile per capire come funziona: la funzione main quella che verr eseguita allavvio, allinizio viene assegnato il valore 0 a PORTB (che indica il valore assunto dai piedini della porta B del PIC), e TRISB (che determina la direzione dei pin, 0 indica che sono stati configurati tutti come uscite). A questo punto inizia un ciclo infinito realizzato con listruzione while. Dentro al ciclo viene assegnato il valore 1 a PORTB, cio viene portato alto il piedino RB0. Quindi viene richiamata una routine che genera un ritardo di 500ms (mezzo secondo), viene portato basso il piedino RB0, e vengono attesi altri 500ms, quindi il loop si ripete. A questo punto utile una piccola spiegazione: per capire su quale piedino della porta B agiamo, dobbiamo considerare lespressione binaria del numero che abbiamo utilizzato, ciascun bit rappresenta ordinatamente un piedino della porta. Se avessimo voluto accendere i pin RB0 ed RB1 assieme (valore binario 00000011), avremmo dovuto usare il valore decimale 3. Per facilitare questo tipo di operazioni il MikroC riconosce anche i numeri scritti direttamente in binario,

basta farli precedere da 0b (in questo caso ad esempio potremmo scrivere 0b00000011). possibile anche usare il Qconvertor posto in basso per eseguire questo tipo di conversioni. Una piccola nota importante: tutti i programmi che scriveremo saranno sempre racchiusi da, o termineranno con, un loop infinito (eventualmente vuoto). Questo necessario perch altrimenti, una volta terminata la funzione main, il programma si trover in una condizione indefinita: potrebbe bloccare il microcontrollore, compiere delle azioni imprevedibili, o ripetersi in modo non corretto. Chi conosce il C o ha gi usato altri compilatori, avr notato che non stato necessario includere nessuna libreria: il MikroC infatti provvede automaticamente a includere le definizioni relative al PIC usato (come PORTB e TRISB), e diverse funzioni di libreria. Per compilare il nostro programma, usiamo il pulsante Build Project (quello con gli ingranaggi in alto), o lequivalente voce del menu Project. Il report di compilazione sar visibile nella finestra in basso. Se diamo unocchiata alle statistiche sulloccupazione di memoria vediamo che il nostro programmino occupa 74 word nella Flash del PIC. Proviamo a scriverlo in un modo un po pi ottimizzato:void main() { PORTB = 0; TRISB = 0; while(1) { PORTB = PORTB^0b00000001; Delay_ms(500); } }

Figura 8 Finestra per limmissione dei dati del progetto

Per ottenere il comportamento intermittente abbiamo usato loperatore XOR del C (laccento circonflesso ^). LXOR ha leffetto di invertire i bit della variabile in corrispondenza dei bit 1 indicati nelloperando, in questo caso quindi invertiamo solo il primo bit, quello corrispondente a RB0. Alla seconda inversione, il bit torna come prima, ottenendo leffetto intermittente. Il programma quindi funzioner esattamente

FARE ELETTRONICA - GIUGNO 2006

come prima. Quanto occupa il nostro programma questa volta? Soltanto 42 word! Questo risultato dovuto sia alla maggiore compattezza del programma, sia al fatto che Delay_ms una macro, non una funzione, quindi prima veniva effettivamente copiata due volte nel programma! E se volessimo far lampeggiare due led, uno su RB0 e laltro su RB1, in modo alternato? (Schema in Figura 9). Ecco come modificare il programma:void main() { PORTB = 0b00000010; TRISB = 0; while(1) { PORTB = PORTB^0b00000011; Delay_ms(500); } }

RIFERIMENTI Il MikroC pu essere scaricato dal sito Internet del produttore allindirizzo: www.mikroelektronika.co.yu Maggiori informazioni sui PIC possono essere trovate sul corso PIC By Example pubblicato su Fare Elettronica (numeri da 157 a 176) e sul CDROM omonimo, o sul libro della serie Conoscere ed usare dal titolo PICmicro di Maurizio Del Corso e Tiziano Galizia, edito dalla Inware. Maggiori informazioni sul linguaggio C si possono trovare nella serie di articoli Vitamina C pubblicato su Fare Elettronica (numeri da 217 a 246), o sul CD-ROM omonimo, o sul libro della serie Conoscere ed usare dal titolo Il Linguaggio ANSI C di Antonio Di Stefano, edito dalla Inware Edizioni. Alcune spiegazioni pi dettagliate sugli algoritmi e sui circuiti utilizzati in alcuni degli esempi (compresa la scheda EasyPIC) si possono trovare nel tutorial sul MikroBasic, pubblicato su Fare Elettronica (dal numero 238). CONCLUSIONI Nella prossima puntata considereremo degli esempi un po pi complessi, che partendo da quelli appena visti ne espanderanno molto le possibilit utilizzando istruzioni e costrutti pi potenti, per gestire il flusso del programma e le temporizzazioni. Non mancate! Codice MIP252080

87Teoria

Abbiamo modificato soltanto due parametri: il valore iniziale (allinizio un LED sar gi acceso, laltro spento), ed abbiamo fatto in modo che venissero invertiti entrambi i bit meno significativi.

Se vogliamo provare i nostri programmi con il debugger, possiamo richiamare la voce Start Debugger dal menu Run, ed usare le opzioni di step (stesso men, oppure tasti F7 ed F8). Se invece vogliamo provare il codice direttamente sul circuito vero e proprio, dopo la compilazione avremo a disposizione il file .hex da caricare nel PIC. Potremo usare lo stesso MikroC se stiamo usando una delle schede EasyPIC (il download avviene via USB!), oppure potremo usare un programma esterno qualsiasi (come il noto IC-Prog) ed il nostro programmatore preferito. I LED dovrebbero iniziare a lampeggiare immediataFigura 9 Schema per laccensione di due LED alternati mente, come voluto.

FARE ELETTRONICA - GIUGNO 2006

TEORIAPrima parte n 252 - Giugno 2006

RISORSE

SPECIALE

PRATICA

Lambiente di sviluppoSecondo parte n 253/254 - Luglio/Agosto 2006

Controllare le uscite del PICTerza parte n 255 - Settembre 2006

Gestione di pulsanti, tastiere e display LCD

MikroC by Example:siderare, dal momento che ciascuna di esse pu adattarsi meglio a specifiche applicazioni. Supponiamo ad esempio di utilizzare 8 LED, ciascuno collegato ad un piedino della porta B come mostrato in figura 2, e di volerli accendere in sequenza nelle due direzioni (il classico effetto supercar). Le alternative pi convenienti sono due: in un caso possiamo utilizzare gli operatori del C che permettono di manipolare i bit, nellaltro possiamo utilizzare una tabella di consultazione (look-up table). Consideriamo il primo caso, cio partiamo da

I104Teoria

n questa puntata scopriremo come scrivere in C degli algoritmi dedicati alla gestione delle uscite dei PIC, per comandare LED, display ed altri dispositivi, utilizzando le tecniche pi efficienti e gli strumenti messi a disposizione dal MikroC.

GENERAZIONE DI PATTERN E SEQUENZE Nella scorsa puntata abbiamo mostrato il codice 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:void main() { PORTB = 0; TRISB = 0; while(1) { PORTB = PORTB^0b00000001; Delay_ms(500); }FARE ELETTRONICA - LUGLIO/AGOSTO 2006

Figura 1 Schema usato per fare lampeggiare il LED

}

Il programma molto semplice: utilizza solamente unoperazione di XOR (loperatore ^ del C) per ottenere linversione del primo bit della porta B (e quindi il lampeggio del LED), ed una routine di ritardo per determinarne la frequenza. Se dovessimo generare delle combinazioni pi complesse (come avviene in molte applicazioni reali) questo approccio potrebbe non essere adeguato. Esistono diverse possibilit che il caso di con-

Figura 2 Schema usato per accendere i LED in sequenza

Controllare le uscite del PICdi Antonio Di Stefano

una configurazione delle uscite, ed otteniamo le altre operando sui bit. Il codice il seguente:void main() { char dir; /* Direzione di scorrimento 1=sinistra, 0=destra */ dir=1; // Inizializz. porta B PORTB = 0x01; TRISB = 0; // Loop infinito while(1) { // Raggiunti bordi? if (PORTB&0x01) dir=1; if (PORTB&0x80) dir=0; // Aggiornamento direzione if (dir) { PORTB = PORTB > 1; } Delay_ms(100); } }

porta B sono state configurate tutte come uscite (TRISB=0), e soltanto il primo piedino stato posto alto (PORTB=0x01). Ricordiamo che il MikroC permette di esprimere i valori numerici anche in binario (anteponendo 0b al numero), ma abbiamo preferito utilizzare la notazione esadecimale per rendere il codice maggiormente portabile. Per convertire questi valori in binario si pu utilizzare il convertitore Qconvertor, che si trova in basso nella finestra del messaggi del MikroC. Allinterno del loop principale viene dapprima verificato se il LED attualmente acceso il primo o lultimo, e in ciascuno di questi due casi viene cambiata la direzione dello scorrimento. Per eseguire questo controllo stata utilizzata listruzione if del C: solo se la condizione dentro le parentesi verificata lespressione che segue vene eseguita. Lespressione che viene controllata lAND binario tra i bit della porta B e 0x01 (oppure 0x08). Questa espressione dar 0x01 solo se il bit meno significativo della porta B sar alto (lo stesso per il pi significativo nel caso di 0x80), altrimenti zero. Per maggiore chiarezza avremmo potuto scrivere:if ((PORTB&0x01)==0x01) dir=1; if ((PORTB&0x80)==0x80) dir=0;

105TeoriaFARE ELETTRONICA - LUGLIO/AGOSTO 2006

Il funzionamento del programma dovrebbe risultare abbastanza intuitivo: inizialmente viene dichiarata una variabile (dir) per tenere traccia della direzione di scorrimento, in seguito vengono inizializzate le variabili e le porte, e poi viene eseguito il loop principale. Durante il funzionamento la variabile dir assumer soltanto due valori (scelti da noi), quindi conveniente dichiararla del tipo pi piccolo possibile gestito dal C, cio char (8 bit). Le linee della

ma ricordiamo che il C considera vera qualsiasi espressione che non valga 0, quindi anche non indicando il valore atteso otteniamo lo stesso risultato. Abbiamo usato lo stesso accorgimento per il frammento di codice successivo, che quello che si occupa dellaggiornamento della posizione. Se la variabile dir vale 1 viene eseguito uno scorrimento binario di una posizione a sinistra (a destra nellimmagine), altrimenti (else) viene eseguito uno scorrimento a destra (a sinistra nellimmagine). Gli scorrimenti (operatori del C) produrranno la sequenza di valori: 0x01, 0x02, 0x04, 0x08,

TEORIASeconda parte

RISORSE

SPECIALE

PRATICA

MikroC by Example: Controllare le uscite del PIC

0x10, 0x80, e poi a ritroso (quando cambier la direzione di scorrimento) fino a 0x01. Dopo ogni scorrimento attendiamo 100ms usando lapposita routine di libreria Delay_ms, messa a disposizione dal MikroC, e ripetiamo lintera routine, allinfinito. Consideriamo adesso un altro approccio per ottenere lo stesso risultato. In questo caso utilizzeremo una look-up table per memorizzare le configurazioni delle uscite che vogliamo ottenere. Il codice il seguente:void main() { char n=0; char leds[14]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02}; // Inizializz. porta B TRISB = 0; // Loop infinito while(1) { PORTB=leds[n]; n++; if (n==14) n=0; Delay_ms(100); } }

106Teoria

dichiarazione dellarray. Inoltre abbiamo dichiarato unaltra variabile (n) che verr utilizzata come contatore, cio come indice per scorrere la tabella. Nel loop principale assegniamo direttamente il valore corrente della tabella alla porta B, inoltre incrementiamo lindice n (con listruzione n++). Quando lindice raggiunger il valore 14, sar riportato a 0, e quindi il conteggio ripartir da questo valore. Notare la differenza tra == ed = nellistruzione if. Ricordiamo che il primo un operatore relazionale, che controlla se il valore dellespressione di sinistra uguale a quello dellespressione di destra (restituendo un valore di verit). Laltro operatore invece assegna un valore ad una variabile. Questa seconda versione del programma, sebbene richieda un po pi di memoria, ha un vantaggio importante: basta cambiare i valori in tabella per ottenere comportamenti diversi. Si provi ad esempio ad utilizzare questi valori:char leds[14]={0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42};

FARE ELETTRONICA - LUGLIO/AGOSTO 2006

Per creare la tabella di consultazione abbiamo utilizzato un array (leds[]), in cui abbiamo inserito manualmente le configurazioni delle uscite volute (che sono le stesse che abbiamo ottenuto col programma precedente). Ci occorrono soltanto 14 voci per la tabella, che sono state inizializzate direttamente nella

Ci saranno due LED accesi che si muoveranno in direzione opposta (basta convertire in binario i valori per rendersene conto). Lapproccio usato nel primo programma invece risulta pi flessibile quando le configurazioni utilizzate non sono sempre le stesse, ma variano nel tempo, magari in base a condizioni esterne. PILOTARE I DISPLAY A 7 SEGMENTI I display a 7 segmenti rappresentano un economico e funzionale dispositivo di visualizzazione. 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

TEORIASeconda parte

RISORSE

SPECIALE

PRATICA

MikroC by Example: Controllare le uscite del PIC

108Teoria

lizzarli. Un display a 7 segmenti composto da 8 LED disposti a formare 7 segmenti pi un punto decimale (non sempre presente), con cui possibile rappresentare numeri, lettere e simboli grafici. I display a 7 segmenti sono disponibili in due versioni, che differiscono per i collegamenti dei LED: in entrambi i casi i LED possono essere pilotati indipendentemente da un terminale, mentre laltro comune a tutti. Il terminale comune pu essere lanodo o il catodo dei LED (e da questo particolare deriva il nome del display). Quando il terminale comune il catodo (figura 3), questultimo sar collegato a massa, e per accendere un segmento sar sufficiente fornire unalimentazione positiva al rispettivo anodo (ad esempio utilizzando un piedino di uscita portato a livello logico alto). Nel caso di display ad anodo comune (figura 4), questo terminale verr collegato al positivo dellalimentazione, e per accendere un segmento sar necessario portare a massa il catodo del segmento che si vuole accendere (usando un piedino di uscita a livello logico basso). Per pilotare un display a 7 segmenti avremo bisogno quindi di almeno 8 uscite del PIC, e con queste potremo gestire soltanto un carattere. Per fare le prime prove colleghiamo il display al PIC come mostrato in figura 5 (stiamo quindi utilizzando un display a catodo comune): i segmenti verranno pilotati tramite i piedini della porta B. Possiamo quindi procedere come negli esempi visti fino ad ora, lunico problema che dobbiamo ricavare per ogni carattere che vogliamo visualizzare il corrispondente valore da inviare alla porta B (che esprime quali segmenti sono accesi e quali spenti). Per fare questo possiamo utilizzare lap-

posito strumento messo a disposizione dal MikroC, richiamabile selezionando la voce Seven Segment Convertor dal menu Tools (figura 6). sufficiente disegnare il carattere che vogliamo visualizzare per avere il valore numerico corrispondente ad uno dei due tipi di display. Nel nostro caso ricaveremo il valore per le cifre da 0 a 9 e per le lettere da A, b, c, d, E ed F (che ci potrebbero servire per rappresentare valori esadecimali). Un modo molto semplice per associare questi caratteri ai valori numerici consiste nellutilizzare un array. Vediamo quindi come realizzare un programma che conta continuamente da 0 a 9:void main() { char n=0; char segs[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71}; // Inizializz. porta B TRISB = 0; // Loop infinito while(1) { PORTB=segs[n]; n++; if (n==10) n=0; Delay_ms(1000); } }

Figura 5 Collegamento al display a 7 segmenti

Come si pu notare il programma quasi identico a quello visto precedentemente, sono stati modificati soltanto i valori contenuti nellarray, che in questo caso codificano i caratteri voluti. Se si estende il conteggio fino a 16 sar possibile visualizzare anche le cifre Figura 6 Il convertitore per display esadecimali da A a 7-seg F. Non possiamo

FARE ELETTRONICA - LUGLIO/AGOSTO 2006

superare 16 perch altrimenti leggeremmo una posizione dellarray che non esiste, ottenendo un risultato imprevedibile. E se volessimo utilizzare pi cifre, e quindi pi unit a 7 segmenti? Occorrerebbe utilizzare molte pi porte di I/O, oppure ricorrere alla tecnica del multiplexing, molto utilizzata in questi casi. Occorre collegare i display come mostrato in figura 7 ed utilizzare soltanto 4 linee di I/O aggiuntive (questa volta provenienti dalla porta A) per gestire le 4 cifre. Il funzionamento semplice: le linee della porta B saranno condivise da tutti i display, che quindi riceveranno gli stessi dati, ma soltanto un display alla volta sar acceso, comandando attraverso la porta A i transistor BJT sui cui collettori si trovano i display. In questo modo riusciamo a comandare individualmente i singoli display: se vogliamo visualizzare un carattere sul display pi a sinistra, dovremo inviare il codice del carattere sulla porta B e portare alto soltanto RA0. Ovviamente soltanto un display alla volta potr essere acceso. Occorre quindi accenderli in successione ad una velocit tale da non farne percepire allocchio lo spegnimento. Per ottenere questo effetto sufficiente accendere ogni cifra almeno ogni 20ms. Dal momento che le cifre sono 4, dovremo tenerle accese singolarmente meno di 5ms. Per evitare un effetto di sfarfallamento possiamo anche usare una velocit maggiore (senza esagerare, altrimenti otterremo una bassa luminosit). Riassumendo: Sulla porta B dovranno essere inviati ciclicamente i valori corrispondenti alle 4 cifre che vogliamo visualizzare. Sulle porta A dovr essere portata alta una sola linea alla volta, quella corrispondente alla cifra da visualizzare (avremo quindi ciclicamente 0b0001, 0b0010, 0b0100, 0b1000). Il codice che implementa questo comportamento il seguente:void main() { char n, ds; char segs[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};

char cifra[4]={1,2,3,4}; // Inizializz. porte TRISA = 0; TRISB = 0; // Loop infinito while(1) { ds = 1; for(n=0; n>2); dato[2] = (char)(Adc_Read(2)>>2); dato[3] = (char)(Adc_Read(3)>>2); } else { // Modalit AABT void EEPROM_Wr(unsigned addr, char data) { // Issue I2C start signal I2C_Start(); // Send byte via I2C I2C_Wr(0xA0); // Send byte (MSB address) I2C_Wr((addr>>8)&0xFF); // Send byte (LSB address) I2C_Wr(addr&0xFF); // Send data (data to be written) // Configura porta A come I/O digitale ADCON1 = 0xFF; PORTA TRISA = 0xFF; = 0xFF; char EEPROM_Rd(unsigned addr) Delay_us(120); Ow_Reset(&PORTA,5); // Comando SKIP_ROM Ow_Write(&PORTA,5,0xCC); // Comando CONVERT_T Ow_Write(&PORTA,5,0x44); Delay_us(120); Ow_Reset(&PORTA,5); // Comando SKIP_ROM Ow_Write(&PORTA,5,0xCC); // Comando READ_SCRATCHPAD Ow_Write(&PORTA,5,0xBE); Delay_ms(1); // Lettura LSB tt = Ow_Read(&PORTA,5); // Lettura MSB tt = tt+(Ow_Read(&PORTA,5)2); dato[1] = (char)(Adc_Read(1)>>2); dato[2] = PORTB;

I2C_Wr(data); I2C_Stop(); }

{ char k; // Issue I2C start signal I2C_Start(); // Send byte via I2C I2C_Wr(0xA0); // Send byte (MSB address) I2C_Wr((addr>>8)&0xFF); // Send byte (LSB address) I2C_Wr(addr&0xFF); // Issue I2C start signal I2C_Repeated_Start(); // Send byte (device address + R) I2C_Wr(0xA1); // Read the data (NO acknowledge) k = I2C_Rd(0); I2C_Stop(); return k; } (device address + W)

ADCON1=0x82; PORTA=0; TRISA=0xFF; } }

Scrittura e lettura dalla EEPROM Anche in questo caso le routine utilizzate (visibili nel Listato 3) sono simili a quella descritte nel

Memorizzazione dei dati La funzione di memorizzazione, scrive i 4 dati acquisiti sulla memoria (sequenzialmente), provvedendo anche ad aggiornare il puntatore allultimo dato scritto, ed il numero complessivo dei campioni (questa caratteristica utile per recu-

perare correttamente i dati, anche se il datalogger viene spento). Essa responsabile inoltre dellarresto del campionamento, quando viene raggiunto il numero di campioni prestabilito, o lindirizzo finale della zona riservata ai dati. Il codice della funzione riportato nel Listato 4.Listato 4void Memorizza(void) { // Memorizza campioni EEPROM_Wr(config.data_ptr, dato[0]); config.data_ptr++; EEPROM_Wr(config.data_ptr, dato[1]); config.data_ptr++; EEPROM_Wr(config.data_ptr, dato[2]); config.data_ptr++; EEPROM_Wr(config.data_ptr, dato[3]); config.data_ptr++; config.n_campioni++; // Memorizza puntatore e num. campioni EEPROM_Wr(ADDR_INFO+2, (config.n_campioni)&0xFF); EEPROM_Wr(ADDR_INFO+3, (config.n_campioni>>8)&0xFF);

EEPROM_Wr(ADDR_INFO+4, (config.data_ptr)&0xFF); EEPROM_Wr(ADDR_INFO+5, (config.data_ptr>>8)&0xFF); // Controllo fine memoria if ((config.n_campioni==N_SAMP)|| (config.data_ptr>ADDR_END)) { if (config.loop) { config.data_ptr=0; } else { config.logging=0; } } }

Memorizzazione configurazione Anche i parametri relativi alla configurazione attuale sono memorizzati nella EEPROM per consentire di separare la fase di programmazione (che necessita di un PC), dalleffettivo impiego per il campionamento, che pu avvenire anche in maniera autonoma. I parametri della configurazione sono memorizzati in due byte: il primo contiene il periodo di campionamento, mentre il

109TEORIA

Compilatore MikroCUn potente compilatore C per PICmicro Code Editor Code Explorer Debugger StatisticheTutto in un ambiente Windows facile ed intuitivoUn set di strumenti veramente indispensabili per sviluppare applicazioni con i PICmicroCodice MIP 262109FARE ELETTRONICA - APRILE 2007

Ordinalo subito su www.ieshop.it oppure telefona allo 02.66504755

secondo gli altri parametri ad 1 bit accorpati assieme. La funzione di lettura (Config_Load) legge ed aggiorna anche il valore del puntatore e del numero di campioni memorizzati nella EEPROM (che occupano i 4 byte successivi alle altre informazioni). Il codice delle funzioni mostrato nel Listato 5.Listato 5void Config_Store(void) { unsigned char x; EEPROM_Wr(ADDR_INFO, config.periodo); x=config.canali>1)&0x01; config.monitor=x&0x01; config.n_campioni=EEPROM_Rd(ADDR_INFO+2)+ (EEPROM_Rd(ADDR_INFO+3)