[Precedente] [Indice principale] [Seguente]
[Piedinatura e aree di memoria] [Istruzioni] [Note per la programmazione]
Picture by Sergio Tanzilli |
Il PIC 16F84 e' un microcontroller e puo' essere pensato come un piccolissimo computer completo realizzato in un unico integrato a 18 pin. E' dotato infatti di memoria programma, ram utente, periferiche interne e porte di ingresso/uscita per ricevere e trasmettere segnali da e verso l'esterno. Puo' essere alimentato da 3 a 5,5V e assorbe poco piu' di 2 mA. Vss e' la massa (chiamata anche GND), Vdd e' il positivo di alimentazione (chiamato anche Vcc). OSC1 e OSC2 sono i pin a cui va collegato il quarzo per il clock, a questi vanno anche collegati due condensatori da 22pF verso massa come indicato nella figura di sotto. Il quarzo puo' arrivare fino a 20Mhz a seconda del tipo di PIC. Collegando a massa il pin MCLR si ottiene il reset del micro, normalmente questo pin va tenuto a 1 con una resistenza da qualche K collegata a Vdd. Gli altri 13 pin sono ingressi/uscite singolarmente programmabili e ciascuno puo' pilotare almeno 20mA. Il pin RB0 puo' essere programmato come ingresso di interrupt. I pin da RB4 a RB7 possono generare un interrupt di gruppo. Tutti i pin della porta B (RB0..RB7) se configurati come ingressi possono disporre di una resistenza di pull-up interna. Il pin RA4 in uscita e' un open collector, e in ingresso puo' essere usato come clock di conteggio per il timer interno. Lo schema seguente mostra il collegamento base del 16f84. Anche se nello schema non e' indicato, e' sempre consigliabile collegare un condensatore da 100nF tra i pin Vdd e Vss per filtrare i possibili disturbi sull'alimentazione.
Il PIC 16F84 dispone di una memoria programma separata dalla memoria dati. La memoria programma e' lunga 1024 locazioni (1kwords) con indirizzi da 0 a 1023. Il PIC all'accensione (o dopo un reset) inizia a leggere il programma dall'indirizzo 0. L'indirizzo 4 e' il punto di partenza dell' interrupt handler, la discriminazione della sorgente dell'interrupt va effettuata via software.
La memoria dati e' lunga 80 locazioni
(indirizzi
da 0 a 79) e prende il nome di register file in quanto ogni locazione
puo'
essere considerata come un registro a 8 bit. I primi 12 indirizzi
(0..11)
servono per il controllo dell'hardware del PIC, i seguenti 68 indirizzi
(12..79) sono usabili dall'utente per memorizzare i propri dati di
lavoro.
Inoltre i primi 12 indirizzi dispongono di due banchi di registri,
alcuni
dei quali sono visibili in entrambi i banchi, mentre altri sono
presenti
solo in un banco. Il registro STATUS per esempio e' visibile in
entrambi
i banchi, puo' cioe' essere letto o scritto sia se il banco attivo e'
lo
0, sia se e' l' 1. La commutazione da un banco all'altro avviene
settando
il bit 5 di STATUS (bit RP0), se vale 0 e' attivo il banco 0, se vale 1
e' attivo il banco 1. I 68 registri utente dall'indirizzo 12 (0CH) in
poi
sono invece sempre visibili e non sono influenzati dal banco attivo. Il
registro STATUS contiene anche i flags, il bit 0 e' il flag C, il bit 2
e' il flag Z.
Picture
by Microchip
ISTRUZIONI
[Caricamento
dati] [Aritmetiche]
[Logiche] [Rotazioni
e set/reset]
[Salti
e subroutine] [Controllo sistema]
[Riepilogo]
Il PIC dispone di un set di 35 istruzioni elementari, e ogni istruzione occupa una sola locazione della memoria programma. Quasi tutte le istruzioni vengono eseguite in 4 cicli di clock, un PIC cloccato a 4Mhz e' percio' in grado di eseguire 1milione di istruzioni al secondo (1 mips) e ogni istruzione dura 1µS. Le istruzioni di branch (salto) possono richiedere 8 cicli di clock anziche' 4. Nella terminologia Microchip un gruppo di 4 cicli di clock e' detto "ciclo", per cui le istruzioni vengono eseguite in uno o due cicli.
Le aree di memoria su cui si puo' agire sono i registri della memoria dati e il registro accumulatore W (che non fa parte dell'area dati, ma e' un ulteriore registro hardware interno al PIC utilizzato nelle operazioni aritmetico logiche).
Nelle seguenti liste delle istruzioni
si
deve considerare n come un valore (literal) a 8 bit, addr
come un valore che indica una locazione di memoria (di programma o dati
a seconda dell'istruzione) e b come un valore compreso tra 0 e
7
che indica il bit all'interno di un byte. Inoltre sono riportati gli
effetti
sui flags, una X indica che il valore finale del flag dipende dal
risultato
dell'operazione. Molte istruzioni che operano su registri permettono di
trasferire il risultato dell'operazione o nel registro W o nel registro
stesso chiamato in causa dall'istruzione, queste due possibilita' si
specificano
scrivendo ,w o ,f alla fine dell'istruzione.
ISTRUZIONI DI CARICAMENTO DATI A 8 BIT
movlw n | n -> W | |
movwf addr | W -> (addr) | |
movf addr,w | Z=X | (addr) -> W |
movf addr,f | Z=X | (addr) -> (addr) |
swapf addr,w | swap(addr) -> W | |
swapf addr,f | swap(addr) -> (addr) | |
clrf addr | Z=1 | (addr) = 0 |
clrw | Z=1 | W = 0 |
Le istruzioni movlw e movwf non alterano i flags. L'istruzione movf invece modifica il flag Z, che risulta settato (s=set) se il valore caricato e' 0, e resettato (c=clear) se il valore caricato e' diverso da 0. Nell' ultima movf il valore viene trasferito nella stessa locazione da cui viene preso, il suo valore percio' non cambia, ma, visto che il flag Z viene modificato, e' un modo rapido per verificare se contiene zero.
L' istruzione swapf scambia i nibbles (i 4 bit superiori e i 4 bit inferiori) della locazione addr, e deposita il risultato nell'accumulatore o nella locazione stessa. In alcuni casi puo' essere vantaggioso usarla, oltre che per swappare i nibble, anche come spostamento perche' non altera i flags (per esempio e' usata per salvare il registro STATUS durante un interrupt).
Le istruzioni clrf e clrw sono un
caricamento
diretto del valore 0 in una locazione dati o nell'accumulatore.
Entrambe
impostano il flag Z a 1.
addlw n | C=X Z=X | W = W + n |
addwf addr,w | C=X Z=X | W = W + (addr) |
addwf addr,f | C=X Z=X | (addr) = W + (addr) |
sublw n | C=X Z=X | W = n - W |
subwf addr,w | C=X Z=X | W = (addr) - W |
subwf addr,f | C=X Z=X | (addr) = (addr) - W |
incf addr,w | Z=X | W = (addr) + 1 |
incf addr,f | Z=X | (addr) = (addr) + 1 |
decf addr,w | Z=X | W = (addr) - 1 |
decf addr,f | Z=X | (addr) = (addr) - 1 |
Le istruzioni di somma e sottrazione alterano entrambi i flags C e Z. Il flag Z e' sempre clear, viene settato solo quando il risultato dell'operazione e' 0, Durante una somma il flag C e' sempre resettato, viene settato solo se l'operazione causa un overflow. Durante una sottrazione il flag C e' sempre settato, viene resettato solo se l'operazione causa un prestito. Controllando lo stato di questi flags dopo una sottrazione e' possibile stabilire se un numero e' maggiore, minore o uguale a un'altro.
Le istruzioni di incremento decremento
settano il flag Z se il risultato dell'operazione e' 0.
andlw n | Z=X | W = W AND n |
andwf addr,w | Z=X | W = W AND (addr) |
andwf addr,f | Z=X | (addr) = W AND (addr) |
iorlw n | Z=X | W = W OR n |
iorwf addr,w | Z=X | W = W OR (addr) |
iorwf addr,f | Z=X | (addr) = W OR (addr) |
xorlw n | Z=X | W = W XOR n |
xorwf addr,w | Z=X | W = W XOR (addr) |
xorwf addr,f | Z=X | (addr) = W XOR (addr) |
comf addr,w | Z=X | W = NOT(addr) |
comf addr,f | Z=X | (addr) = NOT(addr) |
Tutte le istruzioni logiche settano il
flag Z nel caso che il risultato dell'operazione sia 0.
ROTAZIONI E SET/RESET DI SINGOLI BIT
rlf addr,w | C=X | W = rlf(addr) |
rlf addr,f | C=X | (addr) = rlf(addr) |
rrf addr,w | C=X | W = rrf(addr) |
rrf addr,f | C=X | (addr) = rrf(addr) |
bcf addr,b | Bit b di (addr) = 0 | |
bsf addr,b | Bit b di (addr) = 1 |
Le istruzioni rlf e rrf ruotano
rispettivamente
a sinistra o a destra il contenuto di un registro. Il
risultato
e' depositato nell'accumulatore o nella locazione di memoria stessa e
la
rotazione avviene sempre attraverso il flag C.
btfsc addr,b | Skip se bit b di (addr) = 0 | |
btfss addr,b | Skip se bit b di (addr) = 1 | |
incfsz addr,w | W = (addr)+1 Skip se W = 0 | |
incfsz addr,f | (addr) = (addr)+1 Skip se (addr) = 0 | |
decfsz addr,w | W = (addr)-1 Skip se W = 0 | |
decfsz addr,f | (addr) = (addr)-1 Skip se (addr) = 0 | |
goto addr | Salto a addr | |
call addr | Chiamata di subroutine | |
return | Ritorno da subroutine | |
retlw n | Ritorno da subr. con valore in W | |
retfie | Ritorno da interrupt |
Le istruzioni per il salto
incondizionato
(goto, call, return, retlw, retfie) richiedono sempre 2 cicli macchina,
mentre i salti condizionati (skip) ne richiedono 2 solo se la
condizione
e' verificata.
ISTRUZIONI DI CONTROLLO SISTEMA
nop | Nessuna operazione | |
clrwdt | Azzera watch dog timer | |
sleep | Standby mode |
RIEPILOGO
ISTRUZIONI
Il valore di d puo' valere 0 o
1 (o, rispettivamente, W o F), addr indica un registro
dati
oppure un indirizzo di programma nelle istruzioni goto e call, b
indica un bit all'interno di un byte, n e' un valore costante
(literal)
a 8 bit.
Mnemonic operands | Cyc. | Flag | Description |
Byte oriented file register operations |
|||
addwf addr,d | 1 | Z C | d = W + (addr) |
andwf addr,d | 1 | Z | d = W AND (addr) |
clrf addr | 1 | Z | (addr) = 0 |
clrw | 1 | Z | W = 0 |
comf addr,d | 1 | Z | d = NOT(addr) |
decf addr,d | 1 | Z | d = (addr) - 1 |
decfsz addr,d | 1(2) | d = (addr)-1 Skip se d = 0 | |
incf addr,d | 1 | Z | d = (addr) + 1 |
incfsz addr,d | 1(2) | d = (addr)+1 Skip se d = 0 | |
iorwf addr,d | 1 | Z | d = W OR (addr) |
movf addr,d | 1 | Z | (addr) -> d |
movwf addr | 1 | W -> (addr) | |
rlf addr,d | 1 | C | d = rlf(addr) |
rrf addr,d | 1 | C | d = rrf(addr) |
subwf addr,d | 1 | Z C | d = (addr) - W |
swapf addr,d | 1 | swap(addr) -> d | |
xorwf addr,d | 1 | Z | d = W XOR (addr) |
Bit oriented file register operations |
|||
bcf addr,b | 1 | Bit b di (addr) = 0 | |
bsf addr,b | 1 | Bit b di (addr) = 1 | |
btfsc addr,b | 1(2) | Skip se bit b di (addr) = 0 | |
btfss addr,b | 1(2) | Skip se bit b di (addr) = 1 | |
Literal and control operations |
|||
addlw n | 1 | Z C | W = W + n |
andlw n | 1 | Z | W = W AND n |
call addr | 2 | Chiamata di subroutine | |
clrwdt | 1 | Azzera watch dog timer | |
goto addr | 2 | Salto a addr | |
iorlw n | 1 | Z | W = W OR n |
movlw n | 1 | n -> W | |
nop | 1 | Nessuna operazione | |
retfie | 2 | Ritorno da interrupt | |
retlw n | 2 | Ritorno da subr. con valore in W | |
return | 2 | Ritorno da subroutine | |
sleep | 1 | Standby mode | |
sublw n | 1 | Z C | W = n - W |
xorlw n | 1 | Z | W = W XOR n |
NOTE
PER LA PROGRAMMAZIONE
[Generalità]
[Configurazione hardware] [Esempio
di programma] [Loop] [Tabelle
dati] [Ritardi software]
GENERALITA'
Le istruzioni dei PIC sono molto veloci
ma anche molto elementari. Questo significa che e' necessario un certo
studio e una certa quantita' di istruzioni anche per realizzare le piu'
semplici strutture software (come ad esempio i loop). Solo alcune
operazioni
alterano i flags, e i salti condizionati sono dei semplici skip
dell'istruzione
successiva. Questo obbliga a pensare alle condizioni in negativo, nel
senso
che invece del consueto "salta a se si verifica che" si deve
ragionare
come "skip se non si verifica che" seguito da un salto
incondizionato
(goto).
EQU
Le 68 locazioni della memoria dati utente,
e le 12 per il controllo hardware del PIC, possono essere indirizzate
scrivendo
direttamente il loro indirizzo nelle istruzioni (gli addr nella lista
istruzioni
precedente) o usando la direttiva EQU per specificarne un nome
simbolico.
Il registro di stato all'indirizzo 3 puo' essere infatti definito
con una EQU:
STATUS
EQU 3
E quindi ci si puo' riferire a lui
indifferentemente
come STATUS o come indirizzo 3:
btfss
STATUS,2 ;Skip se bit 2 di status = 1
btfss
3,2 ;Skip se bit 2 di
status
= 1
In realta' anche i flags possono essere
definiti con una EQU:
Z
EQU 2
...e quindi ci si puo' riferire al flag
Z nel seguente modo:
btfss
STATUS,Z ;Skip se il flag Z e' settato
Anche alle locazioni utente puo' essere
assegnato un nome, e quindi possono essere usate come se fossero 68
registri
ciascuno col suo nome:
var1
EQU 12
var2
EQU 13
contat
EQU 14
...
INCLUDE
Per ogni tipo di pic esiste un file gia'
pronto (fornito assieme all'assemblatore) che contiene tutte le
definizioni
standard. Per esempio in un programma scritto per il pic 16F84A andra'
incluso il file P16F84a.INC con la direttiva:
INCLUDE
"P16F84a.INC"
La direttiva INCLUDE puo' servire anche
per incorporare nel proprio programma degli altri pezzi di programma
scritti
in uno o piu' files esterni.
ORG
La direttiva di compilazione ORG (origine)
che serve per due scopi differenti, a seconda che si applichi al
programma
o all'area dati. Nel primo caso serve per indicare all'assemblatore
l'indirizzo
fisico dove dovranno essere caricate le istruzioni successive
(generalmente
un programma inizia sempre all' ORG 0). Nel secondo caso invece
permette
di definire l'indirizzo fisico di partenza di un'area dati, e di
definirne
poi l'occupazione tramite nomi simbolici e la direttiva RES (riserva).
Le nostre 3 variabili dell'esempio precedente potrebbero per esempio
essere
dichiarate con:
ORG 0CH
var1
RES 1
var2
RES 1
contat
RES 3
...
Queste righe indicano al compilatore di
riservare 1 byte all'indirizzo 12 (0CH) e chiamarlo var1, un altro byte
all'indirizzo 13 con il nome var2 ecc... Questo puo' essere comodo ad
esempio
per spostare un programma da un tipo di pic all'altro, in quanto basta
cambiare l'org dell'area dati senza dover riscrivere tutti gli
indirizzi
fisici associati a ciascun nome simbolico. Come si vede nell'esempio,
con
res si puo' riservare anche piu' di un byte, la variabile contat e' a
24
bit, e possiamo riferirci ai suoi tre byte come contat, contat+1 e
contat+2.
#DEFINE
Esiste poi la possibilita' di ridefinire
dei comandi comuni usati spesso assegnando loro un nome piu' comodo.
Per
esempio per impostare il banco attivo nella prima parte dell'area dati
(quella che controlla l'hardware) si deve settare o resettare il bit
RP0
del registro status:
bsf
STATUS,RP0 ;attiva banco 1
bcf
STATUS,RP0 ;attiva banco 0
Per evitare di scrivere ogni volta
queste
istruzioni le possiamo ridefinire con le parole Bank1 e Bank0:
#define
Bank0 bcf STATUS,RP0
#define
Bank1 bsf STATUS,RP0
A questo punto nel programma possiamo
semplicemente
scrivere Bank0 o Bank1
CONFIGURAZIONE
HARDWARE
I pic dispongono di un registro di
configurazione
hardware, che viene scritto una sola volta al momento della
programmazione,
e che stabilisce il funzionamento di alcuni circuiti interni, come il
watch
dog timer (wdt) e l'oscillatore di clock. Questa operazione e'
conosciuta
anche con il nome di "settaggio dei fuses". Nei micro dotati di memoria
flash non si parla naturalmente di fusibili e questi settaggi possono
essere
cambiati semplicemente riprogrammandoli. Ogni programma per pic inizia
con una intestazione in cui si dichiara, oltre al tipo di micro usato e
al formato di default dei numeri (decimale, esadecimale ecc...), anche
la configuration word che ne determinera' il funzionamento (specificata
con __CONFIG):
PROCESSOR
16F84a
RADIX
DEC
INCLUDE
"P16F84a.INC"
__CONFIG
1111111110001b
Il significato completo dei singoli bit
della configuration word e' scritto nel datasheet, e varia per ogni
tipo
di micro. Quella qui riportata significa: oscillatore al quarzo, wtd
disabilitato,
power up timer abilitato, protezione programma disabilitata. Se si
vuole
abilitare il wdt si deve mettere a 1 il bit 2 (ricordandosi sempre che
il bit 2 e' il terzo bit a partire da destra!).
ESEMPIO
DI PROGRAMMA
Il seguente e' un semplice esempio di
programma completo. Funzionalmente non fa altro che leggere i 3 stati
logici
presenti sugli ingressi RB0..RB2 e trasferirli pari pari sulle
uscite
RA0..RA2.
;-----------------------------------------------------------------------
;
TEST1.ASM
- Programma di test per PIC
;-----------------------------------------------------------------------
;
RIEPILOGO
USO PORTE:
;
; RA0
out
Uscita 0
; RA1
out
Uscita 1
; RA2
out
Uscita 2
; RA3
out
Non usato, sempre 0
; RA4
out(oc)
Non usato, sempre 0
;
; RB0
in(p-up)
Ingresso 0
; RB1
in(p-up)
Ingresso 1
; RB2
in(p-up)
Ingresso 2
; RB3
in(p-up)
Non usato
; RB4
in(p-up)
Non usato
; RB5
in(p-up)
Non usato
; RB6
in(p-up)
Non usato
; RB7
in(p-up)
Non usato
;-----------------------------------------------------------------------
;
DEFINIZIONI
;-----------------------------------------------------------------------
PROCESSOR 16F84a
;clock 4 Mhz
RADIX DEC
INCLUDE "P16F84a.INC"
__CONFIG 1111111110001b
#define
Bank0 bcf STATUS,RP0
#define
Bank1 bsf STATUS,RP0
;-----------------------------------------------------------------------
;
PROGRAMMA
;-----------------------------------------------------------------------
ORG 0
goto inizio
;----------INTERRUPT
HANDLER (se usato)
ORG 4
...
;qui vanno le eventuali istruzioni
...
;per la gestione degli interrupt
;----------PREDISPOSIZIONE HARDWARE
inizio
Bank1
;attiva il banco 1
clrf
TRISA
;Predispone porta A come uscite
bcf OPTION_REG,7 ;Attiva
pull-ups
su porta B
Bank0
;attiva il banco 0
;----------CICLO PRINCIPALE DEL PROGRAMMA
mainloop
movf
PORTB,w
;legge porta B
andlw 00000111B
;maschera
i 3 bit inferiori
movwf
PORTA
;li scrive sulla porta A
goto
mainloop
;ripete il ciclo
;-----------------------------------------------------------------------
END
LOOP
Un loop (ciclo) puo' essere realizzato
in modo semplice se il numero di iterazioni non e' maggiore di 256. In
questo caso basta un registro a 8 bit come contatore (Impostando 0 in
contat
il si ottengono 256 iterazioni):
contat EQU 0CH
movlw 30
movwf contat ;predispone 30 iterazioni
ciclo
...
...
...
decfsz contat,f ;decrementa contat, skip se zero
goto ciclo ;ritorna a ciclo se non
zero
Se occorrono piu' di 256 iterazioni si
devono usare piu' di registri. Per esempio con due registri (contenenti
le parti alta e bassa di un numero a 16 bit) si possono realizzare fino
a 65536 iterazioni:
lcont
EQU 0CH
hcont
EQU 0DH
movlw 85
movwf lcont
movlw 4
movwf hcont ;predispone 1109 iterazioni
ciclo
...
...
...
decf lcont,f ;dec parte bassa
incf lcont,w ;incr. per controllare se torna a
0
btfsc STATUS,Z ;skip se non tornato a zero
decf hcont,f ;se tornato a zero decrementa hcont
movf lcont,w ;carica lcont
iorwf hcont,w ;mette in or con hcont
btfss STATUS,Z ;se tutto zero termina
goto ciclo ;altrimenti next
Impostando 0 sia in lcount che in
hcount
si ottengono 65536 iterazioni.
LOOKUP
TABLE (TABELLE DATI)
Usando le istruzioni addwf e retlw e'
possibile creare delle tabelle dati nel programma leggibili con un
indice.
E' infatti permesso sommare un valore alla parte bassa del program
counter
(PCL), quindi basta impostare in W l'indice dell'elemento voluto e fare
una call alla tabella. L' indice parte da 0 (per il primo elemento) e
puo'
andare fino a 254. Bisogna ricordare che l'istruzione addwf lavora solo
su 8 bit e non e' in grado di aggiornare la parte alta del program
counter,
questo significa che la memoria programma puo' essere pensata come
composta
da 4 pagine da 256 byte ciascuna... le tabelle non devono percio'
"sconfinare"
dai bordi delle pagine. Inoltre va anche ricordato che ad ogni addwf la
parte alta del prog.counter viene caricata con il valore del registro
PCLATH
(presente all'indirizzo dati 0AH), e pertanto prima di chiamare una
tabella
questo registro va impostato a seconda della pagina in cui risiede la
tabella
stessa.
table1
addwf PCL,f
retlw 126
retlw 0
retlw 44
retlw 255
retlw 188
....
movlw .... ;pagina della tabella
movwf PCLATH
movlw 4 ;punta il
5° elemento
call table1 ;acquisisce in W il valore
;letto dalla tabella (188)
Indirizzi | PCLATH |
000H - 0FFH | 0 |
100H - 1FFH | 1 |
200H - 2FFH | 2 |
300H - 3FF | 3 |
Se si vuole usare un registro come
puntatore
(per esempio PTAB) agli elementi della tabella possiamo generalizzare
la
chiamata includendo nella tabella stessa anche l'impostazione del
PCLATH
(in questo caso l'indice puo' arrivare al massimo a 251):
PTAB
EQU 0CH
table1
movlw .... ;pagina
movwf PCLATH
movf PTAB,w
addwf PCL,f
retlw 126
retlw 0
retlw 44
retlw 255
retlw 188
....
movlw 2 ;carica 2
nel registro puntatore
movwf PTAB
call table1 ;acquisisce in W il valore 44
RITARDI
SOFTWARE
In alcuni programmi puo' essere necessario
regolare con precisione la durata temporale di una routine software,
inserendo
qua e la delle apposite istruzioni che hanno l'unico scopo di creare un
piccolo ritardo. Usando l'istruzione NOP e' possibile inserire un
ritardo
di 1µS (con clock di 4Mhz), se serve un ritardo di 2µS
possono
essere scritte due NOP una dietro l'altra, oppure, per risparmiare
memoria
programma, si puo' usare una goto fittizia che salta all'istruzione
successiva
(una goto infatti dura sempre 2µS e occupa una sola locazione
della
memoria programma... l'uso delle goto fittizie e' pero' uno stile di
programmazione
un po' scorretto, e va usato solo se e' assolutamente necessario
risparmiare
quelle poche locazioni di memoria, altrimenti e' sicuramente
preferibile
usare due NOP):
Ritardo
1µS:
nop
Ritardo
2µS:
nop
nop
oppure:
goto $+1
Ritardi maggiori possono essere
ottenuti
con combinazioni di NOP e goto fittizie. Quando si arriva ai 7µS
di ritardo diventa conveniente usare un loop, con il quale si possono
realizzare
ritardi di centinaia di µS. Il ciclo formato dalle seguenti 4
istruzioni
per esempio impiega 301µS per essere eseguito da un PIC cloccato
a 4 Mhz:
movlw 100
movwf contat ;predispone 100 iterazioni
ciclo
decfsz contat,f ;decrementa contat, skip se zero
goto ciclo ;prossimo ciclo se non
zero
Da dove saltano fuori i 301µS? Le
prime 2 istruzioni durano 1 µS ciascuna, poi il decremento e il
goto
vengono eseguiti 99 volte, e il decremento saltando il goto una sola
volta
all'ultimo ciclo. Quando il decremento non da risultato 0 dura 1
µS,
seguito dal goto che dura 2 µS, quando invece il decremento da
come
risultato 0 dura 2 µS e il goto e' saltato... quindi:
µS
= 2 + 3*(n-1) + 2 = 2 + 3*99 + 2 = 301
Se vogliamo sapere che valore dobbiamo
dare al registro contatore per ottenere i µS desiderati
basta
fare:
n
= ( µS - 1 ) / 3
infatti se vogliamo 301 µS allora n = (301-1)/3 = 100
Si puo' notare che con il ciclo non e'
possibile ottenere 302 e 303 µS in quanto dando il valore 101 al
contatore otteniamo gia' 304µS. Nel caso si desiderassero i
302µS
si scrive una NOP prima o dopo del ciclo, se si desiderassero i
303µS
si puo' usare una goto fittizia:
goto $+1 ;goto fittizia
2 cicli
movlw 100
movwf contat ;predispone 100 iterazioni
ciclo
decfsz contat,f ;decrementa contat, skip se zero
goto ciclo ;prossimo ciclo se non
zero
[Precedente] [Indice principale] [Seguente]
|
|