|
|
Box |
Uso dell'interrupt
(parte 5)
Sommario
|
|
|
Per le informazioni riferite a questo argomento e per compilare i programmi è stata usata la vers. 7.0.0.2 di mikroBasic.
Altre versioni del compilatore potrebbero avere comportamenti diversi o non funzionare. |
Interrupt nel PIC12F675
Alcune caratteristiche dei PIC12F675 (PIC12F629).
12F... |
Pin |
Flash |
RAM |
Eeprom |
I/O |
Timer |
Clock
interno |
CCP |
ADC |
Comp |
Usart |
LVP |
Costo |
629 |
8 |
1k |
64 |
128 |
6 |
2 |
4MHz |
No |
- |
1 |
- |
No |
€1,45 |
675 |
8 |
1k |
64 |
128 |
6 |
2 |
4MHz |
No |
4 |
1 |
- |
No |
€1,51 |
Vediamo gli interrupt che possono essere gestiti dal PIC12F675 (PIC12F629).
Sorgente di Interrupt
(12F675) |
Registri coinvolti |
Bit di Enable (abilitaz.) |
Bit di Flag (segnalaz.) |
Note |
Cambio stato ingressi GPIO |
INTCON, IOC |
GPIE |
GPIF |
Possibilità di scegliere quali ingressi |
Cambio stato ingresso GPIO.2 |
INTCON, OPTION_REG |
INTE |
INTF |
Possibilità di scegliere fronte di salita o discesa |
Overflow TMR0 (Timer zero) |
INTCON |
T0IE |
T0IF |
|
Overflow TMR1 (Timer 1) |
PIE1, PIR1 |
TMR1IE |
TMR1IF |
|
Cambio stato Comparatore |
PIE1, PIR1 |
CMIE |
CMIF |
|
Conversione A/D completata |
PIE1, PIR1 |
ADIE |
ADIF |
|
Scrittura EEPROM completata |
PIE1, PIR1 |
EEIE |
EEIF |
|
Il PIC12F675 contiene moduli di periferica, quindi sono presenti, oltre al registro INTCON, anche i registri PIE1 e PIR1, che permettono la gestione degli interrupt tramite l'impostazione di alcuni bit specifici.
|
Confrontando il registro INTCON con quello del PIC16F84A, notiamo che il bit 6 ha un'altro nome: PEIE.
Il bit PEIE abilita, se messo a 1, tutte le interruzioni abilitate (non mascherate), dei moduli di periferica.
Se messo a 0, invece, blocca tutte le interruzioni generate dai moduli di periferica.
Dopo un reset o quando viene data alimentazione al circuito, questo bit viene messo a 0.
Il bit GIE ha sempre la funzione di bloccare o sbloccare tutte le interruzioni.
Gli altri bit del registro INTCON hanno le stesse funzioni come viste nel 16F84A (anche se con nomi differenti). |
Il bit EEIE, che abilita l'interruzione su fine scrittura EEprom, che, nel 16F84A, si trovava nel registro INTCON, è stato spostato nel registro PIE1.
Il registro Peripheral Interrupt Enable (PIE1), contiene i bit di abilitazione individuali per gli interrupt dei moduli di periferica.
Se un bit viene messo a 1, verrà abilitato l'interrupt del modulo di periferica associato a quel bit.
Se messo a 0, verrà disabilitato (si dice, anche, mascherato), l'interrupt per quella periferica.
Dopo un reset o quando viene data alimentazione al circuito, tutti i bit sono messi a 0.
Il registro Peripheral Interrupt Flag (PIR1), contiene i bit di flag individuali per gli interrupt dei moduli di periferica. Il bit di flag d'interrupt di una periferica viene messo a 1 quando si verifica una condizione d'interruzione per quella periferica.
Per abilitare una interruzione di un modulo di periferica, non basta abilitarla nel registro PIE1, ma bisogna anche ricordarsi di mettere a 1 il bit PEIE del registro INTCON.
Vediamo ora, in dettaglio, come possiamo gestire e controllare i vari eventi con mikroBasic.
Cambio stato ingressi GPIO
Questo è un interrupt esterno generato dagli ingressi GPIO.0, GPIO.1, GPIO.2, GPIO.3, GPIO.4, GPIO.5 che avviene quando, su almeno uno di questi ingressi, viene riscontrato un cambiamento di stato.
Questo interrupt può risvegliare il PIC dallo stato SLEEP.
Nel registro IOC (Interrupt On Change), tramite i bit da IOC0 a IOC5, si impostano quali ingressi possono generare l'interrupt.
|
|
|
Quando si alimenta il PIC o dopo un reset, i bit di questo registro vengono messi a 0. Quando il bit IOCx è impostato a 1, l'ingresso corrispondente potrà generare l'interrupt.
Quando il bit IOCx è impostato a 0, l'ingresso corrispondente non genererà interrupt.
Per abilitare l'interruzione, bisogna anche impostare a 1 il bit GPIE, nel registro INTCON.
Se qualcuno dei pin GPIO viene configurato come uscita anziché come ingresso, viene automaticamente escluso dalla possibilità di generare una interruzione.
program prova_Int_1
' 12F675 - 8MHz
dim pausa as byte
sub procedure interrupt
if testbit(INTCON,GPIF) then
if testbit(GPIO,1) then
pausa = 1
end if
if testbit(GPIO,2) then
pausa = 0
end if
clearbit(INTCON,GPIF)
end if
end sub
sub procedure pausa500
if pausa = 0 then
delay_ms(500)
else
delay_ms(250)
end if
end sub
main:
CMCON = %00000111 'comparatore off
ANSEL = %00000000 'tutti I/O digitali
GPIO = 0
TRISIO = %000110
IOC = %000110 'scelta ingressi IOC
setbit(INTCON,GPIE) 'interr. port GPIO
setbit(INTCON,GIE) 'abilita tutti interrupt
pausa = 0
while true
setbit(GPIO,0)
pausa500
clearbit(GPIO,0)
pausa500
wend
End.
|
Dopo l'etichetta main, impostiamo GPIO.0 come uscita, GPIO.1 e GPIO.2 come ingressi, il resto come uscite.
Poi impostiamo gli ingressi che devono generare l'interrupt tramite i bit del registro IOC.
Impostiamo a 1 il bit GPIE di INTCON, abilitando le interruzioni sul cambio stato degli ingressi GPIO.
Impostiamo a 1 il bit GIE di INTCON per abilitare tutti gli interrupt.
Facciamo lampeggiare un LED, con cadenza di circa 2 volte al secondo, su GPIO.0.
A questo punto, quando verrà generato un'interruzione qualunque, il programma interromperà l'esecuzione e salterà all'indirizzo del vettore di interrupt dove c'è la sub procedura interrupt ed eseguirà il test del bit GPIF di INTCON.
Se questo bit sarà a 1, si eseguiranno le istruzioni per individuare quale ingresso ha causato l'interrupt.
Se l'ingresso è GPIO.1 il led verrà fatto lampeggiare 4 volte al secondo.
Se l'ingresso è GPIO.2 il led verrà fatto lampeggiare 2 volte al secondo.
Prima di uscire dalla sub interrupt, azzeriamo il bit GPIF di INTCON.
Ora, il programma uscirà dalla sub e riprenderà l'esecuzione da dove era stata interrotta precedentemente. |
Cambio stato ingresso GPIO.2 (GP2/AN2/T0CKI/INT/COUT)
Questo è un interrupt esterno generato dal piedino GP2, che viene causato dal passaggio, da uno stato logico ad un altro, dell'ingresso GPIO.2.
Questo interrupt può risvegliare il PIC dallo stato SLEEP.
E' possibile far agire l'interrupt sia su un fronte di salita (passaggio da 0 a 1) che su un fronte di discesa (passaggio da 1 a 0).
L'una o l'altra modalità viene selezionata attraverso il bit INTEDG del registro OPTION_REG.
Se questo bit viene messo a 1, l'interrupt avviene in corrispondenza di un fronte di salita, mentre, se viene messo a 0, l'interrupt avviene in corrispondenza di un fronte di discesa.
Quando si alimenta il PIC o dopo un reset, questo bit viene messo a 1.
program prova_Int_2
' 12F675 - 8MHz
sub procedure interrupt
if testbit(INTCON,INTF) then 'GPIO.2 int
if testbit(GPIO,0) then
clearbit(GPIO,0)
else
setbit(GPIO,0)
end if
clearbit(INTCON,INTF)
end if
end sub
sub procedure pausa1000
delay_ms(1000)
end sub
main:
CMCON = %00000111 'comparatore off
ANSEL = %00000000 'tutti I/O digitali
GPIO = 0
TRISIO = %000100
setbit(INTCON,INTE) 'abilita interr. GPIO.2
setbit(INTCON,GIE) 'abilita interrupt
while true
setbit(GPIO,1)
pausa1000
clearbit(GPIO,1)
pausa1000
wend
End.
|
Dopo l'etichetta main, impostiamo GPIO.2 come ingresso, il resto come uscite.
Impostiamo a 1 il bit INTE di INTCON, abilitando le interruzioni sul cambio stato dell'ingresso GPIO.2.
Impostiamo a 1 il bit GIE di INTCON per abilitare tutti gli interrupt.
Facciamo lampeggiare un LED, con cadenza di circa 1 secondo, su GPIO.1.
A questo punto, quando verrà generato un'interruzione qualunque, il programma interromperà l'esecuzione e salterà all'indirizzo del vettore di interrupt dove c'è la sub procedura interrupt ed eseguirà il test del bit INTF di INTCON.
Se questo bit sarà a 1, si eseguiranno le istruzioni predisposte.
Prima di uscire dalla sub, azzeriamo il bit INTF di INTCON.
Ora, il programma uscirà dalla sub e riprenderà l'esecuzione da dove era stata interrotta precedentemente. |
Azzeramento di TMR0
Il TMR0 è il registro che tiene il conteggio del Timer0 ed avanza automaticamente durante l'esecuzione di un programma.
Il microcontrollore genera un'interrupt non appena il valore di tale registro supera il limite di 255, ossia al verificarsi del relativo overflow e quindi azzeramento.
Questo interrupt non risveglia il PIC dallo stato SLEEP perchè, in quel caso, il Timer0 viene spento.
program prova_Int_3
' 16F675 - 8MHz
dim conta as byte
sub procedure interrupt
if testbit(INTCON,T0IF) then ' TMR0 int
Inc(conta)
TMR0 = 100
clearbit(INTCON,T0IF)
end if
end sub
main:
CMCON = %00000111 'comparatore off
ANSEL = %00000000 'tutti I/O digitali
GPIO = %111
TRISIO = %000000
OPTION_REG = %11000101 'prescaler 1:64
TMR0 = 100
conta = 0
setbit(INTCON,T0IE) ' TMR0
setbit(INTCON,GIE) 'abilita interrupt
while TRUE
if conta = 200 then
GPIO = not GPIO
conta = 0
end if
wend
end.
|
Dopo l'etichetta main,
impostiamo GPIO, il prescaler e il valore iniziale del registro TMR0.
Impostiamo a 1 il bit T0IE di INTCON, abilitando le interruzioni sull'azzeramento di TMR0.
Impostiamo a 1 il bit GIE di INTCON per abilitare tutti gli interrupt.
Tutta GPIO sarà impostata a 1. Ogni volta che la variabile conta arriva a 200, GPIO verrà invertita di stato.
Il risultato sarà che GPIO lampeggerà con cadenza di circa 1 secondo.
Quando verrà generato un'interruzione qualunque, il programma interromperà l'esecuzione e salterà all'indirizzo del vettore di interrupt dove c'è la sub procedura interrupt ed eseguirà il test del bit T0IF di INTCON.
Se questo bit sarà a 1, verrà incrementata la variabile conta e reimpostato il valore di partenza di TMR0.
Prima di uscire dalla sub, azzeriamo il bit T0IF di INTCON.
Ora, il programma uscirà dalla sub e riprenderà l'esecuzione da dove era stata interrotta precedentemente. |
program prova_Int_6
' 12F675 - 8MHz
sub procedure interrupt
if testbit(PIR1,TMR1IF) then
..... vostre istruzioni
clearbit(PIR1,TMR1IF)
end if
end sub
main:
setbit(PIE1,TMR1IE) 'abil. interr. TMR1
setbit(INTCON,PEIE) 'abil. interr. perif.
setbit(INTCON,GIE) 'abil. tutti interrupt
while TRUE
..... vostre istruzioni
wend
end.
|
Azzeramento di TMR1
Il TMR1 è un registro a 16 bit (TMR1L - TMR1H) che tiene il conteggio del Timer1 ed avanza automaticamente durante l'esecuzione di un programma.
Il microcontrollore genera un'interrupt settando il bit di flag TMR1IF, in PIR1, non appena il valore, di tale registro, supera il limite di 65535, ossia al verificarsi del relativo overflow e quindi azzeramento.
Questo interrupt può risvegliare il PIC dallo stato SLEEP solo se il Timer1 viene fatto funzionare in modo asincrono (clock esterno). |
program prova_Int_11
' 12F675 - 8MHz
sub procedure interrupt
if testbit(PIR1,CMIF) then
..... vostre istruzioni
clearbit(PIR1,CMIF)
end if
end sub
main:
setbit(PIE1,CMIE) 'abil. interr. compar.
setbit(INTCON,PEIE) 'abil. interr. perif.
setbit(INTCON,GIE) 'abil. tutti interrupt
while TRUE
..... vostre istruzioni
wend
end.
|
Interrupt su cambio stato del comparatore
Quando lo stato di uscita del comparatore cambia, viene generato un'interrupt settando il bit di flag CMIF di PIR1. |
program prova_Int_13
' 12F675 - 8MHz
sub procedure interrupt
if testbit(PIR1,ADIF) then
..... vostre istruzioni
clearbit(PIR1,ADIF)
end if
end sub
main:
setbit(PIE1,ADIE) 'abil. interr. conv. A/D
setbit(INTCON,PEIE) 'abil. interr. perif.
setbit(INTCON,GIE) 'abil. tutti interrupt
while TRUE
..... vostre istruzioni
wend
end.
|
Interrupt su completamento conversione A/D
Quando la conversione A/D è stata completata, viene generato un'interrupt settando il bit di flag ADIF di PIR1. |
program prova_Int_5
' 12F675 - 8MHz
dim conta, scrivi as byte
sub procedure interrupt
if testbit(INTCON,INTF) then
clearbit(GPIO,1)
scrivi = 1
clearbit(INTCON,INTF)
else
if testbit(INTCON,T0IF) then 'TMR0 int
Inc(conta)
TMR0 = 100
clearbit(INTCON,T0IF)
else 'EEprom int
if testbit(PIR1,EEIF) then
setbit(GPIO,1)
clearbit(PIR1,EEIF)
end if
end if
end if
end sub
main:
CMCON = %00000111 'comparatore off
ANSEL = %00000000 'tutti I/O digitali
GPIO = 0
TRISIO = %000100
OPTION_REG = %11000101 'prescaler 1:64
TMR0 = 100
conta = 0
scrivi = 0
setbit(INTCON,INTE) 'abil. interr. GP2
setbit(INTCON,T0IE) 'TMR0
setbit(PIE1,EEIE) 'abil. interr. EEprom
setbit(INTCON,PEIE) 'abil. interr. perif.
setbit(INTCON,GIE) 'abil. tutti interrupt
while TRUE
if conta = 200 then
GPIO.0 = not GPIO.0
conta = 0
end if
if scrivi = 1 then
delay_ms(1000)
Eeprom_Write(2, 10)
scrivi = 0
end if
wend
end.
|
Ciclo completo di scrittura su Eeprom
Viene generato un'interrupt settando il bit di flag EEIF di PIR1, appena un programma termina un ciclo normale di memorizzazione su Eeprom.
Dopo l'etichetta main, impostiamo GPIO.2 come ingresso, il resto come uscite.
Impostiamo a 1 i bit INTE, T0IE di INTCON per abilitare gli interrupt visti più sopra.
Impostiamo a 1 anche il bit EEIE di PIE1, abilitando le interruzioni sulla scrittura completata in EEprom.
Impostiamo a 1 anche i bit PEIE e GIE di INTCON per abilitare tutti gli interrupt.
Ogni volta che la variabile conta arriverà a 200, GPIO.0 verrà invertito di stato.
Il risultato sarà che GPIO.0 lampeggerà con cadenza di circa 1 secondo.
Se la variabile scrivi è uguale a 1, si effettuerà la scrittura di un dato in EEprom.
A questo punto, quando verrà generato un'interruzione qualunque, il programma interromperà l'esecuzione e salterà all'indirizzo del vettore di interrupt dove c'è la sub procedura interrupt ed eseguirà il test del bit INTF di INTCON.
Se questo bit sarà a 1, viene impostata a 1 la variabile scrivi, che permetterà la scrittura di un dato in EEprom.
Prima di uscire, azzeriamo il bit GPIF di INTCON.
Oppure eseguirà il test del bit T0IF di INTCON.
Se questo bit sarà a 1, si eseguiranno le istruzioni predisposte per gestire il Timer0.
Prima di uscire, mettiamo a 0 il bit T0IF di INTCON.
Oppure eseguirà il test del bit EEIF di PIR1.
Se questo bit sarà a 1, significa che l'interrupt è stato generato dalla scrittura completata in EEprom e quindi, verrà acceso il LED su GPIO.1.
Prima di uscire, azzeriamo il bit EEIF di PIR1.
Ora, il programma uscirà dalla sub e riprenderà l'esecuzione da dove era stata interrotta precedentemente. |
- Sorgenti mikroBasic per questi appunti
Bibliografia:
Manuale mikroBasic
PICmicro MID-RANGE MCU family - section 8. Interrupts
PIC18C Reference Manual - section 10. Interrupts
Datasheet PIC12F675
Continua nella successiva parte
Ultima modifica
|
|