Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Indice generale
Il PIC 16F84
o Introduzione
o Caratteristiche
o Piedinatura
o Il piedino #MCLR
o Oscillatore esterno
XT
RC
LP e HS
Memoria RAM/FLASH/EEPROM
I registri SFR
I registri GPR
Il program counter
o La EEPROM
o STATUS
o OPTION_REG
o PCL
o PCLATH
o INTCON
o Introduzione
o Concetti generali
o Operazioni di base
No operation (NOP)
Salto
(GOTO)
Cicli di delay
incondizionato
o Le porte di I/O
o Caratteristiche elettriche
Linee porta A
Linee porta B
o Lettura e scrittura
o Esempi software
o Esempi di collegamento
Utilizzare
ouput
i piedini come
Utilizzare
input
i piedini come
o Operazioni logiche
AND logico
ANDLW)
(ANDWF
OR
logico
IORLW)
(IORWF
XOR logico
XORLW)
(XORWF
o Operazioni aritmetiche
Addizione
ADDLW)
(ADDWF
Sottrazione
SUBLW)
Decremento (DECF)
Incremento (INCF)
(SUBWF
Nibble-swap (SWAPF)
o Chiamata a funzione
Chiamata
(CALL)
funzione
Ritorno
con
(RETLW)
parametro
Programmare il PIC
o Fasi di sviluppo
o Costruzione del programmatore
Funzionamento e schema
elettrico
Configurazione di ICPROG
o L'ambiente MPLAB
Compilazione
o Il programma
o Circuito di prova
Il timer interno
Sistema di interrupt
La memoria EEPROM
o Lettura
o Scrittura
Modalita' sleep
Indirizzamento indiretto
Il Watch-Dog
Il PIC 16F84
Introduzione
Caratteristiche
memorie
Watch-dog interno
Piedinatura
RB0, RB1, RB2, RB3, RB4, RB5, RB6, RB7 - Sono gli
8 piedini della porta B. Valgono le considerazioni viste
per quelli della porta A.
Deve
essere
Il piedino #MCLR
Oscillatore esterno
XT
RC
LP e HS
Struttura interna
Torna all'indice
Memoria RAM/FLASH/EEPROM
La memoria dati (memoria RAM)
La memoria RAM del PIC 16F84 ha una dimensione di 90 byte, 22 byte per i
SFR (Special Function Register) e i restanti 68 byte per i 68 GPR (General
Purpose Register). Ogni registro occupa sempre ed esattamente un byte.
Gli SFR sono registri che controllano il funzionamento e le periferiche del
microcontrollore (ad esempio, e' qui che sono mappate le porte A e B): tali
registri non possono quindi essere utilizzati come memoria RAM per i
programmi utente ma semplicemente fungono da pannello di controllo per
l'intero
microcontrollore.
I GPR sono invece 68 registri liberi a disposizione dell'utente.
Le aree di memoria colorate in azzurro non sono implementate; qualsiasi
lettura in queste locazioni ritorna sempre con valore zero, mentre le
scritture non hanno effetto.
La memoria RAM e' suddivisa in due banchi distinti (banco 0 e banco 1). Per
poter accedere ad un registro e' quindi necessario specificare sia l'indirizzo
di memoria che il banco. Ad esempio, all'indirizzo 01h e banco 0 abbiamo
TMR0, mentre all'indirizzo 06h e banco 1 abbiamo TRIS B.
Alcuni registri sono "copiati" in entrambi i banchi; cio' significa che per
accede a quel registro e' sufficiente specificarne l'indirizzo di memoria, non
importa quale banco sia abilitato in quel momento. Ad esempio, per
accedere al registro PCL possiamo portarci all'indirizzo 02h e banco 0, ma
anche all'indirizzo 02h e banco 1. I registri di questo tipo sono: Indirect
addr., PCL, STATUS, FSR, PCLATH, INTCON e tutti e 68 i registri GPR.
I registri SFR
Come appare poco evidente dalla composizione della memoria RAM, i
registri SFR sono solo 16 (sembrerebbero 22 scartando le 2 sole aree in
azzurro, ma ovviamente quelli mappati in ambedue i banchi contano
sempre per uno solo, quindi sono effettivamente 16!). Eccoli elencati e
suddivisi
in
gruppi:
Registri SFR di controllo del PIC
INDF
TMR0
OPTION_REG
PCL
STATUS
FSR
PCLATH
INTCON
PORT_A
TRIS_A
PORT_B
TRIS_B
EEDATA
EECON1
EEADR
EECON2
Tutti i registri verranno analizzati nel corso del tutorial e nelle rispettive
sezioni. Ad esempio, i registri per l'utilizzo delle memoria EEPROM sono
approfonditi nella sezione "Utilizzo della memoria EEPROM". I registri piu'
trasversali, cioe' che riguardano e toccano piu' argomenti diversi, vengono
approfonditi all'occorrenza.
I registri GPR
I registri GPR, come detto in precedenza, sono tutti quelli che vanno
dall'indirizzo di memoria 0Ch a 4Fh inclusi. Sono 68 ed ognuno di essi e'
mappato in entrambi i banchi RAM.
scrittura dal registro PCL, quindi da tale registro e' possibile sia modificare
gli 8 bit meno significativi del program counter che leggerne lo stato. Il
registro PCL viene costantemente aggiornato e rispecchia sempre lo stato
dei 8 bit meno significativi del program counter. Per i restanti 2 bit del
program counter il discorso e' differente: tali bit sono nascosti e non sono
visibili all'utente, ma possono essere modificati andando a cambiare i due
bit meno significativi del registro PCLATH. PCLATH non viene mai aggiornato
e quindi il suo stato non corrisponde a quello dei 2 bit piu' significativi del
program
counter.
La figura mostra come sono relazionati i registri PCL e PCLATH con il
program
counter:
La EEPROM
Torna all'indice
STATUS
OPTION_REG
PCL
PCLATH
INTCON
Registro STATUS
Locazione
di
Banco RAM: mappato in entrambi
memoria:
0x03
bit C
bit DC
bit Z
bit #PD
bit #TO
bit RP0
bit RP1
Non implementato
bit IRP
Non implementato
Registro OPTION_REG
Locazione
Banco RAM: banco 1
di
memoria:
0x01
prescaler
bit PS1
bit PS2
bit PSA
Bit
di
assegnazione
1
al
0 - al TIMER0
del
prescaler
Watch-Dog
bit T0SE
bit T0CS
Registro PCL
Locazione
di
Banco RAM: mappato in entrambi
memoria:
0x02
Registro PCLATH
Locazione
di
Banco RAM: mappato in entrambi
memoria:
0x0a
Descrizione
dei
bit:
I due bit meno significativi sono messi in corrispondenza dei due bit piu'
significativi del program counter. Gli altri bit di PCLATH non sono
implementati. E' possibile sia leggere che scrivere. I due bit meno
significativi di PCLATH vengono scritti nei due piu' significativi del program
counter solo quando una qualche istruzione modifica il registro PCL.
Valore
di
default al
power-on-reset:
---00000
Valore di default per gli altri reset (#MCLR e Watch dog timer reset):
---00000
Legenda:
x
=
q
=
dipendente
u
=
rimane
- = non implementato
da
come
altri
era
aleatorio
fattori
prima
Registro INTCON
Locazione
di
Banco RAM: mappato in entrambi
memoria:
0x0B
bit RBIF
bit INTF
bit T0IF
bit RBIE
bit INTE
bit T0IE
bit EEIE
bit GIE
Torna all'indice
Introduzione
Il PIC 16F84 ha un set di appena 35 istruzioni. Ogni istruzione e' una parola
a 14 bit ed e' composta da un opcode che specifica l'istruzione stessa e da
uno o due operandi (per alcune questi sono facoltativi o del tutto assenti)
che
specificano
ulteriormente
l'operazione
da
eseguire.
Ogni istruzione viene eseguita in un ciclo macchina (4 colpi di clock) eccetto
per le istruzioni di salto (ma solo quando il salto e' effettuato) e per le
istruzioni che modificano il program counter; in questi due casi l'istruzione
richiede
2
cicli
macchina
(8
colpi
di
clock).
Le istruzioni sono variegate, ma possono essere raggruppate in tre
categorie principali: le istruzioni di salto (condizionato o non), quelle
aritmetiche/logiche e di movimentazione dei dati.
Concetti generali
Molte istruzioni sono composte dallo mnemonico (il nome dell'istruzione
stessa) e da uno o due parametri (a volte nessuno). I parametri possono
essere di quattro tipi: parametro F, parametro D, B e K.
e' possibile definire delle etichette da associare alle locazioni RAM del PIC.
In questo modo ci si puo' riferire piu' facilmente a tali locazioni
specificandone il nome scelto anziche' l'indirizzo in esadecimale. Per ora e'
sufficiente sapere che scrivendo la seguente riga in cima al listato
ILMIOREGISTRO
EQU
0x25
Operazioni di base
Set e clear dei bit (BSF e BCF)
Sono
le
due
istruzioni
BSF
e
BCF.
Vengono utilizzate per impostare a 0 o 1 i singoli bit dei registri.
BSF setta a uno il bit in posizione B del registro F, mentre BCF setta a zero il
bit
in
posizione
B
del
registro
F.
Sintassi
BSF
BCF
delle
F
F
istruzioni:
B
B
Esempio:
Settare ad uno il sesto bit meno significativo del registro alla locazione 0x13
BSF 0x13,5
NOTA: Il sesto bit e' il numero cinque, perche' il primo bit e' il numero zero!
Esempio:
Portare a zero il primo e l'ultimo bit del registro FSR
BCF 0x04,0
BCF 0x04,7
oppure, utilizzando le etichette:
FSR EQU 0x04
BCF FSR,0
BCF FSR,7
Esempio:
0x19,0
0x19,1
0x19,2
0x19,3
0x19,4
0x19,5
0x19,6
0x19,7
Sono le tre istruzioni MOVLW, MOVF e MOVWF. Grazie a queste tre istruzioni
e' possibile copiare un byte da un registro ram (GPR o SFR) al registro W e
viceversa, oppure caricare W con un valore letterale compreso tra 0 e 255.
MOVLW si usa tutte le volte in cui occorre inizializzare il registro W con un
dato
valore.
Sintassi
delle
istruzioni:
MOVLW
MOVWF
MOVF
F,D
BSF 0x03,5
MOVF 0x05,0
NOTA: In questo caso e' necessario prima specificare il banco RAM per
accedere a TRIS_A
Esempio:
Copiare il contenuto del registro OPTION_REG in PORT_A
BSF 0x03,5
MOVF 0x01,0
BCF 0x03,5
MOVWF 0x05
Vengono
utilizzate
per
azzerare
Sintassi
delle
CLRF
contenuti
dei
registri.
istruzioni:
CLRW
Azzera il contentuo del registro di lavoro W. Viene automaticamente settata
a
1
la
ZERO_FLAG
del
registro
di
stato.
Esempio:
Azzerare il contenuto di PORT_A
CLRF 0x05
Esempio:
Azzerare il contenuto di TRIS_B
BSF 0x03,5
CLRF 0x05
Esempio:
Azzerare il contenuto del registro W
CLRW
No operation (NOP)
della
istruzione:
NOP
Esempio:
Effettuare un ritardo di 3us supponendo un oscillatore da 8MHz.
NOP
NOP
NOP
NOP
NOP
NOP
NOTA: Con un oscillatore da 8MHz ogni istruzione viene eseguta in 0,5us.
Quindi per un ritardo di 3us occorrono 6 NOP.
della
istruzione:
GOTO
addr
:loop
;label di nome "loop"
MOVLW 0x30
;caricamento di W con il valore 0x30
GOTO loop
;salto alla istruzione dopo "loop"
Esempio:
Saltare tre istruzioni
BSF 0x03,5
MOVF 0x01,0
GOTO salto
BCF 0x03,5
CLRW
MOVLW 0x10
:salto
BCF 0x03,5
MOVWF 0x05
;salto
BTFSC
delle
istruzioni:
F,B
Se il B-esimo bit del registro F e' settato a uno (condizione FALSA) viene
eseguita l'istruzione immediatamente successiva; se vale zero (condizione
VERA) l'istruzione immediatamente successiva viene saltata e si passa a
quella
dopo.
BTFSS
F,B
Se il B-esimo bit del registro F e' settato a zero (condizione FALSA) viene
eseguita l'istruzione immediatamente successiva; se vale uno (condizione
VERA) l'istruzione immediatamente successiva viene saltata e si passa a
quella dopo. Questa istruzione di salto e' simile alla precedente ma il
controllo
sul
bit
B-esimo
e'
invertito.
DECFSZ
F,D
INCFSZ
F,D
Esempio:
Scrivere nel registro 0x30 tutti i valori in successione da 0 a 255. Infine
azzerare W.
MOVLW 0x00
MOVWF 0x2F
:loop
MOVLW 0x2F,0
MOVWF 0x30
INCFSZ 0x2F,1
GOTO loop
CLRW
Cicli di delay
Abbiamo gia' visto come effettuare un ritardo tramite l'uso ripetuto
dell'istruzione NOP. La tecnica non permette di generare grandi ritardi
perche' occorrebbe inserire un gran numero di NOP in sequenza, occupando
tutta
la
memoria
di
programma.
Conviene invece scrivere un ciclo che itera per un determinato numero di
volte, decrementando un registro GPR adibito a contatore; l'istruzione di
decremento e' incorporata in quella di salto, quindi il sistema e'
estremamente semplice da implementare. Piu' difficile e' stabilire il valore
iniziale del contatore per ottere uno specifico tempo di ritardo: occorre
infatti calcolare accuratamente tutte le durate di esecuzione delle istruzioni.
Un tipico ciclo di delay e' quello riportato qui sotto:
Ciclo di delay:
Considerando un oscillatore a 4MHz si crea un ritardo di 500us (mezzo
millisecondo)
COUNT EQU 0x30
:delay
MOVLW 0xA7
MOVWF COUNT
:loop
DECFSZ COUNT,1
goto loop
(N-1)+2
us
(N-1) volte richiede 1us (quando non salta) e all'ultimo giro richiede 2us
(salta).
L'istruzione GOTO viene eseguita N-1 volte e quindi richiede 2(N-1) us.
In
definitiva
si
ha:
tempo_tot
(N-1)+2+2(N-1)
us
semplificando:
tempo_tot
3(N-1)+2
us
semplificando
ancora:
tempo_tot
risolvendo
N
=
rispetto
3N-1
a
us
si
ottiene:
(tempo_tot+1)/3
Torna all'indice
Caratteristiche elettriche
Linee porta A
Le linee della porta A come detto prima sono 5, associate ai registri PORT_A
e TRIS_A. I pin RA0,RA1,RA2 e RA3, quando configurati come output, sono
di tipo push-pull, ovverosia possono essere utilizzati sia come "sorgenti" di
corrente (drain mode) che come "pozzi" (sink mode), in altre parole sono in
grado sia di assorbire corrente dal positivo dell'alimentazione (25mA max),
sia
di
fornirla
verso
massa
(20mA
max).
In figura si mostrano i collegamenti interni per i pin RA0,RA1,RA2 e RA3:
Il pin RA4 e' un caso a parte perche' e' di tipo a collettore aperto (open
drain); cio significa che e' possibile utilizzarlo esclusivamente come pozzo di
corrente: il suo comportamento equivalente e' come quello di un
interruttore che si chiude verso massa. La figura mostra i collegamenti
interni relativi alla linea RA4:
Lettura e scrittura
La lettura e scrittura delle porte di I/O e' estremamente semplice. Una volta
che si siano scelte le direzioni delle linee tramite l'imposizione dei bit dei
registri TRIS_A e TRIS_B sara' sufficiente settare opportunamente i bit dei
registri di porta (ad esempio con le istruzioni MOV,BCF,BSF etc..) per
ottenere le tensioni ai capi dei pin corrispondenti. Ovviamente ha senso
imporre lo stato dei bit solo per le linee dichiarate come output. Per
acquisire lo stato delle linee di input e' sufficiente andare a leggere lo stato
dei relativi bit di porta, con le normali tecniche di lettura dei registri messe
a
disposizione (istruzioni
della
famiglia
MOV).
Una linea di I/O impostata come output presentera' all'esterno (cioe' sul
relativo pin) una tensione di +5volt se il bit corrispondente nel registro di
porta (PORT_A o PORT_B) e' settato ad 1; 0volt nel caso sia settato a 0.
Una linea di I/O impostata come input invece e' l'esatto contrario: se la
tensione ai capi del relativo pin e' di circa 5volt, allora il PIC imposta ad 1 il
bit corrispondente nel registro di porta. Se la tensione e' nulla, lo setta a 0.
Esempi software
Esempio:
Inizializzare la porta A in modo che RA0 e RA1 siano di output e RA2,RA3 e
RA4 di input.
STATUS EQU 0x03
PORT_A EQU 0x05
TRIS_A EQU 0x05
BCF STATUS,5
CLRF PORT_A
BSF STATUS,5
MOVLW 0x1C
MOVWF TRIS_A
Esempio:
Supponendo che tutte le linee della porta B siano gia' settate come output,
scrivere il contenuto del registro 0x20 su tale porta.
STATUS EQU 0x03
PORT_B EQU 0x06
BCF STATUS,5
MOVF 0x20,0
MOVWF PORT_B
Esempi di collegamento
Utilizzare i piedini come output
Ecco alcuni esempi di collegamenti al pin RB0 configurato come output.
In figura si riporta un collegamento di un led alla linea RB0 del
microcontrollore:
La resistenza da 330 ohm limita la corrente nel ramo a circa 15mA. Quando
sulla linea RB0 viene imposto un 1 il piedino si porta a VCC Volt ed inizia a
fluire una corrente VERSO massa e quindi il led si accende. Quando viene
imposto 0 il piedino si porta a massa e la corrente smette di fluire; il led si
spenge.
Il circuito appena descritto utilizza il piedino RB0 come sorgente (source) di
corrente.
Il prossimo schema mostra come utilizzare il piedono RB0 come pozzo
(sink) di corrente:
Schema per impostare lo stato della linea RB0 (resistenze interne di pullup attivate!)
Schema per impostare lo stato della linea RB0 (resistenze interne di pull-up
disattivate!)
Lo schema precedente e' obbligatorio per gli input delle linee A, per le quali
non sono previste resistenze di pull-up interne attivabili via software come
accade per le B.
Torna all'indice
ANDWF
ANDLW
delle
istruzioni:
F,D
K
delle
istruzioni:
IORWF
IORLW
F,D
K
delle
istruzioni:
XORWF
XORLW
F,D
K
di
NOT
si
Sintassi
effettua
con
l'istruzione
della
COMF
COMF
istruzione:
F,D
Operazioni aritmetiche
Addizione (ADDWF e ADDLW)
Per l'operazione di somma sono messe a disposizione le due istruzioni
ADDWF
e
ADDLW.
Sintassi
delle
istruzioni:
ADDWF
ADDLW
F,D
K
delle
istruzioni:
SUBWF
SUBLW
F,D
K
Decremento (DECF)
Operazione
Sintassi
DECF
di
decremento
dela
unitario.
istruzione:
F,D
Incremento (INCF)
Operazione
Sintassi
di
decremento.
dela
istruzione:
INCF
F,D
All'inizio tale bit potra' trovarsi in uno stato qualsiasi (dipendera' da quello
che e' successo prima nel programma, il suo stato non e' noto) quindi,
anziche' scrivere 0 oppure 1, scriveremo una 'x'.
C 76543210
x 00000001
Ora, effettuando in sequeza tante istruzioni RLF (Rotate Left) ecco come
cambia il contenuto del nostro registro e del bit C:
RLF
RLF
RLF
RLF
RLF
RLF
RLF
RLF
RLF
RLF
C 76543210
x 00000001
0 00000010
0 00000100
0 00001000
0 00010000
0 00100000
0 01000000
0 10000000
1 00000000
0 00000001
0 00000010
e cosi' via...
Analogamente, ecco cosa succede con RRF (Rotate Right) partendo sempre
dal medesimo contenuto di registro:
C 76543210
x 00000001
RRF 1 00000000
RRF 0 10000000
RRF 0 01000000
RRF 0 00100000
RRF 0 00010000
RRF 0 00001000
RRF 0 00000100
RRF 0 00000010
RRF 0 00000001
RRF 1 00000000
RRF 0 10000000
RRF 0 01000000
RRF 0 00100000
RRF 0 00010000
e cosi' via...
Ecco perche' abbiamo detto che la rotazione avviene "attraverso" il bit C.
Questo sistema permette la lettura in sequenza di tutti i bit di un dato
registro semplicemente effettuando le rotazioni e controllando lo stato del
bit C.
Sintassi
RRF
RLF
delle
istruzioni:
F,D
F,D
NOP
Nibble-swap (SWAPF)
Effettua uno scambio dei quattro bit piu' significativi con i quattro meno
significativi. In gergo il termine "nibble" significa "gruppo di quattro bit".
L'istruzione scambia tra loro il nibble alto ed il nibble basso di un dato
registro.
Sintassi
della
SWAPF
istruzione:
F,D
Effettua lo scambio delle due meta' del registro F. Se D=1 il risultato viene
posto in F, altrimenti viene posto in W senza toccare F.
Esempio:
Scambiare tra loro le due meta' del registro 0x32 e porre il risultato nel
registro 0x33 lasciando inalterato 0x32.
SWAPF 0x32,0
MOVWF 0x33
Chiamata a funzione
Il microcontrolle 16F84 mette a disposizione del programmatore anche
l'utilissimo sistema di chiamata a funzione, un classico per qualsiasi CPU. In
pratica tramite apposite istruzioni e' possibile richiamare una pezzo di
codice di programma; in questo senso il sistema e' simile ad un GOTO con
ritorno, cioe' si salta in un altro punto della memoria di programma, si
esegue un certo pezzo di codice e poi si ritorna all'istruzione
immediatamente successiva a quella dove abbiamo saltato. L'istruzione di
salto e' CALL, mentre l'istruzione di ritorno puo' essere o RETURN, oppure
RETLW. Il pezzo di codice eseguito e' detto "subroutine". In pratica, quando
si vuole richiamare una subroutine, e' sufficiente invocare la CALL
specificando l'indirizzo della prima istruzione di tale subroutine (o una label,
come visto per le istruzioni di salto): il codice viene quindi eseguito dal
punto specificato in poi sino a che non si giunge ad una istruzione di
RETURN o RETLW. Giunti a questo punto si ritorna ad eseguire il programma
dall'istruzione immediatamente successiva a CALL. Si capisce facilmente
quindi che l'ultima istruzione di una data subroutine deve essere o RETURN
o RETLW; ovviamente se tali istruzioni non sono presenti il ritorno non avra'
luogo. Inoltre, piu' CALL possono riferirsi ad una stessa subroutine,
esattamente come piu GOTO possono riferirsi ad uno stesso punto di codice.
La figura sottostante mostra il sistema di chiamata a funzione:
la
chiamata
Sintassi
funzione
(subroutine).
della
istruzione:
CALL
addr
indietro
verso
la
CALL
della
chiamante.
istruzione:
RETURN
L'istruzione non ha parametri. L'esecuzione comporta il recupero dell'ultimo
indirizzo di programma inserito nello stack ed il salto verso tale locazione.
L'istruzione prevede due cicli macchina per essere eseguita.
Esempio:
Chiamare una subroutine che azzera il contenuto del registro 0x30, poi
incrementare di una unita' tale registro.
CALL azzera
INCF 0x30
azzera:
CLRF 0x30
RETURN
della
RETLW
istruzione:
somma:
;label di inizio della subroutine "somma"
MOVF 0x20,0
;copia il contenuto di 0x20 in W
ADDWF 0x21,0
;effettua la somma
RETLW
;ritorna indietro al programma principale
Torna all'indice
Il programma
Una possibile soluzione per poter far lampeggiare un led e' quella ad
esempio di avere una linea di I/O che emette un segnale in cui si alternano
le tensioni di 0 e +5 volt. A tale linea collegheremo in serie il led ed una
resistenza limitatrice di corrente. Allo scopo puo' essere utilizzato il
programma precedente che alterna i valori 0 e 1 sul bit meno significativo
(il
primo
bit)
del
registro
PORTB.
Riportiamo il codice del programma:
;******************************************************
;
Programma di prova
;
Alterna 1 e 0 sul primo bit di PORTB ogni 100ms
;******************************************************
;direttive
PROCESSOR
RADIX
;definizioni
R1
R2
R3
PORTB
TRISB
TRISA
PORTA
PORTB
STATUS
FSR
INDF
16F84A
HEX
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
;inizio programma
ORG
0x0000
bsf
STATUS,5
0x20
0x21
0x22
0x06
0x06
0x05
0x05
0x06
0x03
0x04
0x00
movlw
movwf
bcf
loop:
bsf
call
bcf
call
goto
0x00
TRISB
STATUS,5
PORTB,0
wait
PORTB,0
wait
loop
Circuito di prova
Una volta compilato e programmato correttamente il PIC occorrera'
realizzare questo piccolo circuito:
Torna all'indice
Il timer interno
Il TIMER0 e' un dispositivo interno al
microcontrollore in grado di assolvere alla
duplice funzione di contatore e temporizzatore.
Le due modalita' sono mutualmente esclusive e
possono essere scelte via software. In ogni caso
il modulo e' ad 8 bit, cio' significa che e' solo in
grado di contare in step di 1 unita' e ripetere
ciclicamente i valori nell'intervallo da 0 a 255. Al
TIMER0 e' associato un prescaler in grado di
rallentare la velocita' di incremento dei valori in
8 possibili modalita' (1:2, 1:4, 1:8, 1:16, 1:32,
1:64, 1:128, 1:256). Inoltre, se si vuole, e'
possibile impostare il modulo in maniera tale da
produrre un interrupt ogni volta che si ha un
overflow del TIMER0, cioe' ogni volta che il
modulo passa dal valore 255 (0xFF) a 0 (0x00).
Al TIMER0 e' associato un registro, il TMR0
(mappato nel banco 0 alla locazione di memoria
0x01); in questo registro e' possibile leggere lo
stato attuale di avanzamento del contatore
oppure impostarne il valore.
Prescaler
Il prescaler e' un modulo per "rallentare" la
frequenza di aggiornamento del TIMER0 tramite
8 fattori di divisione prestabiliti. Il prescaler puo'
essere assegnato al TIMER0 oppure (in maniera
mutualmente esclusiva) al Watch-Dog interno (il
Watch-Dog e' un modulo aggiuntivo del
microcontrollore spiegato piu' avanti nella
guida). Il bit PSA del registro OPTION_REG
determina a chi associare il prescaler (al TIMER0
con PSA=0 oppure al Watch-Dog con PSA=1). I
tre bit PS0,PS1 e PS2 determinano una tra gli 8
possibili rapporti di divisione di frequenza
cioe' 1:2, 1:4, 1:8, 1:16, 1:32, 1:64, 1:128,
1:256. Ovviamente se il prescaler non viene
assegnato al TIMER0 (cioe' PSA=1) otteniamo
automaticamente un rapporto di divisione di
1:1.
Quando il prescaler e' associato al TIMER0, ogni
istruizione che vada a modificare il registro
TMR0 (ad esempio, CLRF 0x01, MOVWF 0x01,
BSF 0x01,3 etc...) comporta automaticamente il
reset a 0 dei tre bit PS0,PS1 e PS2.
Per finire, nella figura seguente sono mostrati i
collegamenti interni che collegano il prescaler al
TIMER0 e al Watch-Dog:
Torna all'indice
Sistema di interrupt
Il sistema di interrupt e' stato gia' introdotto a
grandi
linee
alla
sezione
"Memoria
RAM/FLASH/EEPROM". Grazie alla gestione degli
interrupt, il microcontrollore puo' essere istruito
in maniera tale da "porsi in ascolto" di eventi
esterni durante l'esecuzione normale del
programma; quando uno di questi eventi si
manifesta
il
program
counter
viene
temporaneamente salvato nello stack e si salta
alla locazione di memoria 0x0004 (vettore di
interrupt). Compito del programmatore e' quello
di inserire, a partire da questa locazione, una
subroutine in grado di gestire l'attuale istanza di
interruzione. La subroutine di gestione delle
interruzioni dovra' terminare con l'istruzione
RETFIE:
questa
istruzione
ricarica
automaticamente l'ultimo program counter
salvato nello stack e cosi' permette la normale
Rising edge
Falling edge
Torna all'indice
La memoria
EEPROM
La memoria EEPROM e' un modulo di memoria
all'interno del microcontrollore in grado di
mantenere le informazioni anche a sistema
spento. La memoria e' costituita da 64 byte in
tutto, accessibili sia in lettura che in
scrittura tramite quattro appositi registri, cioe':
Il
EECON1
EECON2
EEDATA
EEADR
registro
EEDATA,
mappato
in
RAM
alla
Registro EECON1
Lettura
Scrittura
Esempio:
Scrive nella EEPROM il valore 0x02 alla locazione
0x10
BCF
0x03,5
MOVLW
MOVWF 0x08
MOVLW
MOVWF 0x09
BSF
0x03,5
BCF
0x0B,7
;inizio
sequenza
BSF
0x08,2
MOVLW
MOVWF 0x09
MOVLW
MOVWF 0x09
BSF 0x08,1
;bit WR ad 1 -> inizio scrittura
BSF
0x0B,7
;riabilita gli interrupt
;fine della sequenza
Torna all'indice
Modalit sleep
Lo sleep e' una particolare modalita' nella quale il microcontrollore
cessa momentaneamente di eseguire istruzioni e si porta in uno stato
di stand-by durante il quale i consumi di energia sono ridotti al
minimo; e' possibile poi "risvegliare il PIC" in qualsiasi momento
successivo. Questa modalita' e' utile nel caso in cui si voglia usare il
PIC in sistemi alimentati a batteria o comunque dove i consumi sono
un aspetto critico.
Watch-Dog time-out
Torna all'indice
Indirizzamento
indiretto
L'indirizzamento indiretto e' una delle
caratteristiche piu' interessanti del PIC
16F84. Grazie a questo sistema e' possibile
accedere sia in lettura che in scrittura ad un
dato registro GPR in modo indirietto,
ovverosia specificandone l'indirizzo sotto
forma di dato contenuto in un altro registro.
All'apparenza
il
meccanismo
potrebbe
apparire come una complicazione non
strettamente necessaria, in realta' e'
estremamente utile. Un esempio aiutera' a
capirne l'ambito di utilizzo: normalmente
per poter accedere in scrittura ad un dato
registro occorre specificarne l'indirizzo
direttamente
nell'istruzione.
Ad esempio, il codice seguente carica il
registo
0x0C
con
il
valore
0xA3:
MOVLW
MOVWF
0xA3
0x0C
0xA3
0x0C
0x0E
0x0F
0x4F
FSR
INDF
FSR
INDF
STATUS
EQU
EQU
EQU
0x04
0x00
0x03
:clearall
MOVLW 0x0C
;inizializzo il puntatore
al primo registro GPR
MOVWF FSR
;e lo scrivo nel registro
FSR
next:
CLRF INDF
;cancello il contenuto di
INDF
INCF FSR
;incremento di uno il
puntatore
MOVF FSR,0
SUBLW 0x50
BTFSS STATUS,2
;se FSR=0x50 vai a
RETURN, altrimenti vai a next
GOTO next
RETURN
Torna all'indice
Watch-Dog
Il Watch-Dog e' un oscillatore RC secondario
inserito all'interno del microcontrollore. Tale
oscillatore non richiede alcun componente
esterno per funzionare ed e' completamente
indipendente da quello che regola il
funzionamento del PIC: cio' significa che il
Watch-Dog continua a funzionare anche nel
caso in cui viene a mancare il segnale di
clock esterno. Il Watch-Dog ha associato un
tempo di default pari a 18 ms terminato il
quale effettua il reset del microcontrollore
(oppure, se in modo sleep, lo risveglia). Se
si desiderano tempi piu' lunghi e' possibile
associare il prescaler al Watch-Dog settando
a 0 il bit PSA del registro OPTION_REG e poi
impostare il rapporto di moltiplicazione
tramite i bit PS0,PS1 e PS2 (il prescaler,
quando viene associato al Watch-Dog,
funziona da moltiplicatore anziche' da
divisore come invece accadeva quando
associato al TIMER0). In sostanza lo scopo
del Watch-Dog e' quello di attendere il
periodo di tempo selezionato (di default 18
ms) e poi scatenare automaticamente il
reset del microcontrollore (nel caso il PIC sia
in modalita' sleep viene semplicemente
risvegliato continuando l'esecuzione del
programma). L'unico modo per prevenire il
reset del PIC e' quello di resettare il WatchDog, cioe' quello di riazzerare il suo conto
alla
rovescia
tramite
l'esecuzione
dell'istruzione
CLRWDT.
Il Watch-Dog e' utile in tutti quei casi in cui
non si vuole che, per qualche errore di
programmazione, il microcontrollore si
blocchi in un loop infinito in qualche parte
del programma. Si predispongono le
istruzioni di CLRWDT lungo tutto il codice del
programma in maniera tale da riazzerare
Torna all'indice