ESERCITAZIONE # 6
Modifica sull' Esercitazione 5 e
programmazione del firmware
In questa esercitazione effettuiamo qualche modifica al sorgente dell'
Esercitazione precedente:
- Innanzitutto, utilizziamo un numero maggiore di LED, per avere un effetto
ottico migliore.
- Poi, inseriamo una breve pausa tra ogni ciclo di lampeggio, per
evidenziare maggiormente il cambio del clock
Utilizziamo 4 LED collegati ai primi 4 pin di PORTC e li facciamo accendere
alternativamente, a coppie.
E modifichiamo il flow chart del ciclo principale per l' aggiunta della
pausa.
|
Sostanzialmente, si tratta di aggiungere semplicemente
delle routine di attesa dopo ogni cambio di clock.
Le routine saranno sempre realizzate come per
gli altri esempi, onde evitare per ora calcoli sui tempi di ciclo delle
istruzioni, utilizziando il calcolatore disponibile in rete per la creazione di
ritardi di tempo, il noto Delay
Generator di Nicolai Golovchenko.
Nel sorgente il tempo di pausa è di 1 secondo, ma
potrà essere variato a piacere modificando le impostazioni della
routine di attesa. |
Il nostro esercizio prevede di collegare LED ai bit 3:0 di PORTC
, che saranno accesi a coppie.
La gestione relativa è, anche qui, realizzata con macro per semplificare il
sorgente.
Per l' esecuzione pratica si dovranno semplicemente collegare i pin PC0:3 ai
LED della UniBoard (o del proprio hardware).
Il Pickit è inserito direttamente nella spina ICSP/ICD e permette un debug passo passo delle
istruzioni.
Per chi non avesse chiare le connessioni, qui trova di seguito una pagina dedicata.
L' esercizio richiede le seguenti risorse:
- MPLAB IDE installato
- Pickit3 (o Pickit2)
- 28-40pin UniBoard con PIC18F2321
0 4321 (o 2221 o 4221 o altro hardware similare)
- quattro cavetti jumper da 14-15 cm
Il listato sorgente è una estensione di quello già visto negli altri
esercizi e che fa da base per tutti i seguenti, aggiungendo gli elementi
necessari al nuovo lavoro.
Vediamo solamente le differenze da quello dell' esercizio 5.
Viene introdotta una selezione per la compilazione in ambiente debug o in
release.
Una condizione if/else/endif consente di escludere
dalla compilazione uno o l' altro blocco di elementi.
- Se la variabile DebugOn è uguale a 1, viene compilato il set di CONFIG
per il debug.
- Se DebugOn è uguale a 0, viene compilato il set per la release.
Lo scambio tra le due condizioni si ottiene semplicemente commentando
(aggiungendo ; a inizio riga) o de commentando (togliendo il ; iniziale) le
linee voluta.
Questa tecnica consente di avere un solo listato per ottenere sia l' oggetto per
il debug sia quello per la release finale.
;---------------------------------------------------------------------
; Condizione di compilazione
; Selezionare la modalità richiesta
DebugOn equ
1 ; condizioni di
debug
;DebugOn equ 0 ; condizioni di release
;---------------------------------------------------------------------
; Condizioni comuni
; Single-Supply ICSP disabled
CONFIG LVP = OFF
; Uso dell' oscillatore interno, port su RA7 e FOSC/4 su RA6
CONFIG OSC = INTIO1
; Funzione del pin MCLR abilitata
CONFIG MCLRE = ON
; WDT disabilitato
CONFIG WDT = OFF
; Brown-out in hardware only
CONFIG BOR = ON
; Condizione di debug
#if DebugOn == 1
; Background debugger enabled su RB6 e RB7 per il debug con il
; Pickit o altro, attraverso ICSP/ICD
CONFIG DEBUG = ON
; PWRT disabled per il debug
CONFIG PWRT = OFF
; Soglia BOR 4.2V
CONFIG BORV = 1
#else
; Condizioni di release
; debug disabilitato
CONFIG DEBUG = OFF
; BORV a 2.7V per alimentazione a batteria
CONFIG BORV = 2
; Power On Timer abilitato
CONFIG PWRT = ON
#endif |
Così come è scritta, quest' area equivale dunque a:
;---------------------------------------------------------------------
; Condizione di compilazione
; Selezionare la modalità richiesta
DebugOn equ
1 ; condizioni di
debug
;DebugOn equ 0 ; condizioni di release
;---------------------------------------------------------------------
; Condizioni comuni
; Single-Supply ICSP disabled
CONFIG LVP = OFF
; Uso dell' oscillatore interno, port su RA7 e FOSC/4 su RA6
CONFIG OSC = INTIO1
; Funzione del pin MCLR abilitata
CONFIG MCLRE = ON
; WDT disabilitato
CONFIG WDT = OFF
; Brown-out in hardware only
CONFIG BOR = ON
; Condizione di debug
; Background debugger enabled su RB6 e RB7 per il debug con il
; Pickit o altro, attraverso ICSP/ICD
CONFIG DEBUG = ON
; PWRT disabled per il debug
CONFIG PWRT = OFF
; Soglia BOR 4.2V
CONFIG BORV = 1
|
Nel caso in cui si selezionasse l' altra possibilità, sarebbe equivalente ad
avere scritto:.
;---------------------------------------------------------------------
; Condizione di compilazione
; Selezionare la modalità richiesta
;DebugOn
equ 1
; condizioni di debug
DebugOn equ
0 ; condizioni di release
;---------------------------------------------------------------------
; Condizioni comuni
; Single-Supply ICSP disabled
CONFIG LVP = OFF
; Uso dell' oscillatore interno, port su RA7 e FOSC/4 su RA6
CONFIG OSC = INTIO1
; Funzione del pin MCLR abilitata
CONFIG MCLRE = ON
; WDT disabilitato
CONFIG WDT = OFF
; Brown-out in hardware only
CONFIG BOR = ON
; Condizioni di release
; debug disabilitato
CONFIG DEBUG = OFF
; BORV a 2.7V per alimentazione a batteria
CONFIG BORV = 2
; Power On Timer abilitato
CONFIG PWRT = ON
|
Nell' area degli Equates inseriamo alcune definizioni che ci serviranno
durante il programma e possiamo anche creare due macro per il comando dei LED, con la finalità di
rendere più leggibile il listato.
;----------------------------------------------------------------------
; Equates
;
; Numero lampeggi a 1 MHz
nlamp equ .5
;----------------------------------------------------------------------
; Macros
;
; Gestione on-off dei LED collegati a PC0 e PC2 contemporaneamente
Led1On
MACRO
bsf
LATC,0
bsf
LATC,2
ENDM
Led1Off
MACRO
bcf
LATC,0
bcf
LATC,2
ENDM
; Gestione on-off dei LED collegati a PC1 e PC3 contemporaneamente
Led2On
MACRO
bsf
LATC,1
bsf
LATC,3
ENDM
Led2Off
MACRO
bcf
LATC,1
bcf
LATC,3
ENDM
; spegne tutti i lED
azzerando i bit 3:0 di PORTC
LedOff MACRO
movlw
b'11110000'
andwf LATC,f
ENDM
|
Per quanto riguarda il "programma" vero e proprio, si tratta solo dell' aggiunta
della chiamata alla pausa intermedia.
Va considerato che le routines di tempo usate si basano sul clock per il calcolo
della loro durata; nell' eserciz è utilizzata una pausa di 0.5 secondi con un
clock di 1MHz.
Però, durante il funzionamento, è proprio il clock a cambiare: per avere una
durata costante della pausa anche la sua lunghezza deve variare di conseguenza.
Per semplicità viene usato lo stesso meccanismo impiegato per i cicli di lampeggio,
ovvero si ripete un numero di volte crescente una stessa temporizzazione per
avere uguale durata con il variare del clock.
Infatti, se la temporizzazione vale 1/2 secondo a 1MHz, occorrerà ripeterla due
volte con un clock di 2 MHz per avere sempre 1/2 secondo. Così sarà necessario
ripeterla 4 volte a 4 MHZ e 8 volte a 8 MHz.
Va notato che se la pausa base, calcolata a 1MHz, è perfettamente
precisa (in funzione della precisione dell' oscillatore, ovviamente), il
ripeterla n volte porta ad una lieve imprecisione dovuta all' aggiunta
delle istruzioni di ripetizione, la cui durata andrebbe calcolata per
ottenere un tempo esatto.
Però si tratta di pochi micro secondi, che in questa applicazione sono
del tutto trascurabili. Quindi non viene effettuata alcuna correzione. |
Il numero dei lampeggi per ciclo è fissato in fase di compilazione dalla
variabile
nlamp.
Il numero delle ripetizioni è fissato a seguito di ogni cambio del clock
caricando in WREG un numero proprozionale al clock.
; Ciclo primario
mainloop
movlw
nlamp ;
numero lampeggi
call
ciclo ;
lampeggio
m18SetIntClock 2
; clock 2 MHz
m18IntOscStable
; attendi stabilizzazione oscillatore
movlw
nlamp ; numero lampeggi
call
ciclo ;
lampeggio
movlw
.2
; numero ripetizioni cicli pausa
call
Pausa
; pausa 1 s
; ecc..
|
Si potrebbe anche accorpare la pausa nella routine di ciclo lampeggio, ma si
è preferito averla come elemento separato che può essere modificato a piacere.
La prima istruzione della routine recupera da WREG il valore da applicare
alle ripetizoni, che viene salvato nella locazione di RAM counter
. Sarà questo counter ad essere decrementato per calcolare il numero delle
ripetizoni.
; Pausa
; La routine si basa sulla ripetizione di un
ciclo base di
; 1 s a 1MHz di clock
; per cui con clock a 2 MHz il ciclo sarà ripetuto due volte,
; 4 volte con 4 MHz e 8 volte con 8 MHz
; in modo da mantenere sempre una pausa di circa 1 secondo
Pausa
movf counter
; numero cicli pausa da eseguire
pas1 call Attesa
; da 1 s @ 1 MHz
decfsz
counter ;
fine cicli pausa ?
bra
pas1 ; no
- altro ciclo
return
; si - fine pausa e ritorno
|
Per semplicità, anche la Pausa si bassa sulla routine Attesa (1/2 s a 1 MHz).
Nulla vieta di utilizzare il calcolatore di Golovchenko per determinare altri
tempi e inserirli nel programma.
Se si incontrano errori nella compilazione è opportuno verificarli con la
lista di descrizione degli errori e correggere dove si è sbagliato.
Il file compresso di questa esercitazione è scaricabile dall'
area di download.
|