[Precedente]
[Indice principale] [Seguente]
[Confronto tra numeri a 8 bit] [Ricezione
seriale] [Loop lunghi]
CONFRONTO
TRA NUMERI A 8 BIT
In
un programma puo' essere necessario confrontare due valori per
stabilire
quale dei due e' maggiore (o minore) dell'altro , o se sono uguali, o
tutte le altre
combinazioni
possibili (che in tutto sono 6). Il confronto viene effettuato
facendone
la sottrazione e verificando poi lo stato dei flags C e Z.
Infatti durante una sottrazione viene
settato
il flag Z nel caso in cui il risultato sia 0, e resettato il flag C nel
caso in cui si verifichi un prestito. Esistono due istruzioni di
sottrazione,
la prima e' sublw (dal valore specificato viene sottratto
l'accumulatore),
la seconda e' subwf (dalla variabile specificata viene sottratto
l'accumulatore):
SUBLW
45
= W = 45 - W
SUBWF var,W
= W = var - W
SUBWF
var,F
= var = var - W
Facendo la sottrazione si puo' pensare nei termini di: confronto il valore con quello dell'accumulatore, per vedere se l'accumulatore e' maggiore, minore, uguale ecc...
Condizioni | Impostazione dei flags |
W = var
(uguale) W <> var (diverso) W > var (maggiore) W < var (minore) W >= var (maggiore o uguale) W <= var (minore o uguale) |
Z=1 Z=0 C=0 Z=0 and C=1 Z=1 or C=0 C=1 |
Come si puo' vedere la
condizione
di uguaglianza e' segnalata dal flag Z settato (il C in questo caso e'
irrilevante) e quella di disuguaglianza dal flag Z resettato,
pertanto puo' essere semplicemente testata con le istruzioni btfss o
btfsc. Le condizioni "minore" e "maggiore o uguale" sono
invece abbastanza complesse da codificare per il fatto che devono
essere tenuti in considerazione entrambi i flags C e Z, ma il lavoro in
pratica si semplifica scambiando l'ordine degli operandi nel seguente
modo:
Se devo verificare se A>B faccio B-A, se C vale 0 la condizione e' vera. |
Se devo verificare se A<B faccio A-B, se C vale 0 la condizione e' vera. |
Se devo verificare se A<=B faccio B-A, se C vale 1 la condizione e' vera. |
Se devo verificare se A>=B faccio A-B, se C vale 1 la condizione e' vera. |
ESEMPI:
;IF pippo>26 THEN GOTO label
MOVF pippo,W
SUBLW 26
BTFSS STATUS,C
GOTO label
;IF pippo<120 THEN GOTO label
MOVLW 120
SUBWF pippo,W
BTFSS STATUS,C
GOTO label
;IF pippo<=pluto THEN GOTO label
MOVF pippo,W
SUBWF pluto,W
BTFSC STATUS,C
GOTO label
;IF pippo>=pluto THEN GOTO label
MOVF pluto,W
SUBWF pippo,W
BTFSC STATUS,C
GOTO label
RICEZIONE
SERIALE
Similmente
a quanto visto per la trasmissione seriale software e' possibile
realizzare
un ricevitore seriale che acquisisce un byte dal PC e lo presenta in
formato
binario sui pin RB0..RB7 (questa volta configurati come uscite). Questo
circuito puo' essere utile a tutti coloro che hanno bisogno di un
convertitore
seriale/parallelo per comandare attraverso la porta seriale fino a 8
carichi
indipendenti come ad esempio dei rele'.
Lo schema del circuito e' riportato nella figura seguente. I pin RB0..RB7 sono le uscite, il pin RA0 e' l'ingresso da cui si ricevono i dati attraverso un transistor adattatore di livello EIA/TTL. Il terminale chiamato TX e' la trasmissione del PC (in caso di dubbi sulla piedinatura della porta seriale o sul formato dei dati vedere l'apposita pagina).
Il
programma
del PIC: rxser.asm Include per pic16f84a: P16F84a.INC L'eseguibile: RXSER.HEX |
Il programma provvede innanzitutto a configurare la porta B come uscita, avendo l'accortezza di precaricare 0 nel registro di uscita (portb) prima di renderla un'uscita. In questo modo all'istante dell'accensione questi pin sono in alta impedenza e subito dopo diventano delle uscite a zero senza glitch, cioe' senza stati incerti della durata di qualche microsecondo che potrebbero creare falsi comandi verso l'esterno, e questo permette di pilotare tranquillamente dei comuni transistor npn (o array di transistor integrati come gli ULN2003) come indicato nello schema seguente:
Il formato di ricezione e' asincrono start-stop 9600 8-N-1. Gli unici controlli effettuati sulla corretteza dei dati sono ll valore del bit di start (che deve essere 0) e quello del bit di stop (che deve essere 1). I byte non corretti vengono ignorati, quelli corretti vengono portati sull'uscita.
Togliendo il transistor adattatore di livello sia da questo circuito che da quello del trasmettitore e' possibile collegare tra loro due pic (uno trasmettitore e l'altro ricevitore) e fare in modo di portare sulle uscite dell'uno i valori in ingresso dell'altro (puo' servire per esempio per trasferire su due soli fili lo stato di 8 segnali digitali)... attenzione pero' che questo sistema non e' ad alta affidabilita', e percio' e' adatto solo per scopi didattici o dove la presenza di errori di trasmissione e' una cosa accettabile.
LOOP
CON ALTO NUMERO DI CICLI
Come
gia' detto nel paragrafo sui loop, con un registro a 8 bit si puo'
realizzare
un numero di cicli massimo di 256 iterazioni. Con combinazioni di
registri,
o con loop nidificati uno dentro l'altro, si puo' raggiungere un numero
di iterazioni qualsiasi, con lo scotto pero' di dover scrivere una
notevole
quantita' di istruzioni solo per il controllo del ciclo (ben 8 per un
ciclo
da 65536 iterazioni massime, realizzato quindi con 2 registri da 8
bit).
Ancora una volta ci vengono incontro le macro, infatti quelle 8
istruzioni
possono essere racchiuse in un'unica macroistruzione chiamata per
esempio
Djnz16 (decrementa una variabile a 16 bit e salta se non e' arrivata a
0):
Djnz16
macro var,addr
decf var,f ;dec parte bassa
incf var,w ;incr. per controllare
se
torna a 0
btfsc STATUS,Z ;skip se non tornato a zero
decf var+1,f ;altrimenti decrementa parte alta
movf var,w ;carica parte bassa
iorwf var+1,w ;mette in or con parte alta
btfss STATUS,Z ;se tutto zero termina
goto addr ;altrimenti next
endm
Per realizzare un ciclo a 16 bit con
questa
macro dobbiamo riservare 2 byte per una variabile di conteggio,
chiamata
ad esempio cont:
ORG 0CH
cont RES 2
Poi dobbiamo assegnare ai suoi 2 byte
il valore che ci interessa, per esempio per 25000 iterazioni abbiamo 97
come parte alta e 168 come parte bassa (256*97+168=25000), possiamo
percio'
caricare i due valori in cont ricordandoci che all'indirizzo piu' basso
va messa la parte bassa. L'esempio seguente mostra come realizzare
questo
loop a 16 bit:
movlw 168
movwf cont
movlw 97
movwf cont+1
label
.....
.....
Djnz16 cont,label
Allo stesso modo possiamo anche pensare
ad una macro per un loop a 24 bit (che puo' eseguire fino a
16.777.216
iterazioni):
Djnz24
macro var,addr
decf var,f ;dec parte bassa
incfsz var,w ;incr. per controllare se torna a
0
goto $+5
decf var+1,f ;decrementa parte media
incf var+1,w ;incr. per controllare se torna a
0
btfsc STATUS,Z ;skip se non tornato a zero
decf var+2,f ;se tornato a zero decrementa
parte
alta
movf var,w ;carica parte bassa
iorwf var+1,w ;mette in or con parte media
iorwf var+2,w ;mette in or con parte alta
btfss STATUS,Z ;se tutto zero termina
goto addr ;altrimenti next
endm
L'esempio seguente realizza un ciclo di
900000 iterazioni usando la macroistruzione djnz24:
ORG 0CH
cont RES 3
;riserva 3 byte per il contatore
movlw 160
movwf cont
;carica parte bassa
movlw 187
movwf cont+1 ;carica
parte
media
movlw 13
movwf cont+2 ;carica
parte
alta
label
.....
.....
Djnz24 cont,label ;decrementa e salta a label se non
0
Per quanto riguarda i tempi di esecuzione come gia' detto si calcolano considerando che al posto della macro ci siano scritte le istruzioni in essa contenute.
Per scrivere poi piu' comodamente le
assegnazioni
di valori a variabili a 8,16 e 24 bit possiamo scrivere altre tre macro:
Ldf
macro var,n
movlw n
movwf var
endm
Ldf16
macro var,n2,n1
movlw n1
movwf var
movlw n2
movwf var+1
endm
Ldf24
macro var,n3,n2,n1
movlw n1
movwf var
movlw n2
movwf var+1
movlw n3
movwf var+2
endm
Queste ci consentono di assegnare un
valore
a 8,16 o a 24 bit con un'unica istruzione. Per esempio, se nel nostro
contatore
a 16 bit vogliamo caricare 25000 e in quello a 24 bit 900000 possiamo
scrivere:
Ldf16 cont,97,168
Ldf24 cont,13,187,160
I vari valori vanno scritti dal piu'
significativo
(parte alta) al meno significativo (parte bassa), in questo modo e'
anche
semplice determinarli scrivendone le doppiette esadecimali:
25000 = 61A8 Ldf16 cont,61H,0A8H
900000 = 0DBBA0 Ldf24 cont,0DH,0BBH,0A0H
...e la scrittura di un ciclo da 8, 16
o 24 bit richiede sempre solo due righe di programma:
Ldf cont,165 ;165 iterazioni
label
....
Djnz cont,label
Ldf16 cont,44,0 ;11264 iterazioni
label
....
Djnz16 cont,label
Ldf24 cont,8,0,133 ;524421 iterazioni
label
....
Djnz24 cont,label
[Precedente]
[Indice principale] [Seguente]
Pagina e disegni By Claudio Fin 2001
Ultimo aggiornamento 11-4-2004
|
|