Vediamo ora un esempio pratico di gestione
degli interrupt. Prendiamo come base di partenza il source LED.ASM
usato nella lezione 1 per realizzare il lampeggiatore a
led.
Come ricorderete questo programma fa semplicemente
lampeggiare il LED1, presente sulla scheda PicTech, a ciclo continuo utilizzando un
ritardo software introdotto dalla subroutine Delay.
Vediamo ora come è possibile fargli rilevare la pressione
di un tasto ed accendere il LED 2 contemporaneamente all'esecuzione del programma
principale.
Il source d'esempio che andremo ad analizzare è
disponibile nel file INTRB.ASM
Proviamo a compilarlo ed a eseguirlo sulla scheda PicTech.
I collegamenti da effettuare sulla scheda PicTech sono gli stessi collegamenti della
lezione precedente ovvero:
RB0-LED1
RB1-LED2
RB2-LED3
RB3-LED4
RB4-PU1
RB5-PU2
RB6-PU3
RB7-PU4
Una volta scaricato il programma INTRB.ASM nella scheda PicTech noteremo che il LED
1 lampeggia esattamente come avveniva con il programma LED.ASM. Proviamo ora a premere uno qualsiasi dei tasti da SW1
a SW4 e vedremo che il LED 2 si accende immediatamente e
rimane acceso per un tempo pari a 3 lampeggi del LED 1.
In pratica mentre il loop principale, derivato dal vecchio LED.ASM, continua a far lampeggiare il LED 1 utilizzando un
ritardo software introdotto dalla subroutine Delay, il PIC è in grado di
accorgersi della pressione di un tasto e di segnalarlo immediatamente sul LED 2
senza influenzare in maniera evidente la frequenza di lampeggio di LED1.
Prima di analizzare il source INTRB.ASM vediamo la differenza di comportamento con un
altro source che effettua le stesse operazioni ma senza ricorrere agli interrupt.
A questo proposito compiliamo ed inseriamo nella scheda
PicTech il programma NOINTRB.ASM. Noteremo che
l'accensione del LED 2, in corrispondenza alla pressione di un tasto, è leggermente
ritardata in quanto la lettura dello stato delle linee RB4-7 non viene effettuata
dall'hardware di gestione dell'interrupt ma direttamente dal programma principale ad ogni
ciclo di loop. Il leggero ritardo è quindi dovuto alla presenza della subroutine Delay
all'interno del loop principale.
Analizziamo ora il source
INTRB.ASM.
Partiamo dalla direttiva ORG 00H che, come
sappiamo serve a posizionare il nostro programma a partire dalla locazione di reset,
ovvero dalla locazione con indirizzo 0.
Notiamo subito che la prima istruzione che incontra il PIC
è un salto incondizionato alla label Start:
ORG 00H
goto Start
seguito da un'altra direttiva:
ORG 04H
e quindi dal codice della subroutine di gestione
dell'interrupt:
bsf PORTB,LED2
movlw 3
movwf nTick
bcf INTCON,RBIF
retfie
Come abbiamo detto nella lezione precedente, l'interrupt
handler deve necessariamente essere allocato a partire dall'indirizzo 04H, quindi per
evitare che venga eseguito al reset dobbiamo necessariamente saltarlo con una istruzione
di salto incondizionato.
Il codice dell'interrupt handler, in questo caso, è molto
semplice e si limita ad accendere il LED 2, quindi inserire nel registro utente nTick
il numero di lampeggi raggiunto il quale il LED 2 deve spegnersi e quindi azzerare il flag
RBIF per consentire alla circuiteria di generazione dell'interrupt di
continuare a funzionare.
L'istruzione RETFIE consente al PIC di
tornare ad eseguire il programma interrotto dall'interrupt.
Ma perchè viene generato un
interrupt quando premiamo un tasto qualsiasi ?
Tra le prime istruzioni che esegue il nostro PIC al reset
troviamo le seguenti:
movlw 10001000B
movwf INTCON
dove in pratica viene messo ad uno il bit GIE
(bit 7) che abilita in generale la circuiteria di generazione degli interrupt e quindi il
bit RBIE (bit 3) che abilita, in particolare, l'interrupt su cambiamento
di stato delle linee RB4-7.
In pratica, avendo collegato i pulsanti PU1, PU2, PU3 e PU4
proprio sulle linee di I/O RB4, RB5, RB6 ed RB7, con la pressione di uno di questi
otteniamo un cambiamento di stato e quindi un interrupt.
Nel loop principale, oltre alle operazioni di accensione e
spegnimento del LED 1, viene decrementato il contatore nTick fino al
raggiungimento dello zero. In corrispondenza di questo viene spento il LED 2. |