Programmare in mikroBasic
 
  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  

 
Privacy Policy Cookie Policy