3° progetto (PIC18F45K50) – Lampeggio LED con interruput

Prima di passare alla realizzazione di questo progetto vi rimando alla teoria relativa agli interrupt (qui). Questo renderà più facile e agevole la vostra comprensione del tutto.

Progetto completo.

Fasi realizzazione progetto (dopo la sua creazione).

  1. Configurazione del PIC
  2. Stesura del codice:
    1. Creazione del ciclo while infinito
    2. Settaggio iniziale (pin e dispositivi)
    3. Progettazione e stesura del programma
    4. Verifica del codice e programmazione del PIC
  3. Montaggio del circuito elettrico
  4. Test su breadboard

Configurazione del PIC.

Questa può essere fatta tramite il tool descritto nel primo progetto (qui) o configurando manualmente cioè ‘scrivendo a mano’ soltanto le configurazioni cambiate.

Stesura del codice.

Creazione del ciclo while infinito.

Per funzionare, il programma ha bisogno di un while infinito entro cui noi andremo a scrivere le istruzioni che verranno svolte in continuazione.

void main(void){
    while(1){
    }
}
Settaggio iniziale (pin e dispositivi).
PINComponente
RD1+ (LED)

Questo progetto necessita, come abbiamo detto nella parte iniziale dell’articolo, di un TIMER (nel nostro caso il TIMER0) che verrà utilizzato in interrupt e ci servirà a dettare i tempi di ritardo del lampeggio. Le configurazioni del TIMER0 andranno inserite ‘insieme’ a quelle dell’oscillatore ed a quelle del settaggio dei pin. I registri che ci serviranno per impostarlo sono i seguenti:

  • RCON – Registro che contiene la possibilità di abilitare gli interrupt su uno o due livelli di priorità;
  • INTCON – Registo che contiene le configurazioni principali degli interrupt, fra cui l’abilitazione globale o l’abilitazione degli interrupt sulle periferiche. Contiene inoltre l’abilitazione al TIMER0 (TMR0IE) e il suo flag che viene settato ogni volta che si è verificato un interrupt (TMR0IF).
  • T0CON – Registro che contiene tutte le impostazioni del TIMER0, in particolare alcuni parametri saranno fondamentali per scandire il tempo ogni quanto si verificherà un interrupt;
  • TMR0L – Registro che contiene il valore del TIMER0, supposto questo a 8 bit.

La prima cosa da fare per setttare l’interrupt è disabilitare la priorità (che in questo caso non serve) nel registro RCON RCONbits.IPEN = 0;.

Fatto questo possiamo andare ad abilitare il nostro interrupt, servendoci del registro INTCON:

// Interrupt globali abilitati
INTCONbits.GIE = 1;
// Interrupt sul TIMER0 abilitato
INTCONbits.TMR0IE = 1;

Non manca ora che settare il nostro TIMER0. Esistono diversi tool in rete che ci permettono di configurare il tempo di interrupt del TIMER0, evitando così la fatica di svolgere calcoli leggermente complessi. Il mio consiglio è di utilizzare il seguente tool, nonostante produca un codice utilizzato da un vecchio compilatore.

Noi genereremo un’interrupt ogni 1ms, che andrà ad incrementare un variabile contatore (Tempo) che verrà controllata continuamente nel main.

// TIMER0
// Registro di configurazione del timer0 (riferimento al datasheet)
T0CON = 0xD3;
//Valore iniziale del TIMER0
TMR0L = 6;

Con queste configurazioni:

  • Abilitiamo il TIMER0;
  • Utilizziamo il timer in modalità a 8 bit;
  • Il clock che determina l’incremento del valore del timer deriva dal clock interno del PIC diviso 4 (FOSC/4), che nel nostro caso risulta essere 4MHz;
  • Ci serviamo di un prescaler 1:16, un divisore del clock realtivo al TIMER0

Impostando il valore iniziale del TIMER a 6 abbiamo un interrupt esattamente ogni 1ms.

Progettazione e stesura del programma.

L’interrupt per funzionare necessita di una sua apposita routine, che deve essere posta al di sotto del main:

void main(void){
    ...
    while(1){
        ...
    }
}

void interrupt NomeInterrupt(void){
    // Routine di interrupt
}

All’interno di questa routine andiamo a controllare quale ‘fonte’ abbia generato l’interrupt. Per fare questo dobbiamo servirci di numerosi ife dei flag relativi agli interrupt utilizzati.

FLAG DEGLI INTERRUPT :

Sono bit di alcuni registri che vengono settati a 1 quando si è verificato un interrupt, per esempio quando abbiamo un interrupt sul TIMER0 il suo flag TMR0IFverrà settato a 1. La maggior parte di questi flag non torna a 0 in maniera automatica ma necessita di un settaggio manuale, quindi, al fine di evitare problemi, al termine di ogni ifriportiamo il flag relativo a 0.

Ecco proposto un piccolo esempio:

void interrupt InterruptRoutine (void){
    // Se l'interrupt è stato causato dal TIMER0
    if(INTCONbits.TMR0IF == 1){
        // Disabilito gli interrupt
        INTCONbits.GIE = 0;
        ...
        // Azzero il flag dell'interrupt
        INTCONbits.TMR0IF = 0;
        // Abilito nuovamente gli interrupt
        INTCONbits.GIE = 1;
    }
}

N.B. Nell’esempio proposto ad ogni interrupt verificatosi, disabilitiamo totalmente gli interrupt per fare in modo che la routine relativa venga eseguita completamente e che non venga interrotta da un altro interrupt.

Per quanto riguarda la realizzazione del nostro progetto all’interno di questa routine non resta che aggiungere l’incremento della nostra variabile Tempo.

La variabile Tempo verrà controllata e azzerata nel main in questo modo:

while (1) {
    // Se sono passati 500ms (mezzo secondo)
    if (Tempo == 500) {
        // Inverto lo stato del pin RD1
        PORTDbits.RD1 = !PORTDbits.RD1;
        // Azzero la variabile tempo
        Tempo = 0;
    }            
}

Così facendo abbiamo ottenuto il lapeggio desiderato e siamo riusciti a comprendere una piccola parte del mondo degli interrupt.

Verifica del codice e programmazione del PIC.

Una breve ricontrollata generale a tutto il codice unita a una buona riuscita nella compilazione del progetto ci permetteranno poi di programmare il nostro microcontrollore.

Montaggio del circuito elettrico.

Fatto questo non ci resta altro che montare il circuito.

 

Mi raccomando prestate particolare attenzione alle varie alimentazioni perchè la mancata attenzione su ciò potrebbe portare alla rottura di diversi componenti.

Test su breadboard.

 

Download.

La cartella del progetto completo, compilato (con XC8 v.1.42) e funzionante la potete scaricare qui  PIC18F45K50_LampeggioLED-Interrupt.X

Lascia un commento