Programma di test - LED
Diamoci ora da
fare nell'impostare il nostro primo programma in C.
Dal menu' scegliamo File -> New per creare un file nuovo vuoto.
Ora senza scriverci nulla lo salveremo con il nome che ci interessa
PICColino.c nella stessa directory del nostro progetto.
Dal menu' scegliamo dunque File -> Save As e
confermiamo dopo esserci posizionati nella corretta directory.
A questo punto il file Untitled verra' correttamente
nominato PICColino_1.c come evidenziato nella barra del titolo. A questo punto
nella finestra del progetto selezioniamo con il tasto destro del mouse Add Files e aggiungiamo al progetto il file vuoto precedentemente
creato cliccando su Apri.
Abbiamo cosi'
istruito il nostro compilatore su cosa dovra' compilare. Ora si tratta
di riempire il nostro file con qualche cosa di sensato o almeno cosi' si
spera.
Riselezioniamo dunque il nostro file vuoto ed iniziamo
a scrivere la testata del programma, ovvero tutte quelle informazioni che non
fanno parte del programma vero e proprio ma che ogni buon programmatore
inserisce in testa al proprio programma non fosse altro per ricordarsi in
futuro a che diavolo serve quanto scritto di seguito
Ognuno e'
libero ovviamente di inserire quello che gli pare purche' evidenzi che quanto
scritto va interpretato come COMMENTO e non come CODICE da parte del
compilatore.
Gia'
ma come faccio a generare un commento?
Semplice,
basta far precedere il commento da // ( valido solo sino a fine riga )
oppure inserire qualsiasi cosa anche su piu' righe tra una apertura di
commento /* ed una chiusura
*/ come visibile
nell'esempio.
Iniziamo ora
ad inserire quache cosa che incidera’ sulla generazione del codice binario
da inserire nel PIC.
Come prima
cosa iniziamo con iserire gli #include, Inserendo la riga
#include < p18F2620.h >
indichiamo
al compilatore che prima di procedere con la compilazione delle riche
successive deve aprire il file p18F2620 ed analizzare tutte le linee di detto
file come se queste fossero inserite nella posizione corrente. La ricerca del
file avverra' nella posizione standard in cui nelle impostazioni abbiamo detto
che sono memorizzati i files standard di inclusione.
Praticamente
con in file di inclusione e' come se incorporassimo il contenuto del relativo
file all'interno del nostro programma.
In particolare
nel file p18F2620 sono contenute tutte le dichiarazioni dei registri del
nostro PIC che ci consentiranno di richiamarli in maniera simbolica
all'interno del nostro programma.
E' buona cosa
dare un'occhiata a questo file per familiarizzarci con la nomenclatura delle
varie attribuzioni, anche senza voler per ora comprendere a fondo tutte le
sintassi che potranno anche apparirci del tutto astruse.
Per aprire il
file basta posizionarsi con il cursore del mouse sulla riga di include e con
il tasto destro scegliere dal menu' che apparira' Open File "p18F2620.h"
Avremo modo di
utilizzare abbondantemente la direttiva #include sia per includere i prototipi
delle funzioni di libreria ( vedremo oltre cosa cio' significa ) che porzioni
di codice che riterremo piu' opportuno accorpare in un file separato anziche'
nel solo file principale.
Abbiamo visto
che nel file p18F2620.h sono definiti i simboli che si riferiscono ai registri
del PIC. Nella stesura del nostro
programma faremo anche noi riferimento quasi esclusivamente a simboli per
accedere sia alla memoria che alle risorse hardware del PIC e della scheda.
Per il momento definiremo direttamente questi simboli all'interno del file
principale come illustrato qui di seguito.
In simbolo puo
essere creato utilizzando la direttiva:
#define nomesimbolo
yes"> attribuzione
Come prima
cosa iniziamo a definire simbolicamente le principali risorse hardware
del nostro PICcolino, i LED i Rele' e gli ingressi optoisolati.
Ciascuno
di questi segnali fa capo ad un bit di una porta per cui nella nostra
definizione del simbolo dovremo riuscire a far corrispondere tale definizione
con il corretto bit della porta.
Nel C per
accedere ad uno specifico bit all'interno
di un registro o di una variabile occorre aver preventivamente definito
delle strutture
di bit abbinate alla variabile cui si vuole accedere " a bit"
yes"> attraverso una
definizione di " union
". Il file p18F2620.h
contiene per buona parte queste definizioni per consentire l'accesso a bit dei
vari registri.
Senza entrare
ora in maggiori dettagli, lo faremo quando utilizzeremo strutture ed union per
definire dei bit a nostro uso e consumo, ci basti sapere che per definire
simbolicamente un bit occorre una sintassi di questo tipo:
#define simbolo
nomeunion.nomebitinstruttura
Con questa
regola, rispettando le definizioni del file p18F2620.h abbiamo definito i
nostri simboli.
Ci dobbiamo
ora mettere nei panni del
compilatore C. Per poter compilare correttamente, ovvero tradurre in
linguaggio macchina quanto da noi scritto sotto forma di istruzioni, e'
necessario che gli forniamo prima di iniziare la compilazione quante piu'
informazioni corrette possibili su come struttureremo il nostro programma.
Sebbene i
moderni compilatori si siano molto evoluti e riescano autonomamente e dedurre
molte informazioni anche quando non esplicitamente dichiarate, e' buona norma
rispettare un corretto standard di programmazione che richiede di definire in
anticipo il "formato" delle funzioni che verranno usate all'interno
del programma. Cosi' facendo il compilatore incontrando una funzione sapra'
come comportarsi senza generare errori o avvisi ( warning ). La definizione
preventiva di una funzioni viene
chiamata "prototipo della funzione"
Gia' ma cos'e'
esattamente una funzione per il C?
Chi e'
abituato a programmare i PIC in
assembler, potra' pensare che una funzione equivale ad una subroutine ed il
richiamo di una funzione sia ne piu' ne meno una CALL alla funzione stessa.
Non e' proprio
cosi'. La cosa e' abbastanza vera
nel caso di funzioni che non dispongano di argomenti ( parametri passati alla
funzione) ne di valori di ritorno, ovvero come nel nostro esempio parametri e
valore di ritorno vengono definiti come void
. Ben diverso e' invece quando una funzione dispone di uno a piu'
argomenti e / o di un valore di ritorno (sempre al massimo solo uno!).
E' in questi
casi come ne avremo modo di
apprezzare in seguito che si esprime tutta la potenza del C come linguaggio
strutturato.
Anticipiamo
per ora solo che il passaggio degli argomenti di una funzione avviene
attraverso lo stack e che dunque per tale motivo all'interno della funzione
non si lavora direttamente con le variabili "passate" ma con una
copia delle stesse ( quelle residenti nello stack ).
Ma
abbandoniamo per ora queste digressioni teoriche per concentrarci finalmente
con il nostro programma che
iniziera' con la scrittura delle funzioni per terminare da ultimo con la
funzione principale main() che deve
essere obbligatoriamente presente in ogni programma.
Di norma tale
funzione viene inserita in fondo al programma per una ragione molto semplice:
la funzione main contiene i richiami alle altre funzioni del programma. se
queste non fossero gia' state prese in considerazione dal compilatore questo
potrebbe non sapere esattamente come trattarle generando degli errori .
Mettendola in fondo non si corre questo rischio e si elimineranno perdite di
tempo alla ricerca degli errori.
La prima
funzione di cui facciamo conoscenza e' la Init_HW_PIC(void)
ogni funzione si divide in due parti: una dichiarazione
ed un corpo
la
dichiarazione precede il corpo ed oltre al nome della funzione definisce i
parametri della funzione. Come gia' accennato un argomento void indica che non
vengono passati parametri alla funzione mentre ad esempio ( int pippo )
indichera' che alla funzione viene passata la variabile pippo che risulta
essere un intero ( 16 bit ).
Il corpo della
funzione e' tutto quanto contenuto tra la parentesi graffa di apertura e quella di chiusura
void nomefunzione ( void )
{
}
Ogni
istruzione all'interno del corpo della funzione occupa di norma una riga e
termina con un ; ( esistono pero' delle eccezioni che generano spesso i
maggiori errori.
Attenti
comunque a non dimenticarsi il ; dato che e'
questa la prima causa di errori nella compilazione.
Dopo il ; e' possibile inserire un commento a piacere,
anzi e' quasi sempre auspicabile che tale commento esista a futura memoria di quanto pensato.
Se analizziamo
il nostro programma vediamo che questa prima funzione consta
essenzialmente di istruzioni di attribuzione che consentono la
programmazione dei registri di porta e direzione del PIC in modo da adattarli
all'hardware del nostro PICcolino.
Non entrero'
qui in dettagli sulle porte e la loro programmazione ampiamente
trattati in altre sezioni del nostro sito ....
evidenzio solo che e' necessario programmare a 0 il bit RBPU di INTCON2
ovvero
INTCON2bits.RBPU = 0;
per inserire le resistenze attive di pull-up sugli
ingressi della porta B
|